;;- Machine description for GNU compiler, Motorola 68000 Version
-;; Copyright (C) 1987, 88, 93, 94, 95, 1996 Free Software Foundation, Inc.
+;; Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
;; This file is part of GNU CC.
;; the Free Software Foundation, 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
+;;- Information about MCF5200 port.
+
+;;- The MCF5200 "ColdFire" architecture is a reduced version of the
+;;- 68k ISA. Differences include reduced support for byte and word
+;;- operands and the removal of BCD, bitfield, rotate, and integer
+;;- divide instructions. The TARGET_5200 flag turns the use of the
+;;- removed opcodes and addressing modes off.
+;;-
+
;;- instruction definitions
;;- 'd' one of the data registers can be used.
;;- 'f' one of the m68881 registers can be used
;;- 'r' either a data or an address register can be used.
-;;- 'x' if one of the Sun FPA registers
+;;- 'x' if one of the Sun FPA registers
;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15).
;;- Immediate Floating point operator constraints
;;- 'J' -32768 .. 32767
;;- 'K' all integers EXCEPT -128 .. 127
;;- 'L' -8 .. -1
+;;- 'M' all integers EXCEPT -256 .. 255
+;;- 'N' 24 .. 31
+;;- 'O' 16
+;;- 'P' 8 .. 15
;;- Assembler specs:
;;- "%." size separator ("." or "") move%.l d0,d1
;;- Information about 68060 port.
;;- The 68060 executes all 68030 and 68881/2 instructions, but some must
-;;- be emulated in software by the OS. It is faster to avoid these
-;;- instructions and issue a library call rather than trapping into
+;;- be emulated in software by the OS. It is faster to avoid these
+;;- instructions and issue a library call rather than trapping into
;;- the kernel. The affected instructions are: divs.l <ea>,Dr:Dq;
-;;- divu.l <ea>,Dr:Dq; muls.l <ea>,Dr:Dq; mulu.l <ea>,Dr:Dq, fintrz;
-;;- and fscale. The TARGET_68060 flag turns the use of the opcodes
-;;- off.
-
+;;- divu.l <ea>,Dr:Dq; muls.l <ea>,Dr:Dq; mulu.l <ea>,Dr:Dq; and
+;;- fscale. The TARGET_68060 flag turns the use of the opcodes off.
;;- FPA port explanation:
;; be folded while optimizing anyway.
(define_expand "tstdi"
- [(parallel
- [(set (cc0)
- (match_operand:DI 0 "nonimmediate_operand" "d"))
- (clobber (match_dup 1))])]
+ [(parallel [(set (cc0)
+ (match_operand:DI 0 "nonimmediate_operand" ""))
+ (clobber (match_scratch:SI 1 ""))
+ (clobber (match_scratch:DI 2 ""))])]
""
- "operands[1] = gen_reg_rtx (DImode);")
+ "m68k_last_compare_had_fp_operands = 0;")
(define_insn ""
[(set (cc0)
- (match_operand:DI 1 "nonimmediate_operand" "0"))
- (clobber (match_operand:DI 0 "register_operand" "=d"))]
+ (match_operand:DI 0 "nonimmediate_operand" "am,d"))
+ (clobber (match_scratch:SI 1 "=X,d"))
+ (clobber (match_scratch:DI 2 "=d,X"))]
""
"*
{
- cc_status.flags |= CC_REVERSED;
- return \"neg%.l %R0\;negx%.l %0\";
+ if (which_alternative == 0)
+ {
+ rtx xoperands[2];
+
+ xoperands[0] = operands[2];
+ xoperands[1] = operands[0];
+ output_move_double (xoperands);
+ cc_status.flags |= CC_REVERSED;
+ return \"neg%.l %R2\;negx%.l %2\";
+ }
+ if (find_reg_note (insn, REG_DEAD, operands[0]))
+ {
+ cc_status.flags |= CC_REVERSED;
+ return \"neg%.l %R0\;negx%.l %0\";
+ }
+ else
+ /*
+ ** 'sub' clears %1, and also clears the X cc bit
+ ** 'tst' sets the Z cc bit according to the low part of the DImode operand
+ ** 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part
+ */
+ return \"sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0\";
}")
-(define_insn "tstsi"
+(define_expand "tstsi"
+ [(set (cc0)
+ (match_operand:SI 0 "nonimmediate_operand" ""))]
+ ""
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
[(set (cc0)
(match_operand:SI 0 "nonimmediate_operand" "rm"))]
""
/* ISI's assembler fails to handle tstl a0. */
if (! ADDRESS_REG_P (operands[0]))
#else
- if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
#endif
return \"tst%.l %0\";
/* If you think that the 68020 does not support tstl a0,
;; This can't use an address register, because comparisons
;; with address registers as second operand always test the whole word.
-(define_insn "tsthi"
+(define_expand "tsthi"
+ [(set (cc0)
+ (match_operand:HI 0 "nonimmediate_operand" ""))]
+ ""
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
[(set (cc0)
(match_operand:HI 0 "nonimmediate_operand" "dm"))]
""
"tst%.w %0")
-(define_insn "tstqi"
+(define_expand "tstqi"
+ [(set (cc0)
+ (match_operand:QI 0 "nonimmediate_operand" ""))]
+ ""
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
[(set (cc0)
(match_operand:QI 0 "nonimmediate_operand" "dm"))]
""
"tst%.b %0")
-
+
(define_expand "tstsf"
[(set (cc0)
(match_operand:SF 0 "general_operand" ""))]
"TARGET_68881 || TARGET_FPA"
"
{
+ m68k_last_compare_had_fp_operands = 1;
if (TARGET_FPA)
{
emit_insn (gen_tstsf_fpa (operands[0]));
"TARGET_68881 || TARGET_FPA"
"
{
+ m68k_last_compare_had_fp_operands = 1;
if (TARGET_FPA)
{
emit_insn (gen_tstsf_fpa (operands[0]));
(match_operand:DI 1 "general_operand" "")))
(clobber (match_dup 2))])]
""
- "operands[2] = gen_reg_rtx (DImode);")
+ "m68k_last_compare_had_fp_operands = 0; operands[2] = gen_reg_rtx (DImode);")
(define_insn ""
[(set (cc0)
""
"
{
- if (flag_pic && symbolic_operand (operands[1], SImode))
+ m68k_last_compare_had_fp_operands = 0;
+ if (flag_pic && symbolic_operand (operands[1], SImode))
{
- /* The source is an address which requires PIC relocation.
+ /* The source is an address which requires PIC relocation.
Call legitimize_pic_address with the source, mode, and a relocation
register (a new pseudo, or the final destination if reload_in_progress
is set). Then fall through normally */
}
}")
-;; A composite of the cmp, cmpa, & cmpi m68000 op codes.
+;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
(define_insn ""
[(set (cc0)
(compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>")
- (match_operand:SI 1 "general_operand" "mr,Ksr,>")))]
- ""
+ (match_operand:SI 1 "general_operand" "mr,rKs,>")))]
+ "!TARGET_5200"
"*
{
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
#endif
}")
-(define_insn "cmphi"
+(define_insn ""
+ [(set (cc0)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
+ (match_operand:SI 1 "general_operand" "r,mrKs")))]
+ "TARGET_5200"
+ "*
+{
+ if (REG_P (operands[1])
+ || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ { cc_status.flags |= CC_REVERSED;
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.l %d1,%d0\";
+#else
+ return \"cmp%.l %d0,%d1\";
+#endif
+ }
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.l %d0,%d1\";
+#else
+ return \"cmp%.l %d1,%d0\";
+#endif
+}")
+
+(define_expand "cmphi"
+ [(set (cc0)
+ (compare (match_operand:HI 0 "nonimmediate_operand" "")
+ (match_operand:HI 1 "general_operand" "")))]
+ "!TARGET_5200"
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
[(set (cc0)
(compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
(match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
- ""
+ "!TARGET_5200"
"*
{
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
#endif
}")
-(define_insn "cmpqi"
+(define_expand "cmpqi"
+ [(set (cc0)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "")
+ (match_operand:QI 1 "general_operand" "")))]
+ "!TARGET_5200"
+ "m68k_last_compare_had_fp_operands = 0;")
+
+(define_insn ""
[(set (cc0)
(compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>")
(match_operand:QI 1 "general_operand" "dm,nd,>")))]
- ""
+ "!TARGET_5200"
"*
{
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
"TARGET_68881 || TARGET_FPA"
"
{
+ m68k_last_compare_had_fp_operands = 1;
if (TARGET_FPA)
{
emit_insn (gen_cmpdf_fpa (operands[0], operands[1]));
"TARGET_68881 || TARGET_FPA"
"
{
+ m68k_last_compare_had_fp_operands = 1;
if (TARGET_FPA)
{
emit_insn (gen_cmpsf_fpa (operands[0], operands[1]));
{
operands[0] = adj_offsettable_operand (operands[0],
INTVAL (operands[1]) / 8);
- operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
7 - INTVAL (operands[1]) % 8);
return output_btst (operands, operands[1], operands[0], insn, 7);
}
;; A special case in which it is not desirable
;; to reload the constant into a data register.
-(define_insn ""
+(define_insn "pushexthisi_const"
[(set (match_operand:SI 0 "push_operand" "=m")
(match_operand:SI 1 "const_int_operand" "J"))]
"INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000"
;; Special case of fullword move when source is zero.
;; The reason this is special is to avoid loading a zero
;; into a data reg with moveq in order to store it elsewhere.
-
-(define_insn ""
+
+(define_insn "movsi_const0"
[(set (match_operand:SI 0 "general_operand" "=g")
(const_int 0))]
;; clr insns on 68000 read before writing.
- ;; This isn't so on the 68010, but we have no alternative for it.
- "(TARGET_68020
+ ;; This isn't so on the 68010, but we have no TARGET_68010.
+ "((TARGET_68020 || TARGET_5200)
|| !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))"
"*
{
if (ADDRESS_REG_P (operands[0]))
- return \"sub%.l %0,%0\";
+ {
+ /* On the '040, 'subl an,an' takes 2 clocks while lea takes only 1 */
+ if (!TARGET_68040 && !TARGET_68060)
+ return \"sub%.l %0,%0\";
+ else
+ {
+#ifdef MOTOROLA
+#ifdef SGS
+ /* Many SGS assemblers croak on size specifiers for constants. */
+ return \"lea 0,%0\";
+#else
+ return \"lea 0.w,%0\";
+#endif
+#else
+ return \"lea 0:w,%0\";
+#endif
+ }
+ }
/* moveq is faster on the 68000. */
- if (DATA_REG_P (operands[0]) && !TARGET_68020)
+ if (DATA_REG_P (operands[0]) && (!TARGET_68020 && !TARGET_5200))
#if defined(MOTOROLA) && !defined(CRDS)
return \"moveq%.l %#0,%0\";
#else
return \"clr%.l %0\";
}")
-;; General case of fullword move.
+;; General case of fullword move.
;;
;; This is the main "hook" for PIC code. When generating
;; PIC, movsi is responsible for determining when the source address
;; to perform the actual relocation.
;;
;; In both the PIC and non-PIC cases the patterns generated will
-;; matched by the next define_insn.
+;; matched by the next define_insn.
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
{
- if (flag_pic && symbolic_operand (operands[1], SImode))
+ if (flag_pic && symbolic_operand (operands[1], SImode))
{
- /* The source is an address which requires PIC relocation.
+ /* The source is an address which requires PIC relocation.
Call legitimize_pic_address with the source, mode, and a relocation
register (a new pseudo, or the final destination if reload_in_progress
is set). Then fall through normally */
;; We do allow y and x regs since fixed point is allowed in them.
[(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
(match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
- ""
+ "!TARGET_5200"
"*
{
if (which_alternative == 3)
- return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
+ return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0]))
return \"fpmove%.l %x1,%x0\";
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- if (operands[1] == const0_rtx
- && (DATA_REG_P (operands[0])
- || GET_CODE (operands[0]) == MEM)
- /* clr insns on 68000 read before writing.
- This isn't so on the 68010, but we have no alternative for it. */
- && (TARGET_68020
- || !(GET_CODE (operands[0]) == MEM
- && MEM_VOLATILE_P (operands[0]))))
- return \"clr%.l %0\";
- else if (DATA_REG_P (operands[0]))
- return output_move_const_into_data_reg (operands);
- else if (ADDRESS_REG_P (operands[0])
- && INTVAL (operands[1]) < 0x8000
- && INTVAL (operands[1]) >= -0x8000)
- return \"move%.w %1,%0\";
- else if (push_operand (operands[0], SImode)
- && INTVAL (operands[1]) < 0x8000
- && INTVAL (operands[1]) >= -0x8000)
- return \"pea %a1\";
- }
- else if ((GET_CODE (operands[1]) == SYMBOL_REF
- || GET_CODE (operands[1]) == CONST)
- && push_operand (operands[0], SImode))
- return \"pea %a1\";
- else if ((GET_CODE (operands[1]) == SYMBOL_REF
- || GET_CODE (operands[1]) == CONST)
- && ADDRESS_REG_P (operands[0]))
- return \"lea %a1,%0\";
- return \"move%.l %1,%0\";
+ return output_move_simode (operands);
}")
-(define_insn "movhi"
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=r<>,g")
+ (match_operand:SI 1 "general_operand" "g,r<>"))]
+ "TARGET_5200"
+ "* return output_move_simode (operands);")
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "general_operand" "")
+ (match_operand:HI 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(match_operand:HI 1 "general_operand" "g"))]
- ""
- "*
-{
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- if (operands[1] == const0_rtx
- && (DATA_REG_P (operands[0])
- || GET_CODE (operands[0]) == MEM)
- /* clr insns on 68000 read before writing.
- This isn't so on the 68010, but we have no alternative for it. */
- && (TARGET_68020
- || !(GET_CODE (operands[0]) == MEM
- && MEM_VOLATILE_P (operands[0]))))
- return \"clr%.w %0\";
- else if (DATA_REG_P (operands[0])
- && INTVAL (operands[1]) < 128
- && INTVAL (operands[1]) >= -128)
- {
-#if defined(MOTOROLA) && !defined(CRDS)
- return \"moveq%.l %1,%0\";
-#else
- return \"moveq %1,%0\";
-#endif
- }
- else if (INTVAL (operands[1]) < 0x8000
- && INTVAL (operands[1]) >= -0x8000)
- return \"move%.w %1,%0\";
- }
- else if (CONSTANT_P (operands[1]))
- return \"move%.l %1,%0\";
-#ifndef SGS_NO_LI
- /* Recognize the insn before a tablejump, one that refers
- to a table of offsets. Such an insn will need to refer
- to a label on the insn. So output one. Use the label-number
- of the table of offsets to generate this label. This code,
- and similar code below, assumes that there will be at most one
- reference to each table. */
- if (GET_CODE (operands[1]) == MEM
- && GET_CODE (XEXP (operands[1], 0)) == PLUS
- && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF
- && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS)
- {
- rtx labelref = XEXP (XEXP (operands[1], 0), 1);
-#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
-#ifdef SGS
- asm_fprintf (asm_out_file, \"\\tset %LLI%d,.+2\\n\",
- CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#else /* not SGS */
- asm_fprintf (asm_out_file, \"\\t.set %LLI%d,.+2\\n\",
- CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#endif /* not SGS */
-#else /* SGS_SWITCH_TABLES or not MOTOROLA */
- ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
- CODE_LABEL_NUMBER (XEXP (labelref, 0)));
-#ifdef SGS_SWITCH_TABLES
- /* Set flag saying we need to define the symbol
- LD%n (with value L%n-LI%n) at the end of the switch table. */
- switch_table_difference_label_flag = 1;
-#endif /* SGS_SWITCH_TABLES */
-#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
- }
-#endif /* SGS_NO_LI */
- return \"move%.w %1,%0\";
-}")
+ "!TARGET_5200"
+ "* return output_move_himode (operands);")
+
+ (define_insn ""
+ [(set (match_operand:HI 0 "general_operand" "=r<>,g")
+ (match_operand:HI 1 "general_operand" "g,r<>"))]
+ "TARGET_5200"
+ "* return output_move_himode (operands);")
(define_insn "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
""
"*
{
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- if (operands[1] == const0_rtx
- && (DATA_REG_P (operands[0])
- || GET_CODE (operands[0]) == MEM)
- /* clr insns on 68000 read before writing.
- This isn't so on the 68010, but we have no alternative for it. */
- && (TARGET_68020
- || !(GET_CODE (operands[0]) == MEM
- && MEM_VOLATILE_P (operands[0]))))
- return \"clr%.w %0\";
- }
+ if (operands[1] == const0_rtx
+ /* clr insns on 68000 read before writing.
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
+ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
+ return \"clr%.w %0\";
return \"move%.w %1,%0\";
}")
-(define_insn "movqi"
- [(set (match_operand:QI 0 "general_operand" "=d,*a,m,m,?*a")
- (match_operand:QI 1 "general_operand" "dmi*a,d*a,dmi,?*a,m"))]
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
""
- "*
-{
- rtx xoperands[4];
-
- /* This is probably useless, since it loses for pushing a struct
- of several bytes a byte at a time. */
- if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
- && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx
- && ! ADDRESS_REG_P (operands[1]))
- {
- xoperands[1] = operands[1];
- xoperands[2]
- = gen_rtx (MEM, QImode,
- gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
- /* Just pushing a byte puts it in the high byte of the halfword. */
- /* We must put it in the low-order, high-numbered byte. */
- output_asm_insn (\"move%.b %1,%-\;move%.b %@,%2\", xoperands);
- return \"\";
- }
-
- /* Moving a byte into an address register is not possible. */
- /* Use d0 as an intermediate, but don't clobber its contents. */
- if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM)
- {
- /* ??? For 2.5, don't allow this choice and use secondary reloads
- instead.
-
- See if the address register is used in the address. If it
- is, we have to generate a more complex sequence than those below. */
- CC_STATUS_INIT;
- if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
- operands[1], NULL_RTX))
- {
- /* See if the stack pointer is used in the address. If it isn't,
- we can push d0 or d1 (the insn can't use both of them) on
- the stack, perform our move into d0/d1, copy the byte from d0/1,
- and pop d0/1. */
- if (! reg_mentioned_p (stack_pointer_rtx, operands[1]))
- {
- if (! refers_to_regno_p (0, 1, operands[1], NULL_RTX))
- return \"move%.l %/d0,%-\;move%.b %1,%/d0\;move%.l %/d0,%0\;move%.l %+,%/d0\";
- else
- return \"move%.l %/d1,%-\;move%.b %1,%/d1\;move%.l %/d1,%0\;move%.l %+,%/d1\";
- }
- else
- {
- /* Otherwise, we know that d0 cannot be used in the address
- (since sp and one address register is). Assume that sp is
- being used as a base register and replace the address
- register that is our operand[0] with d0. */
- rtx reg_map[FIRST_PSEUDO_REGISTER];
- int i;
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- reg_map[i] = 0;
-
- reg_map[REGNO (operands[0])] = gen_rtx (REG, Pmode, 0);
- operands[1] = copy_rtx (operands[1]);
- replace_regs (operands[1], reg_map, FIRST_PSEUDO_REGISTER, 0);
- return \"exg %/d0,%0\;move%.b %1,%/d0\;exg %/d0,%0\";
- }
- }
-
- /* If the address of operand 1 uses d0, choose d1 as intermediate. */
- if (refers_to_regno_p (0, 1, operands[1], NULL_RTX))
- return \"exg %/d1,%0\;move%.b %1,%/d1\;exg %/d1,%0\";
- /* Otherwise d0 is usable.
- (An effective address on the 68k can't use two d-regs.) */
- else
- return \"exg %/d0,%0\;move%.b %1,%/d0\;exg %/d0,%0\";
- }
-
- /* Likewise for moving from an address reg. */
- if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM)
- {
- /* ??? For 2.5, don't allow this choice and use secondary reloads
- instead.
-
- See if the address register is used in the address. If it
- is, we have to generate a more complex sequence than those below. */
- CC_STATUS_INIT;
- if (refers_to_regno_p (REGNO (operands[1]), REGNO (operands[1]) + 1,
- operands[0], NULL_RTX))
- {
- /* See if the stack pointer is used in the address. If it isn't,
- we can push d0 or d1 (the insn can't use both of them) on
- the stack, copy the byte to d0/1, perform our move from d0/d1,
- and pop d0/1. */
- if (! reg_mentioned_p (stack_pointer_rtx, operands[0]))
- {
- if (! refers_to_regno_p (0, 1, operands[0], NULL_RTX))
- return \"move%.l %/d0,%-\;move%.l %1,%/d0\;move%.b %/d0,%0\;move%.l %+,%/d0\";
- else
- return \"move%.l %/d1,%-\;move%.l %1,%/d1\;move%.b %/d1,%0\;move%.l %+,%/d1\";
- }
- else
- {
- /* Otherwise, we know that d0 cannot be used in the address
- (since sp and one address register is). Assume that sp is
- being used as a base register and replace the address
- register that is our operand[1] with d0. */
- rtx reg_map[FIRST_PSEUDO_REGISTER];
- int i;
-
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- reg_map[i] = 0;
-
- reg_map[REGNO (operands[1])] = gen_rtx (REG, Pmode, 0);
- operands[0] = copy_rtx (operands[0]);
- replace_regs (operands[0], reg_map, FIRST_PSEUDO_REGISTER, 0);
- return \"exg %/d0,%1\;move%.b %/d0,%0\;exg %/d0,%1\";
- }
- }
+ "")
- if (refers_to_regno_p (0, 1, operands[0], NULL_RTX))
- return \"exg %/d1,%1\;move%.b %/d1,%0\;exg %/d1,%1\";
- else
- return \"exg %/d0,%1\;move%.b %/d0,%0\;exg %/d0,%1\";
- }
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d,*a,m")
+ (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi"))]
+ "!TARGET_5200"
+ "* return output_move_qimode (operands);")
- /* clr and st insns on 68000 read before writing.
- This isn't so on the 68010, but we have no alternative for it. */
- if (TARGET_68020
- || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
- {
- if (operands[1] == const0_rtx)
- return \"clr%.b %0\";
- if (GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) == -1)
- {
- CC_STATUS_INIT;
- return \"st %0\";
- }
- }
- if (GET_CODE (operands[1]) == CONST_INT
- && DATA_REG_P (operands[0])
- && INTVAL (operands[1]) < 128
- && INTVAL (operands[1]) >= -128)
- {
-#if defined(MOTOROLA) && !defined(CRDS)
- return \"moveq%.l %1,%0\";
-#else
- return \"moveq %1,%0\";
-#endif
- }
- if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
- return \"move%.l %1,%0\";
- if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
- return \"move%.w %1,%0\";
- return \"move%.b %1,%0\";
-}")
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=d<>,dm")
+ (match_operand:QI 1 "general_operand" "dmi,d<>"))]
+ "TARGET_5200"
+ "* return output_move_qimode (operands);")
(define_insn "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
{
if (operands[1] == const0_rtx
/* clr insns on 68000 read before writing.
- This isn't so on the 68010, but we have no alternative for it. */
- && (TARGET_68020
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
|| !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
return \"clr%.b %0\";
return \"move%.b %1,%0\";
}")
-(define_insn "movsf"
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
[(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm")
(match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))]
; [(set (match_operand:SF 0 "general_operand" "=rmf")
; (match_operand:SF 1 "general_operand" "rmfF"))]
- ""
+ "!TARGET_5200"
"*
{
if (which_alternative >= 4)
return \"move%.l %1,%0\";
}")
-(define_insn "movdf"
+(define_insn ""
+ [(set (match_operand:SF 0 "general_operand" "=r,g")
+ (match_operand:SF 1 "general_operand" "g,r"))]
+ "TARGET_5200"
+ "* return \"move%.l %1,%0\";")
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn ""
[(set (match_operand:DF 0 "general_operand" "=rm,rf,rf,&rof<>,y,rm,x,!x,!rm")
(match_operand:DF 1 "general_operand" "rf,m,0,rofE<>,rmE,y,xH,rm,x"))]
; [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>")
; (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))]
- ""
+ "!TARGET_5200"
"*
{
if (which_alternative == 7)
return \"fmove%.d %f1,%0\";
}
return output_move_double (operands);
-}
-")
+}")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "general_operand" "=r,g")
+ (match_operand:DF 1 "general_operand" "g,r"))]
+ "TARGET_5200"
+ "* return output_move_double (operands);")
(define_expand "movxf"
[(set (match_operand:XF 0 "nonimmediate_operand" "")
}
")
+(define_expand "movdi"
+ ;; Let's see if it really still needs to handle fp regs, and, if so, why.
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ ""
+ "")
+
;; movdi can apply to fp regs in some cases
-(define_insn "movdi"
+(define_insn ""
;; Let's see if it really still needs to handle fp regs, and, if so, why.
[(set (match_operand:DI 0 "general_operand" "=rm,r,&ro<>,y,rm,!*x,!rm")
(match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))]
; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))]
; [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f")
; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))]
- ""
+ "!TARGET_5200"
"*
{
if (which_alternative == 8)
return \"fmove%.d %f1,%0\";
}
return output_move_double (operands);
-}
-")
+}")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "general_operand" "=r,g")
+ (match_operand:DI 1 "general_operand" "g,r"))]
+ "TARGET_5200"
+ "* return output_move_double (operands);")
;; Thus goes after the move instructions
;; because the move instructions are better (require no spilling)
;; this is the canonical form for (lshiftrt:DI x 32)
(define_insn "zero_extendsidi2"
- [(set (match_operand:DI 0 "general_operand" "ro,<,>")
- (zero_extend:DI (match_operand:SI 1 "general_operand" "rm,rm,rm")))]
+ [(set (match_operand:DI 0 "general_operand" "rm")
+ (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))]
""
"*
{
CC_STATUS_INIT;
- if (which_alternative == 2)
- return \"clr%.l %0\;move%.l %1,%0\";
- if (which_alternative == 1)
- return \"move%.l %1,%0\;clr%.l %0\";
if (GET_CODE (operands[0]) == REG)
operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"move%.l %1,%0\;clr%.l %0\";
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"clr%.l %0\;move%.l %1,%0\";
else
operands[2] = adj_offsettable_operand (operands[0], 4);
if (ADDRESS_REG_P (operands[0]))
{
CC_STATUS_INIT;
operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
- if (TARGET_68020)
+ if (TARGET_68020 || TARGET_5200)
return \"move%.b %1,%2\;extb%.l %2\;smi %0\;extb%.l %0\";
else
return \"move%.b %1,%2\;ext%.w %0\;ext%.l %2\;move%.l %2,%0\;smi %0\";
{
CC_STATUS_INIT;
operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
- if (TARGET_68020)
+ if (TARGET_68020 || TARGET_5200)
return \"move%.w %1,%2\;ext%.l %2\;smi %0\;extb%.l %0\";
else
return \"move%.w %1,%2\;ext%.l %2\;smi %0\;ext%.w %0\;ext%.l %0\";
{
CC_STATUS_INIT;
operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
- if (TARGET_68020)
+ if (TARGET_68020 || TARGET_5200)
return \"move%.l %1,%2\;smi %0\;extb%.l %0\";
else
return \"move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0\";
operands[1] = operands[2];
operands[2] = tmp;
}
- if (TARGET_68020)
- return \"move%.l %2,%3\;add%.l %1,%3\;smi %0\;extb%.l %0\";
+ if (GET_CODE (operands[1]) == REG
+ && REGNO (operands[1]) == REGNO (operands[3]))
+ output_asm_insn (\"add%.l %2,%3\", operands);
else
- return \"move%.l %2,%3\;add%.l %1,%3\;smi %0\;ext%.w %0\;ext%.l %0\";
+ output_asm_insn (\"move%.l %2,%3\;add%.l %1,%3\", operands);
+ if (TARGET_68020 || TARGET_5200)
+ return \"smi %0\;extb%.l %0\";
+ else
+ return \"smi %0\;ext%.w %0\;ext%.l %0\";
}")
(define_insn "extendhisi2"
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "general_operand" "=d")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))]
- "TARGET_68020"
+ "TARGET_68020 || TARGET_5200"
"extb%.l %0")
\f
;; Conversions between float and double.
(define_insn "ftruncdf2"
[(set (match_operand:DF 0 "general_operand" "=f")
(fix:DF (match_operand:DF 1 "general_operand" "fFm")))]
- "TARGET_68881 && !TARGET_68040 && !TARGET_68060"
+ "TARGET_68881 && !TARGET_68040"
"*
{
if (FP_REG_P (operands[1]))
(define_insn "ftruncsf2"
[(set (match_operand:SF 0 "general_operand" "=f")
(fix:SF (match_operand:SF 1 "general_operand" "dfFm")))]
- "TARGET_68881 && !TARGET_68040 && !TARGET_68060"
+ "TARGET_68881 && !TARGET_68040"
"*
{
if (FP_REG_P (operands[1]))
&& GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)
output_asm_insn (\"move%.l %4,%3\", operands);
output_asm_insn (\"move%.l %1,%0\;smi %2\", operands);
- if (TARGET_68020)
+ if (TARGET_68020 || TARGET_5200)
output_asm_insn (\"extb%.l %2\", operands);
else
output_asm_insn (\"ext%.w %2\;ext%.l %2\", operands);
}")
(define_insn "adddi_sexthishl32"
- [(set (match_operand:DI 0 "general_operand" "=o,d,a")
+ [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
(plus:DI (ashift:DI (sign_extend:DI
- (match_operand:HI 1 "general_operand" "rm,rm,rm"))
+ (match_operand:HI 1 "general_operand" "rm,rm,rm,rm"))
(const_int 32))
- (match_operand:DI 2 "general_operand" "0,0,0")))
- (clobber (match_scratch:SI 3 "=&d*a,a*d,X"))]
- ""
+ (match_operand:DI 2 "general_operand" "0,0,0,0")))
+ (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
+ "!TARGET_5200"
"*
{
CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return \"add%.w %1,%0\";
- else if (DATA_REG_P (operands[3]))
- return \"move%.w %1,%3\;ext%.l %3\;add%.l %3,%0\";
- else if (DATA_REG_P (operands[0]))
+ else if (ADDRESS_REG_P (operands[3]))
return \"move%.w %1,%3\;add%.l %3,%0\";
else
- return \"move%.l %0,%3\;add%.w %1,%3\;mov%.l %3,%0\";
+ return \"move%.w %1,%3\;ext%.l %3\;add%.l %3,%0\";
} ")
(define_insn "adddi_dilshr32"
} ")
(define_insn "adddi3"
- [(set (match_operand:DI 0 "general_operand" "=d,<,d,o<>")
- (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0")
- (match_operand:DI 2 "general_operand" "d,<,*ao>,d")))
- (clobber (match_scratch:SI 3 "=X,X,&d,&d"))]
+ [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
+ (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0,0")
+ (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+ (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
""
"*
{
#ifndef NO_ADDSUB_Q
if (INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) <= 8)
- return (ADDRESS_REG_P (operands[0])
- ? \"addq%.w %2,%0\"
- : \"addq%.l %2,%0\");
+ return \"addq%.l %2,%0\";
if (INTVAL (operands[2]) < 0
&& INTVAL (operands[2]) >= -8)
{
operands[2] = gen_rtx (CONST_INT, VOIDmode,
- INTVAL (operands[2]));
- return (ADDRESS_REG_P (operands[0])
- ? \"subq%.w %2,%0\"
- : \"subq%.l %2,%0\");
+ return \"subq%.l %2,%0\";
}
- /* On everything except the 68000 it is faster to use two
- addqw instructions to add a small integer (8 < N <= 16)
- to an address register. Likewise for subqw.*/
- if (INTVAL (operands[2]) > 8
- && INTVAL (operands[2]) <= 16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
+ /* On the CPU32 it is faster to use two addql instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subql. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
{
- operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8);
- return \"addq%.w %#8,%0\;addq%.w %2,%0\";
- }
- if (INTVAL (operands[2]) < -8
- && INTVAL (operands[2]) >= -16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
- {
- operands[2] = gen_rtx (CONST_INT, VOIDmode,
- - INTVAL (operands[2]) - 8);
- return \"subq%.w %#8,%0\;subq%.w %2,%0\";
+ if (INTVAL (operands[2]) > 8
+ && INTVAL (operands[2]) <= 16)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) - 8);
+ return \"addq%.l %#8,%0\;addq%.l %2,%0\";
+ }
+ if (INTVAL (operands[2]) < -8
+ && INTVAL (operands[2]) >= -16)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]) - 8);
+ return \"subq%.l %#8,%0\;subq%.l %2,%0\";
+ }
}
#endif
if (ADDRESS_REG_P (operands[0])
&& INTVAL (operands[2]) >= -0x8000
&& INTVAL (operands[2]) < 0x8000)
- return \"add%.w %2,%0\";
+ {
+ if (TARGET_68040)
+ return \"add%.w %2,%0\";
+ else
+#ifdef MOTOROLA
+ return \"lea (%c2,%0),%0\";
+#else
+ return \"lea %0@(%c2),%0\";
+#endif
+ }
}
return \"add%.l %2,%0\";
}")
(plus:SI (match_operand:SI 1 "general_operand" "0")
(sign_extend:SI
(match_operand:HI 2 "nonimmediate_operand" "rm"))))]
- ""
+ "!TARGET_5200"
"add%.w %2,%0")
(define_insn "addhi3"
[(set (match_operand:HI 0 "general_operand" "=m,r")
(plus:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_operand" "dn,rmn")))]
- ""
+ "!TARGET_5200"
"*
{
-#ifndef NO_ADDSUB_Q
if (GET_CODE (operands[2]) == CONST_INT)
{
+#ifndef NO_ADDSUB_Q
/* If the constant would be a negative number when interpreted as
HImode, make it negative. This is usually, but not always, done
elsewhere in the compiler. First check for constants out of range,
- INTVAL (operands[2]));
return \"subq%.w %2,%0\";
}
- /* On everything except the 68000 it is faster to use two
- addqw instructions to add a small integer (8 < N <= 16)
- to an address register. Likewise for subqw. */
- if (INTVAL (operands[2]) > 8
- && INTVAL (operands[2]) <= 16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
- {
- operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8);
- return \"addq%.w %#8,%0\;addq%.w %2,%0\";
- }
- if (INTVAL (operands[2]) < -8
- && INTVAL (operands[2]) >= -16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subqw. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
{
- operands[2] = gen_rtx (CONST_INT, VOIDmode,
- - INTVAL (operands[2]) - 8);
- return \"subq%.w %#8,%0\;subq%.w %2,%0\";
+ if (INTVAL (operands[2]) > 8
+ && INTVAL (operands[2]) <= 16)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[2]) - 8);
+ return \"addq%.w %#8,%0\;addq%.w %2,%0\";
+ }
+ if (INTVAL (operands[2]) < -8
+ && INTVAL (operands[2]) >= -16)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[2]) - 8);
+ return \"subq%.w %#8,%0\;subq%.w %2,%0\";
+ }
}
- }
#endif
+ if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA
+ return \"lea (%c2,%0),%0\";
+#else
+ return \"lea %0@(%c2),%0\";
+#endif
+ }
return \"add%.w %2,%0\";
}")
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
(plus:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn,rmn")))]
- ""
+ "!TARGET_5200"
"*
{
-#ifndef NO_ADDSUB_Q
if (GET_CODE (operands[1]) == CONST_INT)
{
+#ifndef NO_ADDSUB_Q
/* If the constant would be a negative number when interpreted as
HImode, make it negative. This is usually, but not always, done
elsewhere in the compiler. First check for constants out of range,
- INTVAL (operands[1]));
return \"subq%.w %1,%0\";
}
- /* On everything except the 68000 it is faster to use two
- addqw instructions to add a small integer (8 < N <= 16)
- to an address register. Likewise for subqw. */
- if (INTVAL (operands[1]) > 8
- && INTVAL (operands[1]) <= 16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subqw. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
{
- operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8);
- return \"addq%.w %#8,%0\;addq%.w %1,%0\";
- }
- if (INTVAL (operands[1]) < -8
- && INTVAL (operands[1]) >= -16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
- {
- operands[1] = gen_rtx (CONST_INT, VOIDmode,
- - INTVAL (operands[1]) - 8);
- return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+ if (INTVAL (operands[1]) > 8
+ && INTVAL (operands[1]) <= 16)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[1]) - 8);
+ return \"addq%.w %#8,%0\;addq%.w %1,%0\";
+ }
+ if (INTVAL (operands[1]) < -8
+ && INTVAL (operands[1]) >= -16)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[1]) - 8);
+ return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+ }
}
- }
#endif
+ if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA
+ return \"lea (%c1,%0),%0\";
+#else
+ return \"lea %0@(%c1),%0\";
+#endif
+ }
return \"add%.w %1,%0\";
}")
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
(plus:HI (match_operand:HI 1 "general_operand" "dn,rmn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"*
{
-#ifndef NO_ADDSUB_Q
if (GET_CODE (operands[1]) == CONST_INT)
{
+#ifndef NO_ADDSUB_Q
/* If the constant would be a negative number when interpreted as
HImode, make it negative. This is usually, but not always, done
elsewhere in the compiler. First check for constants out of range,
- INTVAL (operands[1]));
return \"subq%.w %1,%0\";
}
- /* On everything except the 68000 it is faster to use two
- addqw instructions to add a small integer (8 < N <= 16)
- to an address register. Likewise for subqw. */
- if (INTVAL (operands[1]) > 8
- && INTVAL (operands[1]) <= 16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
- {
- operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8);
- return \"addq%.w %#8,%0\;addq%.w %1,%0\";
- }
- if (INTVAL (operands[1]) < -8
- && INTVAL (operands[1]) >= -16
- && ADDRESS_REG_P (operands[0])
- && TARGET_68020)
+ /* On the CPU32 it is faster to use two addqw instructions to
+ add a small integer (8 < N <= 16) to a register.
+ Likewise for subqw. */
+ if (TARGET_CPU32 && REG_P (operands[0]))
{
- operands[1] = gen_rtx (CONST_INT, VOIDmode,
- - INTVAL (operands[1]) - 8);
- return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+ if (INTVAL (operands[1]) > 8
+ && INTVAL (operands[1]) <= 16)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ INTVAL (operands[1]) - 8);
+ return \"addq%.w %#8,%0\;addq%.w %1,%0\";
+ }
+ if (INTVAL (operands[1]) < -8
+ && INTVAL (operands[1]) >= -16)
+ {
+ operands[1] = gen_rtx (CONST_INT, VOIDmode,
+ - INTVAL (operands[1]) - 8);
+ return \"subq%.w %#8,%0\;subq%.w %1,%0\";
+ }
}
- }
#endif
+ if (ADDRESS_REG_P (operands[0]) && !TARGET_68040)
+#ifdef MOTOROLA
+ return \"lea (%c1,%0),%0\";
+#else
+ return \"lea %0@(%c1),%0\";
+#endif
+ }
return \"add%.w %1,%0\";
}")
[(set (match_operand:QI 0 "general_operand" "=m,d")
(plus:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"*
{
#ifndef NO_ADDSUB_Q
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
(plus:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"*
{
#ifndef NO_ADDSUB_Q
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
(plus:QI (match_operand:QI 1 "general_operand" "dn,dmn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"*
{
#ifndef NO_ADDSUB_Q
;; subtract instructions
(define_insn "subdi_sexthishl32"
- [(set (match_operand:DI 0 "general_operand" "=o,d,a")
- (minus:DI (match_operand:DI 1 "general_operand" "0,0,0")
- (ashift:DI (sign_extend:DI (match_operand:HI 2 "general_operand" "rm,rm,rm"))
+ [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d")
+ (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
+ (ashift:DI (sign_extend:DI (match_operand:HI 2 "general_operand" "rm,rm,rm,rm"))
(const_int 32))))
- (clobber (match_scratch:SI 3 "=&d*a,a*d,X"))]
- ""
+ (clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
+ "!TARGET_5200"
"*
{
CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return \"sub%.w %2,%0\";
- else if (DATA_REG_P (operands[3]))
- return \"move%.w %2,%3\;ext%.l %3\;sub%.l %3,%0\";
- else if (DATA_REG_P (operands[0]))
+ else if (ADDRESS_REG_P (operands[3]))
return \"move%.w %2,%3\;sub%.l %3,%0\";
else
- return \"move%.l %0,%3\;sub%.w %2,%3\;mov%.l %3,%0\";
+ return \"move%.w %2,%3\;ext%.l %3\;sub%.l %3,%0\";
} ")
(define_insn "subdi_dishl32"
} ")
(define_insn "subdi3"
- [(set (match_operand:DI 0 "general_operand" "=d,<,d,o<>")
- (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0")
- (match_operand:DI 2 "general_operand" "d,<,*ao>,d")))
- (clobber (match_scratch:SI 3 "=X,X,&d,&d"))]
+ [(set (match_operand:DI 0 "general_operand" "=<,o<>,d,d,d")
+ (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0,0")
+ (match_operand:DI 2 "general_operand" "<,d,o>,d,a")))
+ (clobber (match_scratch:SI 3 "=X,&d,&d,X,&d"))]
""
"*
{
(minus:SI (match_operand:SI 1 "general_operand" "0")
(sign_extend:SI
(match_operand:HI 2 "nonimmediate_operand" "rm"))))]
- ""
+ "!TARGET_5200"
"sub%.w %2,%0")
(define_insn "subhi3"
[(set (match_operand:HI 0 "general_operand" "=m,r")
(minus:HI (match_operand:HI 1 "general_operand" "0,0")
(match_operand:HI 2 "general_operand" "dn,rmn")))]
- ""
+ "!TARGET_5200"
"sub%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
(minus:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn,rmn")))]
- ""
+ "!TARGET_5200"
"sub%.w %1,%0")
(define_insn "subqi3"
[(set (match_operand:QI 0 "general_operand" "=m,d")
(minus:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:QI 2 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"sub%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
(minus:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"sub%.b %1,%0")
(define_expand "subdf3"
#endif
}")
-(define_insn "mulsi3"
+(define_expand "mulsi3"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (mult:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_68020 || TARGET_5200"
+ "")
+
+(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d")
(mult:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_operand" "dmsK")))]
"TARGET_68020"
"muls%.l %2,%0")
+(define_insn ""
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (mult:SI (match_operand:SI 1 "general_operand" "%0")
+ (match_operand:SI 2 "general_operand" "d<>")))]
+ "TARGET_5200"
+ "muls%.l %2,%0")
+
(define_insn "umulhisi3"
[(set (match_operand:SI 0 "general_operand" "=d")
(mult:SI (zero_extend:SI
(truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
(zero_extend:DI (match_dup 2)))
(const_int 32))))])]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"")
(define_insn ""
(truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
(zero_extend:DI (match_dup 2)))
(const_int 32))))]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"mulu%.l %2,%3:%0")
; Match immediate case. For 2.4 only match things < 2^31.
(truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
(match_dup 2))
(const_int 32))))]
- "TARGET_68020 && !TARGET_68060
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200
&& (unsigned) INTVAL (operands[2]) <= 0x7fffffff"
"mulu%.l %2,%3:%0")
(truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
(sign_extend:DI (match_dup 2)))
(const_int 32))))])]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"")
(define_insn ""
(truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
(sign_extend:DI (match_dup 2)))
(const_int 32))))]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"muls%.l %2,%3:%0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(mult:SI (match_operand:SI 1 "register_operand" "%0")
- (match_operand:SI 2 "const_int_operand" "n")))
+ (match_operand:SI 2 "const_sint32_operand" "")))
(set (match_operand:SI 3 "register_operand" "=d")
(truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
(match_dup 2))
(const_int 32))))]
- "TARGET_68020 && !TARGET_68060
- /* This test is a noop on 32 bit machines,
- but important for a cross-compiler hosted on 64-bit machines. */
- && INTVAL (operands[2]) <= 0x7fffffff
- && INTVAL (operands[2]) >= -0x80000000"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"muls%.l %2,%3:%0")
(define_expand "umulsi3_highpart"
(zero_extend:DI (match_operand:SI 2 "general_operand" "")))
(const_int 32))))
(clobber (match_dup 3))])]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"
{
operands[3] = gen_reg_rtx (SImode);
(zero_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm")))
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"mulu%.l %3,%0:%1")
(define_insn "const_umulsi3_highpart"
(match_operand 3 "const_uint32_operand" ""))
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"mulu%.l %3,%0:%1")
(define_expand "smulsi3_highpart"
(sign_extend:DI (match_operand:SI 2 "general_operand" "")))
(const_int 32))))
(clobber (match_dup 3))])]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"
{
operands[3] = gen_reg_rtx (SImode);
(sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm")))
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"muls%.l %3,%0:%1")
(define_insn "const_smulsi3_highpart"
(match_operand 3 "const_sint32_operand" ""))
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
- "TARGET_68020 && !TARGET_68060"
+ "TARGET_68020 && !TARGET_68060 && !TARGET_5200"
"muls%.l %3,%0:%1")
(define_expand "muldf3"
(match_operand:SI 2 "general_operand" "dmsK")))
(set (match_operand:SI 3 "general_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))]
- "TARGET_68020"
+ "TARGET_68020 && !TARGET_5200"
"*
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
(match_operand:SI 2 "general_operand" "dmsK")))
(set (match_operand:SI 3 "general_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))]
- "TARGET_68020"
+ "TARGET_68020 && !TARGET_5200"
"*
{
if (find_reg_note (insn, REG_UNUSED, operands[3]))
(match_operand:HI 2 "general_operand" "dmsK")))
(set (match_operand:HI 3 "general_operand" "=d")
(mod:HI (match_dup 1) (match_dup 2)))]
- ""
+ "!TARGET_5200"
"*
{
#ifdef MOTOROLA
(match_operand:HI 2 "general_operand" "dmsK")))
(set (match_operand:HI 3 "general_operand" "=d")
(umod:HI (match_dup 1) (match_dup 2)))]
- ""
+ "!TARGET_5200"
"*
{
#ifdef MOTOROLA
;; Prevent AND from being made with sp. This doesn't exist in the machine
;; and reload will cause inefficient code. Since sp is a FIXED_REG, we
;; can't allocate pseudos into it.
-(define_insn "andsi3"
+
+(define_expand "andsi3"
[(set (match_operand:SI 0 "not_sp_operand" "=m,d")
(and:SI (match_operand:SI 1 "general_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "dKs,dmKs")))]
+ (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
""
+ "")
+
+(define_insn "andsi3_internal"
+ [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+ "!TARGET_5200"
"*
{
int logval;
&& (INTVAL (operands[2]) | 0xffff) == 0xffffffff
&& (DATA_REG_P (operands[0])
|| offsettable_memref_p (operands[0])))
- {
+ {
if (GET_CODE (operands[0]) != REG)
operands[0] = adj_offsettable_operand (operands[0], 2);
operands[2] = gen_rtx (CONST_INT, VOIDmode,
&& (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
&& (DATA_REG_P (operands[0])
|| offsettable_memref_p (operands[0])))
- {
+ {
if (DATA_REG_P (operands[0]))
{
operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
return \"and%.l %2,%0\";
}")
+(define_insn "andsi3_5200"
+ [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
+ (and:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,dmsK")))]
+ "TARGET_5200"
+ "and%.l %2,%0")
+
(define_insn "andhi3"
[(set (match_operand:HI 0 "general_operand" "=m,d")
(and:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"and%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
(and:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"and%.w %1,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
(and:HI (match_operand:HI 1 "general_operand" "dn,dmn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"and%.w %1,%0")
(define_insn "andqi3"
[(set (match_operand:QI 0 "general_operand" "=m,d")
(and:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"and%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
(and:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"and%.b %1,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
(and:QI (match_operand:QI 1 "general_operand" "dn,dmn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"and%.b %1,%0")
\f
;; inclusive-or instructions
-(define_insn "iorsi3"
+(define_expand "iorsi3"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (ior:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "")
+
+(define_insn "iorsi3_internal"
[(set (match_operand:SI 0 "general_operand" "=m,d")
(ior:SI (match_operand:SI 1 "general_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "dKs,dmKs")))]
- ""
+ (match_operand:SI 2 "general_operand" "dKs,dmMs")))]
+ "!TARGET_5200"
"*
{
register int logval;
&& INTVAL (operands[2]) >> 16 == 0
&& (DATA_REG_P (operands[0])
|| offsettable_memref_p (operands[0])))
- {
+ {
if (GET_CODE (operands[0]) != REG)
operands[0] = adj_offsettable_operand (operands[0], 2);
/* Do not delete a following tstl %0 insn; that would be incorrect. */
&& (logval = exact_log2 (INTVAL (operands[2]))) >= 0
&& (DATA_REG_P (operands[0])
|| offsettable_memref_p (operands[0])))
- {
+ {
if (DATA_REG_P (operands[0]))
{
operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
return \"or%.l %2,%0\";
}")
+(define_insn "iorsi3_5200"
+ [(set (match_operand:SI 0 "general_operand" "=m,d")
+ (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,dmsK")))]
+ "TARGET_5200"
+ "or%.l %2,%0")
+
(define_insn "iorhi3"
[(set (match_operand:HI 0 "general_operand" "=m,d")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"or%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
(ior:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"or%.w %1,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
(ior:HI (match_operand:HI 1 "general_operand" "dn,dmn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"or%.w %1,%0")
(define_insn "iorqi3"
[(set (match_operand:QI 0 "general_operand" "=m,d")
(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"or%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn,dmn")))]
- ""
+ "!TARGET_5200"
"or%.b %1,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
(ior:QI (match_operand:QI 1 "general_operand" "dn,dmn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"or%.b %1,%0")
+;; On all 68k models, this makes faster code in a special case.
+;; See also ashlsi_16, ashrsi_16 and lshrsi_16.
+
+(define_insn "iorsi_zexthi_ashl16"
+ [(set (match_operand:SI 0 "general_operand" "=d,d")
+ (ior:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "dmn,dmn"))
+ (ashift:SI (match_operand:SI 2 "general_operand" "o,0")
+ (const_int 16))))]
+ ""
+ "*
+{
+ CC_STATUS_INIT;
+ if (GET_CODE (operands[2]) != REG)
+ {
+ operands[2] = adj_offsettable_operand (operands[2], 2);
+ output_asm_insn (\"move%.w %2,%0\", operands);
+ }
+ return \"swap %0\;mov%.w %1,%0\";
+}")
+
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=o,d")
(ior:SI (zero_extend:SI (match_operand 1 "general_operand" "dn,dmn"))
(match_operand:SI 2 "general_operand" "0,0")))]
- ""
+ "!TARGET_5200"
"*
{
int byte_mode;
\f
;; xor instructions
-(define_insn "xorsi3"
+(define_expand "xorsi3"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (xor:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ ""
+ "")
+
+(define_insn "xorsi3_internal"
[(set (match_operand:SI 0 "general_operand" "=do,m")
(xor:SI (match_operand:SI 1 "general_operand" "%0,0")
(match_operand:SI 2 "general_operand" "di,dKs")))]
- ""
+ "!TARGET_5200"
"*
{
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >> 16 == 0
&& (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0])))
- {
+ {
if (! DATA_REG_P (operands[0]))
operands[0] = adj_offsettable_operand (operands[0], 2);
/* Do not delete a following tstl %0 insn; that would be incorrect. */
return \"eor%.l %2,%0\";
}")
+(define_insn "xorsi3_5200"
+ [(set (match_operand:SI 0 "general_operand" "=dm,d")
+ (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,Ks")))]
+ "TARGET_5200"
+ "eor%.l %2,%0")
+
(define_insn "xorhi3"
[(set (match_operand:HI 0 "general_operand" "=dm")
(xor:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "dn")))]
- ""
+ "!TARGET_5200"
"eor%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
(xor:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn")))]
- ""
+ "!TARGET_5200"
"eor%.w %1,%0")
-
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
(xor:HI (match_operand:HI 1 "general_operand" "dn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"eor%.w %1,%0")
(define_insn "xorqi3"
[(set (match_operand:QI 0 "general_operand" "=dm")
(xor:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "dn")))]
- ""
+ "!TARGET_5200"
"eor%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
(xor:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn")))]
- ""
+ "!TARGET_5200"
"eor%.b %1,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
(xor:QI (match_operand:QI 1 "general_operand" "dn")
(match_dup 0)))]
- ""
+ "!TARGET_5200"
"eor%.b %1,%0")
\f
;; negation instructions
-(define_insn "negdi2"
- [(set (match_operand:DI 0 "general_operand" "=d*ao,<")
- (neg:DI (match_operand:DI 1 "general_operand" "0,0")))]
+(define_expand "negdi2"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (neg:DI (match_operand:DI 1 "general_operand" "")))]
""
+ "
+{
+ if (TARGET_5200)
+ emit_insn (gen_negdi2_5200 (operands[0], operands[1]));
+ else
+ emit_insn (gen_negdi2_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "negdi2_internal"
+ [(set (match_operand:DI 0 "general_operand" "=<,do,!*a")
+ (neg:DI (match_operand:DI 1 "general_operand" "0,0,0")))]
+ "!TARGET_5200"
"*
{
- if (which_alternative == 1)
+ if (which_alternative == 0)
return \"neg%.l %0\;negx%.l %0\";
if (GET_CODE (operands[0]) == REG)
operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
return \"neg%.l %1\;negx%.l %0\";
} ")
-(define_insn "negsi2"
+(define_insn "negdi2_5200"
+ [(set (match_operand:DI 0 "general_operand" "=d")
+ (neg:DI (match_operand:DI 1 "general_operand" "0")))]
+ "TARGET_5200"
+ "*
+{
+ operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ return \"neg%.l %1\;negx%.l %0\";
+} ")
+
+(define_expand "negsi2"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (neg:SI (match_operand:SI 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (TARGET_5200)
+ emit_insn (gen_negsi2_5200 (operands[0], operands[1]));
+ else
+ emit_insn (gen_negsi2_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "negsi2_internal"
[(set (match_operand:SI 0 "general_operand" "=dm")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
- ""
+ "!TARGET_5200"
+ "neg%.l %0")
+
+(define_insn "negsi2_5200"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+ "TARGET_5200"
"neg%.l %0")
(define_insn "neghi2"
[(set (match_operand:HI 0 "general_operand" "=dm")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
- ""
+ "!TARGET_5200"
"neg%.w %0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
(neg:HI (match_dup 0)))]
- ""
+ "!TARGET_5200"
"neg%.w %0")
(define_insn "negqi2"
[(set (match_operand:QI 0 "general_operand" "=dm")
(neg:QI (match_operand:QI 1 "general_operand" "0")))]
- ""
+ "!TARGET_5200"
"neg%.b %0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
(neg:QI (match_dup 0)))]
- ""
+ "!TARGET_5200"
"neg%.b %0")
;; If using software floating point, just flip the sign bit.
if (result != target)
emit_move_insn (result, target);
-
+
emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
operand_subword_force (operands[1], 1, DFmode));
if (result != target)
emit_move_insn (result, target);
-
+
emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
operand_subword_force (operands[1], 1, DFmode));
(define_insn "one_cmpldi2"
[(set (match_operand:DI 0 "general_operand" "=dm")
(not:DI (match_operand:DI 1 "general_operand" "0")))]
- ""
+ "!TARGET_5200"
"*
{
CC_STATUS_INIT;
return \"not%.l %1\;not%.l %0\";
}")
-(define_insn "one_cmplsi2"
+(define_expand "one_cmplsi2"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (not:SI (match_operand:SI 1 "general_operand" "")))]
+ ""
+ "
+{
+ if (TARGET_5200)
+ emit_insn (gen_one_cmplsi2_5200 (operands[0], operands[1]));
+ else
+ emit_insn (gen_one_cmplsi2_internal (operands[0], operands[1]));
+ DONE;
+}")
+
+(define_insn "one_cmplsi2_internal"
[(set (match_operand:SI 0 "general_operand" "=dm")
(not:SI (match_operand:SI 1 "general_operand" "0")))]
- ""
+ "!TARGET_5200"
+ "not%.l %0")
+
+(define_insn "one_cmplsi2_5200"
+ [(set (match_operand:SI 0 "general_operand" "=d")
+ (not:SI (match_operand:SI 1 "general_operand" "0")))]
+ "TARGET_5200"
"not%.l %0")
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "general_operand" "=dm")
(not:HI (match_operand:HI 1 "general_operand" "0")))]
- ""
+ "!TARGET_5200"
"not%.w %0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
(not:HI (match_dup 0)))]
- ""
+ "!TARGET_5200"
"not%.w %0")
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "general_operand" "=dm")
(not:QI (match_operand:QI 1 "general_operand" "0")))]
- ""
+ "!TARGET_5200"
"not%.b %0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
(not:QI (match_dup 0)))]
- ""
+ "!TARGET_5200"
"not%.b %0")
\f
;; arithmetic shift instructions
} ")
(define_insn "ashldi_sexthi"
- [(set (match_operand:DI 0 "register_operand" "=*da")
- (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm"))
- (const_int 32)))]
+ [(set (match_operand:DI 0 "general_operand" "=m,a*d")
+ (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm,rm"))
+ (const_int 32)))
+ (clobber (match_scratch:SI 2 "=a,X"))]
""
"*
{
CC_STATUS_INIT;
- operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
- if (DATA_REG_P (operands[0]))
- return \"move%.w %1,%0\;ext%.l %0\;clr%.l %2\";
+ if (GET_CODE (operands[0]) == MEM)
+ {
+ if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"clr%.l %0\;move%.w %1,%2\;move%.l %2,%0\";
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %0\";
+ else
+ {
+ operands[3] = adj_offsettable_operand (operands[0], 4);
+ return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %3\";
+ }
+ }
+ else if (DATA_REG_P (operands[0]))
+ return \"move%.w %1,%0\;ext%.l %0\;clr%.l %R0\";
else
- return \"move%.w %1,%0\;sub%.l %2,%2\";
+ return \"move%.w %1,%0\;sub%.l %R0,%R0\";
} ")
(define_insn "ashldi_const32"
- [(set (match_operand:DI 0 "general_operand" "=ro,<,>")
- (ashift:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
+ [(set (match_operand:DI 0 "general_operand" "=rm")
+ (ashift:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)))]
""
"*
operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
else
operands[3] = adj_offsettable_operand (operands[1], 4);
- if (which_alternative == 1)
- return \"clr%.l %0\;move%.l %3,%0\";
- if (which_alternative == 2)
- return \"move%.l %3,%0\;clr%.l %0\";
if (GET_CODE (operands[0]) == REG)
operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
+ return \"clr%.l %0\;move%.l %3,%0\";
+ else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
+ return \"move%.l %3,%0\;clr%.l %0\";
else
operands[2] = adj_offsettable_operand (operands[0], 4);
if (ADDRESS_REG_P (operands[2]))
FAIL;
} ")
-;; On all 68k models, this makes faster code in a special case.
+;; On most 68k models, this makes faster code in a special case.
-(define_insn ""
+(define_insn "ashlsi_16"
[(set (match_operand:SI 0 "register_operand" "=d")
(ashift:SI (match_operand:SI 1 "register_operand" "0")
(const_int 16)))]
- ""
+ "!TARGET_68060"
"*
{
CC_STATUS_INIT;
return \"swap %0\;clr%.w %0\";
}")
+;; ashift patterns : use lsl instead of asl, because lsl always clears the
+;; overflow bit, so we must not set CC_NO_OVERFLOW.
+
;; On the 68000, this makes faster code in a special case.
-(define_insn ""
+(define_insn "ashlsi_17_24"
[(set (match_operand:SI 0 "register_operand" "=d")
(ashift:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
- "(! TARGET_68020
+ "(! TARGET_68020 && !TARGET_5200
&& INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
"*
{
CC_STATUS_INIT;
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
- return \"asl%.w %2,%0\;swap %0\;clr%.w %0\";
+ return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\";
}")
(define_insn "ashlsi3"
"*
{
if (operands[2] == const1_rtx)
- return \"add%.l %0,%0\";
- return \"asl%.l %2,%0\";
+ {
+ cc_status.flags = CC_NO_OVERFLOW;
+ return \"add%.l %0,%0\";
+ }
+ return \"lsl%.l %2,%0\";
}")
(define_insn "ashlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashift:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
- ""
- "asl%.w %2,%0")
+ "!TARGET_5200"
+ "lsl%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashift:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
- ""
- "asl%.w %1,%0")
+ "!TARGET_5200"
+ "lsl%.w %1,%0")
(define_insn "ashlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashift:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
- ""
- "asl%.b %2,%0")
+ "!TARGET_5200"
+ "lsl%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashift:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
- ""
- "asl%.b %1,%0")
+ "!TARGET_5200"
+ "lsl%.b %1,%0")
-;; On all 68k models, this makes faster code in a special case.
+;; On most 68k models, this makes faster code in a special case.
-(define_insn ""
+(define_insn "ashrsi_16"
[(set (match_operand:SI 0 "register_operand" "=d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
(const_int 16)))]
- ""
+ "!TARGET_68060"
"swap %0\;ext%.l %0")
;; On the 68000, this makes faster code in a special case.
[(set (match_operand:SI 0 "register_operand" "=d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
- "(! TARGET_68020
+ "(! TARGET_68020 && !TARGET_5200
&& INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
"*
{
[(set (match_operand:DI 0 "general_operand" "=d")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
(match_operand 2 "const_int_operand" "n")))]
- "(INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
+ "!TARGET_5200
+ && ((INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
|| INTVAL (operands[2]) == 3 || INTVAL (operands[2]) == 8
- || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 63)"
+ || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 31
+ || INTVAL (operands[2]) == 63))"
"*
{
operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
return \"move%.b %0,%1\;asr%.l %#8,%0\;ror%.l %#8,%1\";
else if (INTVAL (operands[2]) == 16)
return \"move%.w %0,%1\;clr%.w %0\;swap %1\;ext%.l %0\";
+ else if (INTVAL (operands[2]) == 31)
+ return \"add%.l %1,%1\;addx%.l %0,%0\;move%.l %0,%1\;subx%.l %0,%0\";
else if (INTVAL (operands[2]) == 2)
return \"asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\";
else/* if (INTVAL (operands[2]) == 3)*/
[(set (match_operand:DI 0 "general_operand" "")
(ashiftrt:DI (match_operand:DI 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))]
- ""
+ "!TARGET_5200"
"
{
if (GET_CODE (operands[2]) != CONST_INT
|| (INTVAL (operands[2]) != 1 && INTVAL (operands[2]) != 2
&& INTVAL (operands[2]) != 3 && INTVAL (operands[2]) != 8
- && INTVAL (operands[2]) != 16 && INTVAL (operands[2]) != 32
- && INTVAL (operands[2]) != 63))
+ && INTVAL (operands[2]) != 16 && INTVAL (operands[2]) != 31
+ && INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 63))
FAIL;
} ")
[(set (match_operand:HI 0 "register_operand" "=d")
(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"asr%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"asr%.w %1,%0")
(define_insn "ashrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"asr%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"asr%.b %1,%0")
\f
;; logical shift instructions
[(set (match_operand:DI 0 "general_operand" "=d")
(lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
(match_operand 2 "const_int_operand" "n")))]
- "(INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
+ "!TARGET_5200
+ && ((INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2
|| INTVAL (operands[2]) == 3 || INTVAL (operands[2]) == 8
- || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 63)"
+ || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 63))"
"*
{
operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
[(set (match_operand:DI 0 "general_operand" "")
(lshiftrt:DI (match_operand:DI 1 "general_operand" "")
(match_operand 2 "const_int_operand" "")))]
- ""
+ "!TARGET_5200"
"
{
if (GET_CODE (operands[2]) != CONST_INT
return \"add%.l %0,%0\;subx%.l %0,%0\;neg%.l %0\";
}")
-;; On all 68k models, this makes faster code in a special case.
+;; On most 68k models, this makes faster code in a special case.
(define_insn "lshrsi_16"
[(set (match_operand:SI 0 "register_operand" "=d")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(const_int 16)))]
- ""
+ "!TARGET_68060"
"*
{
CC_STATUS_INIT;
[(set (match_operand:SI 0 "register_operand" "=d")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
- "(! TARGET_68020
+ "(! TARGET_68020 && !TARGET_5200
&& INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
"*
{
[(set (match_operand:HI 0 "register_operand" "=d")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"lsr%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(lshiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"lsr%.w %1,%0")
(define_insn "lshrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"lsr%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(lshiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"lsr%.b %1,%0")
\f
;; rotate instructions
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(rotate:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "dI")))]
- ""
- "rol%.l %2,%0")
+ (match_operand:SI 2 "general_operand" "dINO")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)
+ return \"swap %0\";
+ else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, 32 - INTVAL (operands[2]));
+ return \"ror%.l %2,%0\";
+ }
+ else
+ return \"rol%.l %2,%0\";
+}")
(define_insn "rotlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(rotate:HI (match_operand:HI 1 "register_operand" "0")
- (match_operand:HI 2 "general_operand" "dI")))]
- ""
- "rol%.w %2,%0")
-
+ (match_operand:HI 2 "general_operand" "dIP")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, 16 - INTVAL (operands[2]));
+ return \"ror%.w %2,%0\";
+ }
+ else
+ return \"rol%.w %2,%0\";
+}")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(rotate:HI (match_dup 0)
- (match_operand:HI 1 "general_operand" "dI")))]
- ""
- "rol%.w %1,%0")
+ (match_operand:HI 1 "general_operand" "dIP")))]
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, 16 - INTVAL (operands[2]));
+ return \"ror%.w %2,%0\";
+ }
+ else
+ return \"rol%.w %2,%0\";
+}")
(define_insn "rotlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(rotate:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
- ""
- "rol%.b %2,%0")
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, 8 - INTVAL (operands[2]));
+ return \"ror%.b %2,%0\";
+ }
+ else
+ return \"rol%.b %2,%0\";
+}")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(rotate:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
- ""
- "rol%.b %1,%0")
+ "!TARGET_5200"
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, 8 - INTVAL (operands[2]));
+ return \"ror%.b %2,%0\";
+ }
+ else
+ return \"rol%.b %2,%0\";
+}")
(define_insn "rotrsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(rotatert:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"ror%.l %2,%0")
(define_insn "rotrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(rotatert:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"ror%.w %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(rotatert:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"ror%.w %1,%0")
(define_insn "rotrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(rotatert:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"ror%.b %2,%0")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(rotatert:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
- ""
+ "!TARGET_5200"
"ror%.b %1,%0")
\f
{
if (operands[1] == const1_rtx
&& GET_CODE (operands[2]) == CONST_INT)
- {
+ {
int width = GET_CODE (operands[0]) == REG ? 31 : 7;
return output_btst (operands,
gen_rtx (CONST_INT, VOIDmode,
return \"bftst %0{%b2:%b1}\";
}")
-
+
;;; now handle the register cases
(define_insn ""
[(set (cc0)
{
if (operands[1] == const1_rtx
&& GET_CODE (operands[2]) == CONST_INT)
- {
+ {
int width = GET_CODE (operands[0]) == REG ? 31 : 7;
return output_btst (operands,
gen_rtx (CONST_INT, VOIDmode,
return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
} ")
-(define_insn "seq"
- [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "seq"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (eq:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(eq:QI (cc0) (const_int 0)))]
""
"*
OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
")
-(define_insn "sne"
- [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sne"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (ne:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(ne:QI (cc0) (const_int 0)))]
""
"*
OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
")
-(define_insn "sgt"
- [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sgt"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (gt:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(gt:QI (cc0) (const_int 0)))]
""
"*
")
(define_insn "sgtu"
- [(set (match_operand:QI 0 "general_operand" "=d")
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(gtu:QI (cc0) (const_int 0)))]
""
"* cc_status = cc_prev_status;
return \"shi %0\"; ")
-(define_insn "slt"
- [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "slt"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (lt:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(lt:QI (cc0) (const_int 0)))]
""
"* cc_status = cc_prev_status;
OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
(define_insn "sltu"
- [(set (match_operand:QI 0 "general_operand" "=d")
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(ltu:QI (cc0) (const_int 0)))]
""
"* cc_status = cc_prev_status;
return \"scs %0\"; ")
-(define_insn "sge"
- [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sge"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (ge:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(ge:QI (cc0) (const_int 0)))]
""
"* cc_status = cc_prev_status;
OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
(define_insn "sgeu"
- [(set (match_operand:QI 0 "general_operand" "=d")
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(geu:QI (cc0) (const_int 0)))]
""
"* cc_status = cc_prev_status;
return \"scc %0\"; ")
-(define_insn "sle"
- [(set (match_operand:QI 0 "general_operand" "=d")
+(define_expand "sle"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (le:QI (cc0) (const_int 0)))]
+ ""
+ "
+{
+ if (TARGET_68060 && m68k_last_compare_had_fp_operands)
+ {
+ m68k_last_compare_had_fp_operands = 0;
+ FAIL;
+ }
+}")
+
+(define_insn ""
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(le:QI (cc0) (const_int 0)))]
""
"*
")
(define_insn "sleu"
- [(set (match_operand:QI 0 "general_operand" "=d")
+ [(set (match_operand:QI 0 "general_operand" "=dm")
(leu:QI (cc0) (const_int 0)))]
""
"* cc_status = cc_prev_status;
""
"*
{
+ CC_STATUS_INIT;
if (which_alternative == 1)
#ifdef MOTOROLA
return \"move%.l %0,%2\;or%.l %0,%2\;jbeq %l1\";
#else
return \"move%.l %0,%2\;or%.l %0,%2\;jeq %l1\";
#endif
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+#ifdef MOTOROLA
+ return \"jbeq %l1\";
+#else
+ return \"jeq %l1\";
+#endif
+ }
if (GET_CODE (operands[0]) == REG)
operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
else
return \"move%.l %0,%2\;or%.l %3,%2\;jeq %l1\";
#endif
operands[4] = gen_label_rtx();
+ if (TARGET_68020 || TARGET_5200)
+#ifdef MOTOROLA
+ output_asm_insn (\"tst%.l %0\;jbne %l4\;tst%.l %3\;jbeq %l1\", operands);
+#else
+ output_asm_insn (\"tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1\", operands);
+#endif
+ else
#ifdef MOTOROLA
- output_asm_insn (\"tst%.l %0\;jbne %l4\;tst%.l %3\;jbeq %l1\", operands);
+#ifdef SGS_CMP_ORDER
+ output_asm_insn (\"cmp%.w %0,%#0\;jbne %l4\;cmp%.w %3,%#0\;jbeq %l1\", operands);
#else
- output_asm_insn (\"tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1\", operands);
+ output_asm_insn (\"cmp%.w %#0,%0\;jbne %l4\;cmp%.w %#0,%3\;jbeq %l1\", operands);
+#endif
+#else
+ output_asm_insn (\"cmp%.w %#0,%0\;jne %l4\;cmp%.w %#0,%3\;jeq %l1\", operands);
#endif
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (operands[4]));
(const_int 0))
(label_ref (match_operand 1 "" ","))
(pc)))
- (clobber (match_scratch:SI 2 "=d,"))]
+ (clobber (match_scratch:SI 2 "=d,X"))]
""
"*
{
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+#ifdef MOTOROLA
+ return \"jbne %l1\";
+#else
+ return \"jne %l1\";
+#endif
+ }
+ CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
else
operands[3] = adj_offsettable_operand (operands[0], 4);
- if (ADDRESS_REG_P (operands[0]))
+ if (!ADDRESS_REG_P (operands[0]))
+#ifdef MOTOROLA
+ return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\";
+#else
+ return \"move%.l %0,%2\;or%.l %3,%2\;jne %l1\";
+#endif
+ if (TARGET_68020 || TARGET_5200)
#ifdef MOTOROLA
return \"tst%.l %0\;jbne %l1\;tst%.l %3\;jbne %l1\";
#else
#endif
else
#ifdef MOTOROLA
- return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\";
+#ifdef SGS_CMP_ORDER
+ return \"cmp%.w %0,%#0\;jbne %l1\;cmp%.w %3,%#0\;jbne %l1\";
#else
- return \"move%.l %0,%2\;or%.l %3,%2\;jne %l1\";
+ return \"cmp%.w %#0,%0\;jbne %l1\;cmp%.w %#0,%3\;jbne %l1\";
+#endif
+#else
+ return \"cmp%.w %#0,%0\;jne %l1\;cmp%.w %#0,%3\;jne %l1\";
#endif
} ")
""
"*
{
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+ if (cc_status.flags & CC_REVERSED)
+ {
+#ifdef MOTOROLA
+ return \"jble %l1\";
+#else
+ return \"jle %l1\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ return \"jbpl %l1\";
+#else
+ return \"jpl %l1\";
+#endif
+ }
+ }
+ CC_STATUS_INIT;
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
+ output_asm_insn(\"tst%.l %0\", operands);
+ else
+ /* On an address reg, cmpw may replace cmpl. */
+#ifdef SGS_CMP_ORDER
+ output_asm_insn(\"cmp%.w %0,%#0\", operands);
+#else
+ output_asm_insn(\"cmp%.w %#0,%0\", operands);
+#endif
+
#ifdef MOTOROLA
- return \"tst%.l %0\;jbge %l1\";
+ return \"jbpl %l1\";
#else
- return \"tst%.l %0\;jge %l1\";
+ return \"jpl %l1\";
#endif
} ")
""
"*
{
+ if ((cc_prev_status.value1
+ && rtx_equal_p (cc_prev_status.value1, operands[0]))
+ || (cc_prev_status.value2
+ && rtx_equal_p (cc_prev_status.value2, operands[0])))
+ {
+ cc_status = cc_prev_status;
+ if (cc_status.flags & CC_REVERSED)
+ {
+#ifdef MOTOROLA
+ return \"jbgt %l1\";
+#else
+ return \"jgt %l1\";
+#endif
+ }
+ else
+ {
+#ifdef MOTOROLA
+ return \"jbmi %l1\";
+#else
+ return \"jmi %l1\";
+#endif
+ }
+ }
+ CC_STATUS_INIT;
+ if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0]))
+ output_asm_insn(\"tst%.l %0\", operands);
+ else
+ /* On an address reg, cmpw may replace cmpl. */
+#ifdef SGS_CMP_ORDER
+ output_asm_insn(\"cmp%.w %0,%#0\", operands);
+#else
+ output_asm_insn(\"cmp%.w %#0,%0\", operands);
+#endif
+
#ifdef MOTOROLA
- return \"tst%.l %0\;jbmi %l1\";
+ return \"jbmi %l1\";
#else
- return \"tst%.l %0\;jmi %l1\";
+ return \"jmi %l1\";
#endif
} ")
#else
#ifdef SGS
#ifdef ASM_OUTPUT_CASE_LABEL
- return \"jmp 6(%%pc,%0.w)\";
+ if (TARGET_5200)
+ return \"ext%.l %0\;jmp 6(%%pc,%0.l)\";
+ else
+ return \"jmp 6(%%pc,%0.w)\";
+#else
+ if (TARGET_5200)
+ {
+#ifdef CRDS
+ return \"ext%.l %0\;jmp 2(pc,%0.l)\";
#else
+ return \"extl %0\;jmp 2(%%pc,%0.l)\";
+#endif /* end !CRDS */
+ }
+ else
+ {
#ifdef CRDS
- return \"jmp 2(pc,%0.w)\";
+ return \"jmp 2(pc,%0.w)\";
#else
- return \"jmp 2(%%pc,%0.w)\";
+ return \"jmp 2(%%pc,%0.w)\";
#endif /* end !CRDS */
+ }
#endif
#else /* not SGS */
+ if (TARGET_5200)
+ {
+#ifdef MOTOROLA
+ return \"ext%.l %0\;jmp (2,pc,%0.l)\";
+#else
+ return \"extl %0\;jmp pc@(2,%0:l)\";
+#endif
+ }
+ else
+ {
#ifdef MOTOROLA
- return \"jmp (2,pc,%0.w)\";
+ return \"jmp (2,pc,%0.w)\";
#else
- return \"jmp pc@(2,%0:w)\";
+ return \"jmp pc@(2,%0:w)\";
#endif
+ }
#endif
#endif
")
(set (match_dup 0)
(plus:HI (match_dup 0)
(const_int -1)))]
- ""
+ "!TARGET_5200"
"*
{
CC_STATUS_INIT;
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))]
- ""
+ "!TARGET_5200"
"*
{
CC_STATUS_INIT;
(set (match_dup 0)
(plus:HI (match_dup 0)
(const_int -1)))]
- "find_reg_note (insn, REG_NONNEG, 0)"
+ "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)"
"*
{
CC_STATUS_INIT;
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))]
- "find_reg_note (insn, REG_NONNEG, 0)"
+ "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)"
"*
{
CC_STATUS_INIT;
;; For PIC calls, in order to be able to support
-;; dynamic linker LAZY BINDING, all the procedure calls need to go
+;; dynamic linker LAZY BINDING, all the procedure calls need to go
;; through the PLT (Procedure Linkage Table) section in PIC mode.
;;
-;; PIC calls are handled by loading the address of the function into a
+;; PIC calls are handled by loading the address of the function into a
;; register (via movsi), then emitting a register indirect call using
;; the "jsr" function call syntax.
;;
;; We have different patterns for PIC calls and non-PIC calls. The
;; different patterns are only used to choose the right syntax.
;;
-;; The svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it
-;; will create the correct relocation entry (R_68K_PLT32) for `FUNC',
+;; The svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it
+;; will create the correct relocation entry (R_68K_PLT32) for `FUNC',
;; that tells the linker editor to create an entry for `FUNC' in PLT
;; section at link time. However, all global objects reference are still
-;; done by using `OBJ@GOT'. So, the goal here is to output the function
-;; call operand as `FUNC@PLTPC', but output object operand as `OBJ@GOT'.
+;; done by using `OBJ@GOT'. So, the goal here is to output the function
+;; call operand as `FUNC@PLTPC', but output object operand as `OBJ@GOT'.
;; We need to have a way to differentiate these two different operands.
;;
-;; The strategy I use here is to use SYMBOL_REF_FLAG to differentiate
+;; The strategy I use here is to use SYMBOL_REF_FLAG to differentiate
;; these two different operands. The macro LEGITIMATE_PIC_OPERAND_P needs
-;; to be changed to recognize function calls symbol_ref operand as a valid
-;; PIC operand (by checking whether SYMBOL_REF_FLAG is set). This will
-;; avoid the compiler to load this symbol_ref operand into a register.
-;; Remember, the operand "foo@PLTPC" cannot be called via jsr directly
+;; to be changed to recognize function calls symbol_ref operand as a valid
+;; PIC operand (by checking whether SYMBOL_REF_FLAG is set). This will
+;; avoid the compiler to load this symbol_ref operand into a register.
+;; Remember, the operand "foo@PLTPC" cannot be called via jsr directly
;; since the value is a PC relative offset, not a real address.
;;
-;; All global objects are treated in the similar way as in SUN3. The only
-;; difference is: on m68k svr4, the reference of such global object needs
+;; All global objects are treated in the similar way as in SUN3. The only
+;; difference is: on m68k svr4, the reference of such global object needs
;; to end with a suffix "@GOT" so the assembler and linker know to create
-;; an entry for it in GOT (Global Offset Table) section. This is done in
+;; an entry for it in GOT (Global Offset Table) section. This is done in
;; m68k.c.
;; Call subroutine with no return value.
"*
#if defined (MOTOROLA) && !defined (USE_GAS)
#ifdef MOTOROLA_BSR
- if (GET_CODE (operands[0]) == MEM
+ if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
return \"bsr %0\";
#endif
"flag_pic"
"*
- if (GET_CODE (operands[0]) == MEM
+ if (GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
#ifdef MOTOROLA
#ifdef HPUX_ASM
"*
#if defined (MOTOROLA) && !defined (USE_GAS)
#ifdef MOTOROLA_BSR
- if (GET_CODE (operands[1]) == MEM
+ if (GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
return \"bsr %1\";
#endif
;; Operand 2 not really used on the m68000.
"flag_pic"
"*
- if (GET_CODE (operands[1]) == MEM
+ if (GET_CODE (operands[1]) == MEM
&& GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
#ifdef MOTOROLA
#ifdef HPUX_ASM
xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
#ifndef NO_ADDSUB_Q
if (INTVAL (xoperands[1]) <= 8)
- output_asm_insn (\"addq%.w %1,%0\", xoperands);
- else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
{
- xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
+ if (!TARGET_5200)
+ output_asm_insn (\"addq%.w %1,%0\", xoperands);
+ else
+ output_asm_insn (\"addq%.l %1,%0\", xoperands);
+ }
+ else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16)
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
INTVAL (xoperands[1]) - 8);
output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
}
else
#endif
if (INTVAL (xoperands[1]) <= 0x7FFF)
- output_asm_insn (\"add%.w %1,%0\", xoperands);
+ {
+ if (TARGET_68040)
+ output_asm_insn (\"add%.w %1,%0\", xoperands);
+ else
+#ifdef MOTOROLA
+ output_asm_insn (\"lea (%c1,%0),%0\", xoperands);
+#else
+ output_asm_insn (\"lea %0@(%c1),%0\", xoperands);
+#endif
+ }
else
output_asm_insn (\"add%.l %1,%0\", xoperands);
}
xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
#ifndef NO_ADDSUB_Q
if (INTVAL (xoperands[1]) <= 8)
- output_asm_insn (\"addq%.w %1,%0\", xoperands);
- else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
{
- xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
+ if (!TARGET_5200)
+ output_asm_insn (\"addq%.w %1,%0\", xoperands);
+ else
+ output_asm_insn (\"addq%.l %1,%0\", xoperands);
+ }
+ else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16)
+ {
+ xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
INTVAL (xoperands[1]) - 8);
output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
}
else
#endif
if (INTVAL (xoperands[1]) <= 0x7FFF)
- output_asm_insn (\"add%.w %1,%0\", xoperands);
+ {
+ if (TARGET_68040)
+ output_asm_insn (\"add%.w %1,%0\", xoperands);
+ else
+#ifdef MOTOROLA
+ output_asm_insn (\"lea (%c1,%0),%0\", xoperands);
+#else
+ output_asm_insn (\"lea %0@(%c1),%0\", xoperands);
+#endif
+ }
else
output_asm_insn (\"add%.l %1,%0\", xoperands);
}
gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
gen_rtx (CONST_INT, VOIDmode, 3)));
xoperands[3] = stack_pointer_rtx;
- output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
+ if (!TARGET_5200)
+ output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
+ else
+ output_asm_insn (\"subq%.l %#4,%3\;move%.b %1,%2\", xoperands);
return \"\";
}")
&& (DATA_REG_P (operands[0])
|| GET_CODE (operands[0]) == MEM)
/* clr insns on 68000 read before writing.
- This isn't so on the 68010, but we have no alternative for it. */
- && (TARGET_68020
+ This isn't so on the 68010, but we have no TARGET_68010. */
+ && ((TARGET_68020 || TARGET_5200)
|| !(GET_CODE (operands[0]) == MEM
&& MEM_VOLATILE_P (operands[0]))))
return \"clr%.w %0\";
(set (match_dup 0)
(plus:HI (match_dup 0)
(const_int -1)))])]
- "DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
"*
{
CC_STATUS_INIT;
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int -1)))])]
- "DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
"*
{
CC_STATUS_INIT;
fpsm%.s %x3,%2,%x1,%0
fpsm%.s %x3,%2,%x1,%0")
-(define_insn "tstxf"
+(define_expand "tstxf"
+ [(set (cc0)
+ (match_operand:XF 0 "nonimmediate_operand" ""))]
+ "TARGET_68881"
+ "m68k_last_compare_had_fp_operands = 1;")
+
+(define_insn ""
[(set (cc0)
(match_operand:XF 0 "nonimmediate_operand" "fm"))]
"TARGET_68881"
return \"ftst%.x %0\";
}")
-(define_insn "cmpxf"
+(define_expand "cmpxf"
+ [(set (cc0)
+ (compare (match_operand:XF 0 "nonimmediate_operand" "")
+ (match_operand:XF 1 "nonimmediate_operand" "")))]
+ "TARGET_68881"
+ "m68k_last_compare_had_fp_operands = 1;")
+
+(define_insn ""
[(set (cc0)
(compare (match_operand:XF 0 "nonimmediate_operand" "f,m")
(match_operand:XF 1 "nonimmediate_operand" "fm,f")))]
}
return \"fmove%.d %f1,%0\";
}")
-
+
(define_insn "truncxfsf2"
[(set (match_operand:SF 0 "general_operand" "=dm")
(float_truncate:SF
if (result != target)
emit_move_insn (result, target);
-
+
emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
operand_subword_force (operands[1], 1, XFmode));
emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),
if (result != target)
emit_move_insn (result, target);
-
+
emit_move_insn (operand_subword (operands[0], 1, 1, XFmode),
operand_subword_force (operands[1], 1, XFmode));
emit_move_insn (operand_subword (operands[0], 2, 1, XFmode),