#include "expr.h"
#include "toplev.h"
#include "basic-block.h"
+#include "integrate.h"
#include "ggc.h"
#include "target.h"
#include "target-def.h"
extern int reload_completed;
+/* The alias set for prologue/epilogue register save/restore. */
+static int s390_sr_alias_set = 0;
+
/* Function count for creating unique internal labels in a compile unit. */
int s390_function_count = 0;
rtx disp;
};
+/* Structure containing information for prologue and epilogue. */
+
+struct s390_frame
+{
+ int frame_pointer_p;
+ int return_reg_saved_p;
+ int save_fprs_p;
+ int first_save_gpr;
+ int first_restore_gpr;
+ int last_save_gpr;
+ int arg_frame_offset;
+
+ HOST_WIDE_INT frame_size;
+};
+
static int s390_match_ccmode_set PARAMS ((rtx, enum machine_mode));
static int s390_branch_condition_mask PARAMS ((rtx));
static const char *s390_branch_condition_mnemonic PARAMS ((rtx, int));
-static int base_n_index_p PARAMS ((rtx));
static int check_mode PARAMS ((rtx, enum machine_mode *));
+static int general_s_operand PARAMS ((rtx, enum machine_mode, int));
static int s390_decompose_address PARAMS ((rtx, struct s390_address *, int));
static int reg_used_in_mem_p PARAMS ((int, rtx));
static int addr_generation_dependency_p PARAMS ((rtx, rtx));
static rtx check_and_change_labels PARAMS ((rtx, int *));
static void s390_final_chunkify PARAMS ((int));
static int save_fprs_p PARAMS ((void));
-static int cur_is_leaf_function PARAMS ((void));
-static int save_fprs PARAMS ((FILE *, long, int));
-static int restore_fprs PARAMS ((FILE *, long, int));
-static void s390_output_constant_pool PARAMS ((FILE *));
-static rtx s390_force_const_mem_late PARAMS ((rtx));
-static rtx s390_force_const_mem_symbol PARAMS ((const char *, int, int));
+static int find_unused_clobbered_reg PARAMS ((void));
+static void s390_frame_info PARAMS ((struct s390_frame *));
+static rtx save_fpr PARAMS ((rtx, int, int));
+static rtx restore_fpr PARAMS ((rtx, int, int));
static int s390_function_arg_size PARAMS ((enum machine_mode, tree));
return mnemonic[mask];
}
+/* If OP is an integer constant of mode MODE with exactly one
+ HImode subpart unequal to DEF, return the number of that
+ subpart. As a special case, all HImode subparts of OP are
+ equal to DEF, return zero. Otherwise, return -1. */
+
+int
+s390_single_hi (op, mode, def)
+ rtx op;
+ enum machine_mode mode;
+ int def;
+{
+ if (GET_CODE (op) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT value;
+ int n_parts = GET_MODE_SIZE (mode) / 2;
+ int i, part = -1;
+
+ for (i = 0; i < n_parts; i++)
+ {
+ if (i == 0)
+ value = (unsigned HOST_WIDE_INT) INTVAL (op);
+ else
+ value >>= 16;
+
+ if ((value & 0xffff) != (unsigned)(def & 0xffff))
+ {
+ if (part != -1)
+ return -1;
+ else
+ part = i;
+ }
+ }
+
+ return part == -1 ? 0 : (n_parts - 1 - part);
+ }
+
+ else if (GET_CODE (op) == CONST_DOUBLE
+ && GET_MODE (op) == VOIDmode)
+ {
+ unsigned HOST_WIDE_INT value;
+ int n_parts = GET_MODE_SIZE (mode) / 2;
+ int i, part = -1;
+
+ for (i = 0; i < n_parts; i++)
+ {
+ if (i == 0)
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+ else if (i == HOST_BITS_PER_WIDE_INT / 16)
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op);
+ else
+ value >>= 16;
+
+ if ((value & 0xffff) != (unsigned)(def & 0xffff))
+ {
+ if (part != -1)
+ return -1;
+ else
+ part = i;
+ }
+ }
+
+ return part == -1 ? 0 : (n_parts - 1 - part);
+ }
+
+ return -1;
+}
+
+/* Extract the HImode part number PART from integer
+ constant OP of mode MODE. */
+
+int
+s390_extract_hi (op, mode, part)
+ rtx op;
+ enum machine_mode mode;
+ int part;
+{
+ int n_parts = GET_MODE_SIZE (mode) / 2;
+ if (part < 0 || part >= n_parts)
+ abort();
+ else
+ part = n_parts - 1 - part;
+
+ if (GET_CODE (op) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT value = (unsigned HOST_WIDE_INT) INTVAL (op);
+ return ((value >> (16 * part)) & 0xffff);
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE
+ && GET_MODE (op) == VOIDmode)
+ {
+ unsigned HOST_WIDE_INT value;
+ if (part < HOST_BITS_PER_WIDE_INT / 16)
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+ else
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op),
+ part -= HOST_BITS_PER_WIDE_INT / 16;
+
+ return ((value >> (16 * part)) & 0xffff);
+ }
+
+ abort ();
+}
+
+/* If OP is an integer constant of mode MODE with exactly one
+ QImode subpart unequal to DEF, return the number of that
+ subpart. As a special case, all QImode subparts of OP are
+ equal to DEF, return zero. Otherwise, return -1. */
+
+int
+s390_single_qi (op, mode, def)
+ rtx op;
+ enum machine_mode mode;
+ int def;
+{
+ if (GET_CODE (op) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT value;
+ int n_parts = GET_MODE_SIZE (mode);
+ int i, part = -1;
+
+ for (i = 0; i < n_parts; i++)
+ {
+ if (i == 0)
+ value = (unsigned HOST_WIDE_INT) INTVAL (op);
+ else
+ value >>= 8;
+
+ if ((value & 0xff) != (unsigned)(def & 0xff))
+ {
+ if (part != -1)
+ return -1;
+ else
+ part = i;
+ }
+ }
+
+ return part == -1 ? 0 : (n_parts - 1 - part);
+ }
+
+ else if (GET_CODE (op) == CONST_DOUBLE
+ && GET_MODE (op) == VOIDmode)
+ {
+ unsigned HOST_WIDE_INT value;
+ int n_parts = GET_MODE_SIZE (mode);
+ int i, part = -1;
+
+ for (i = 0; i < n_parts; i++)
+ {
+ if (i == 0)
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+ else if (i == HOST_BITS_PER_WIDE_INT / 8)
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op);
+ else
+ value >>= 8;
+
+ if ((value & 0xff) != (unsigned)(def & 0xff))
+ {
+ if (part != -1)
+ return -1;
+ else
+ part = i;
+ }
+ }
+
+ return part == -1 ? 0 : (n_parts - 1 - part);
+ }
+
+ return -1;
+}
+
+/* Extract the QImode part number PART from integer
+ constant OP of mode MODE. */
+
+int
+s390_extract_qi (op, mode, part)
+ rtx op;
+ enum machine_mode mode;
+ int part;
+{
+ int n_parts = GET_MODE_SIZE (mode);
+ if (part < 0 || part >= n_parts)
+ abort();
+ else
+ part = n_parts - 1 - part;
+
+ if (GET_CODE (op) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT value = (unsigned HOST_WIDE_INT) INTVAL (op);
+ return ((value >> (8 * part)) & 0xff);
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE
+ && GET_MODE (op) == VOIDmode)
+ {
+ unsigned HOST_WIDE_INT value;
+ if (part < HOST_BITS_PER_WIDE_INT / 8)
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (op);
+ else
+ value = (unsigned HOST_WIDE_INT) CONST_DOUBLE_HIGH (op),
+ part -= HOST_BITS_PER_WIDE_INT / 8;
+
+ return ((value >> (8 * part)) & 0xff);
+ }
+
+ abort ();
+}
+
/* Change optimizations to be performed, depending on the
optimization level.
#endif
}
+void
+override_options ()
+{
+ /* Acquire a unique set number for our register saves and restores. */
+ s390_sr_alias_set = new_alias_set ();
+}
+
/* Map for smallest class containing reg regno. */
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
FP_REGS, FP_REGS, FP_REGS, FP_REGS,
- ADDR_REGS, NO_REGS
+ ADDR_REGS, NO_REGS, ADDR_REGS
};
return op == CONST0_RTX (mode);
}
-/* Return true if OP a (const_int 1) operand.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-const1_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- return op == CONST1_RTX (mode);
-}
-
-/* Return true if OP needs base and index register. */
-
-static int
-base_n_index_p (op)
- register rtx op;
-{
- if ((GET_CODE (op) == PLUS) &&
- (GET_CODE (XEXP (op, 0)) == PLUS ||
- GET_CODE (XEXP (op, 1)) == PLUS ||
- GET_CODE (XEXP (op, 1)) == REG ))
- return 1;
- return 0;
-}
-
/* Return true if the mode of operand OP matches MODE.
If MODE is set to VOIDmode, set it to the mode of OP. */
return 0;
}
-/* Return true if OP is a valid S operand for an RS, SI or SS type instruction.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-s_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- register enum rtx_code code = GET_CODE (op);
-
- if (! check_mode (op,&mode))
- return 0;
-
- if (code == MEM) {
- if (base_n_index_p (XEXP (op, 0)))
- return 0;
- }
-
- return memory_operand (op, mode);
-}
-
-/* Return 1 if OP is a valid R or S operand for an RS, SI or SS type
- instruction.
+/* Helper routine to implement s_operand and s_imm_operand.
OP is the current operation.
- MODE is the current operation mode. */
+ MODE is the current operation mode.
+ ALLOW_IMMEDIATE specifies whether immediate operands should
+ be accepted or not. */
-int
-r_or_s_operand (op, mode)
+static int
+general_s_operand (op, mode, allow_immediate)
register rtx op;
enum machine_mode mode;
+ int allow_immediate;
{
- register enum rtx_code code = GET_CODE (op);
+ struct s390_address addr;
+ /* Call general_operand first, so that we don't have to
+ check for many special cases. */
if (!general_operand (op, mode))
return 0;
- if (code == MEM) {
- if (base_n_index_p (XEXP (op, 0)))
- return 0;
- else
- return memory_operand (op, mode);
- }
- return register_operand (op, mode);
-}
+ /* Just like memory_operand, allow (subreg (mem ...))
+ after reload. */
+ if (reload_completed
+ && GET_CODE (op) == SUBREG
+ && GET_CODE (SUBREG_REG (op)) == MEM)
+ op = SUBREG_REG (op);
-/* Return true if OP is a valid R or S or immediate operand for
- RS, SI or SS type instruction.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-r_or_s_or_im8_operand (op, mode)
- register rtx op;
- enum machine_mode mode;
-{
- register enum rtx_code code = GET_CODE (op);
+ switch (GET_CODE (op))
+ {
+ /* Constants that we are sure will be forced to the
+ literal pool in reload are OK as s-operand. Note
+ that we cannot call s390_preferred_reload_class here
+ because it might not be known yet at this point
+ whether the current function is a leaf or not. */
+ case CONST_INT:
+ case CONST_DOUBLE:
+ if (!allow_immediate || reload_completed)
+ break;
+ if (!legitimate_reload_constant_p (op))
+ return 1;
+ if (!TARGET_64BIT)
+ return 1;
+ break;
+
+ /* Memory operands are OK unless they already use an
+ index register. */
+ case MEM:
+ if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
+ return 1;
+ if (s390_decompose_address (XEXP (op, 0), &addr, FALSE)
+ && !addr.indx)
+ return 1;
+ break;
- if (!general_operand (op, mode))
- return 0;
+ default:
+ break;
+ }
- if (code == MEM) {
- if (base_n_index_p (XEXP (op, 0)))
- return 0;
- else
- return memory_operand (op, mode);
- }
- return register_operand (op, mode) || immediate_operand (op, mode);
+ return 0;
}
-/* Return true if OP is a valid R or X or 16 bit immediate operand for
- RX, RR or RI type instruction.
+/* Return true if OP is a valid S-type operand.
OP is the current operation.
MODE is the current operation mode. */
int
-r_or_x_or_im16_operand (op, mode)
+s_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
-
- if (! general_operand (op, mode))
- return 0;
-
- if (GET_CODE (op) == CONST_INT)
- return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'));
- return register_operand (op, mode) || memory_operand (op, mode);
+ return general_s_operand (op, mode, 0);
}
-/* Return true if OP is a valid R or 8 bit immediate operand.
+/* Return true if OP is a valid S-type operand or an immediate
+ operand that can be addressed as S-type operand by forcing
+ it into the literal pool.
OP is the current operation.
MODE is the current operation mode. */
int
-r_or_im8_operand (op, mode)
+s_imm_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
-
- if (!general_operand (op, mode))
- return 0;
-
- if (GET_CODE (op) == CONST_INT)
- return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'J'));
- return register_operand (op, mode) || memory_operand (op, mode);
-}
-
-/* Return true if OP is a valid operand for the 'test under mask'
- instruction with 16 bit immediate.
- The value should only have set bits in one halfword.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-tmxx_operand (op, mode)
- register rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
-{
- rtx con;
- if (GET_CODE (op) == CONST_INT)
- return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
- if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == SYMBOL_REF &&
- CONSTANT_POOL_ADDRESS_P (XEXP (op, 0)))
- {
- con = get_pool_constant (XEXP (op, 0));
-
- if (GET_CODE (con) == CONST_INT)
- {
- unsigned HOST_WIDEST_INT c;
-
- c = (unsigned HOST_WIDEST_INT) INTVAL (con);
-
- return ((c & 0xffff) ? ((c & 0xffffffffffff0000ULL)==0) :
- (c & 0xffff0000U) ? ((c & 0xffffffff0000ffffULL)==0) :
- (c & 0xffff00000000ULL) ? ((c & 0xffff0000ffffffffULL)==0) :
- (c & 0xffff000000000000ULL) ? ((c & 0xffffffffffffULL)==0) : 1);
-
- }
- }
- return 0;
+ return general_s_operand (op, mode, 1);
}
/* Return true if OP is a valid operand for the BRAS instruction.
int count = XVECLEN (op, 0);
unsigned int dest_regno;
rtx src_addr;
- int i;
+ int i, off;
/* Perform a quick check so we don't blow up below. */
dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+ /* Check, is base, or base + displacement. */
+
+ if (GET_CODE (src_addr) == REG)
+ off = 0;
+ else if (GET_CODE (src_addr) == PLUS
+ && GET_CODE (XEXP (src_addr, 0)) == REG
+ && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
+ {
+ off = INTVAL (XEXP (src_addr, 1));
+ src_addr = XEXP (src_addr, 0);
+ }
+ else
+ return 0;
+
+ if (src_addr == frame_pointer_rtx || src_addr == arg_pointer_rtx)
+ return 0;
+
for (i = 1; i < count; i++)
{
rtx elt = XVECEXP (op, 0, i);
|| GET_CODE (XEXP (SET_SRC (elt), 0)) != PLUS
|| ! rtx_equal_p (XEXP (XEXP (SET_SRC (elt), 0), 0), src_addr)
|| GET_CODE (XEXP (XEXP (SET_SRC (elt), 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1)) != i * 4)
+ || INTVAL (XEXP (XEXP (SET_SRC (elt), 0), 1))
+ != off + i * UNITS_PER_WORD)
return 0;
}
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- int count = XVECLEN (op, 0) - 1;
+ int count = XVECLEN (op, 0);
unsigned int src_regno;
rtx dest_addr;
- int i;
+ int i, off;
/* Perform a quick check so we don't blow up below. */
if (count <= 1
src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+ /* Check, is base, or base + displacement. */
+
+ if (GET_CODE (dest_addr) == REG)
+ off = 0;
+ else if (GET_CODE (dest_addr) == PLUS
+ && GET_CODE (XEXP (dest_addr, 0)) == REG
+ && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
+ {
+ off = INTVAL (XEXP (dest_addr, 1));
+ dest_addr = XEXP (dest_addr, 0);
+ }
+ else
+ return 0;
+
+ if (dest_addr == frame_pointer_rtx || dest_addr == arg_pointer_rtx)
+ return 0;
+
for (i = 1; i < count; i++)
{
rtx elt = XVECEXP (op, 0, i);
|| GET_CODE (XEXP (SET_DEST (elt), 0)) != PLUS
|| ! rtx_equal_p (XEXP (XEXP (SET_DEST (elt), 0), 0), dest_addr)
|| GET_CODE (XEXP (XEXP (SET_DEST (elt), 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1)) != i * 4)
+ || INTVAL (XEXP (XEXP (SET_DEST (elt), 0), 1))
+ != off + i * UNITS_PER_WORD)
return 0;
}
return 1;
legitimate_pic_operand_p (op)
register rtx op;
{
- /* All non-symbolic constants that made it
- up to here are fine. */
+ /* Accept all non-symbolic constants. */
if (!SYMBOLIC_CONST (op))
return 1;
legitimate_constant_p (op)
register rtx op;
{
- /* Reject doubles and integers out of range. */
- if (GET_CODE (op) == CONST_DOUBLE ||
- (GET_CODE (op) == CONST_INT &&
- (INTVAL (op) < -32768 || INTVAL (op) > 32767)))
- return 0;
-
- /* Accept all other non-symbolic constants. */
+ /* Accept all non-symbolic constants. */
if (!SYMBOLIC_CONST (op))
return 1;
return 0;
}
+/* Returns true if the constant value OP is a legitimate general
+ operand during and after reload. The difference to
+ legitimate_constant_p is that this function will not accept
+ a constant that would need to be forced to the literal pool
+ before it can be used as operand. */
+
+int
+legitimate_reload_constant_p (op)
+ register rtx op;
+{
+ /* Accept l(g)hi operands. */
+ if (GET_CODE (op) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (op), 'K'))
+ return 1;
+
+ /* Accept lliXX operands. */
+ if (TARGET_64BIT
+ && s390_single_hi (op, DImode, 0) >= 0)
+ return 1;
+
+ /* Accept larl operands. */
+ if (TARGET_64BIT
+ && larl_operand (op, VOIDmode))
+ return 1;
+
+ /* If reload is completed, and we do not already have a
+ literal pool, and OP must be forced to the literal
+ pool, then something must have gone wrong earlier.
+ We *cannot* force the constant any more, because the
+ prolog generation already decided we don't need to
+ set up the base register. */
+ if (reload_completed && !regs_ever_live[BASE_REGISTER])
+ abort ();
+
+ /* Everything else cannot be handled without reload. */
+ return 0;
+}
+
+/* Given an rtx OP being reloaded into a reg required to be in class CLASS,
+ return the class of reg to actually use. */
+
+enum reg_class
+s390_preferred_reload_class (op, class)
+ rtx op;
+ enum reg_class class;
+{
+ /* This can happen if a floating point constant is being
+ reloaded into an integer register. Leave well alone. */
+ if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
+ && class != FP_REGS)
+ return class;
+
+ switch (GET_CODE (op))
+ {
+ /* Constants we cannot reload must be forced into the
+ literal pool. For constants we *could* handle directly,
+ it might still be preferable to put them in the pool and
+ use a memory-to-memory instruction.
+
+ However, try to avoid needlessly allocating a literal
+ pool in a routine that wouldn't otherwise need any.
+ Heuristically, we assume that 64-bit leaf functions
+ typically don't need a literal pool, all others do. */
+ case CONST_DOUBLE:
+ case CONST_INT:
+ if (!legitimate_reload_constant_p (op))
+ return NO_REGS;
+
+ if (TARGET_64BIT && current_function_is_leaf)
+ return class;
+
+ return NO_REGS;
+
+ /* If a symbolic constant or a PLUS is reloaded,
+ it is most likely being used as an address. */
+ case PLUS:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ case CONST:
+ return ADDR_REGS;
+
+ default:
+ break;
+ }
+
+ return class;
+}
/* Decompose a RTL expression ADDR for a memory address into
its components, returned in OUT. The boolean STRICT
if (addr.base && GET_CODE (addr.base) == REG)
{
if (REGNO (addr.base) == BASE_REGISTER
- || REGNO (addr.base) == STACK_POINTER_REGNUM)
+ || REGNO (addr.base) == STACK_POINTER_REGNUM
+ || REGNO (addr.base) == FRAME_POINTER_REGNUM)
return TRUE;
}
if (addr.indx && GET_CODE (addr.indx) == REG)
{
if (REGNO (addr.indx) == BASE_REGISTER
- || REGNO (addr.indx) == STACK_POINTER_REGNUM)
+ || REGNO (addr.indx) == STACK_POINTER_REGNUM
+ || REGNO (addr.base) == FRAME_POINTER_REGNUM)
return TRUE;
}
rtx *operands;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
+ rtx temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
operands[1] = force_reg (Pmode, operands[1]);
struct s390_address ad;
if (!s390_decompose_address (addr, &ad, TRUE))
- output_operand_lossage ("cannot decompose address.\n");
+ output_operand_lossage ("Cannot decompose address.");
if (ad.disp)
s390_output_symbolic_const (file, ad.disp);
case CONST_INT:
if (code == 'b')
- fprintf (file, "%d", (int)(INTVAL (x) & 0xff));
- else if (code == 'X')
- fprintf (file, "%d", (int)(INTVAL (x) & 0xff));
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
+ else if (code == 'x')
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffff);
+ else if (code == 'h')
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xffff) ^ 0x8000) - 0x8000);
+ else
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
+ break;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (x) != VOIDmode)
+ abort ();
+ if (code == 'b')
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xff);
else if (code == 'x')
- fprintf (file, "0x%x", (int)(INTVAL (x) & 0xffff));
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xffff);
else if (code == 'h')
- fprintf (file, "%d", (int)(INTVAL (x) << 16) >> 16);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((CONST_DOUBLE_LOW (x) & 0xffff) ^ 0x8000) - 0x8000);
else
- fprintf (file, "%d", (int)INTVAL (x));
+ abort ();
break;
default:
XEXP (x, 0), 0))
return 1;
}
+ else if (code == SET
+ && GET_CODE (SET_DEST (x)) == PC)
+ {
+ if (refers_to_regno_p (regno, regno+1,
+ SET_SRC (x), 0))
+ return 1;
+ }
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
rtx dep_rtx;
rtx insn;
{
- rtx target;
+ rtx target, pat;
if (GET_CODE (dep_rtx) == SET)
{
int regno = REGNO (target);
if (get_attr_type (insn) == TYPE_LA)
- return refers_to_regno_p (regno, regno+1,
- SET_SRC (PATTERN (insn)), 0);
- else if (get_attr_atype (insn) == ATYPE_MEM)
- return reg_used_in_mem_p (regno, PATTERN (insn));
- }
+ {
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == PARALLEL)
+ {
+ if (XVECLEN (pat, 0) != 2)
+ abort();
+ pat = XVECEXP (pat, 0, 0);
+ }
+ if (GET_CODE (pat) == SET)
+ return refers_to_regno_p (regno, regno+1, SET_SRC (pat), 0);
+ else
+ abort();
+ }
+ else if (get_attr_atype (insn) == ATYPE_MEM)
+ return reg_used_in_mem_p (regno, PATTERN (insn));
+ }
}
return 0;
}
if (priority >= 0 && priority < 0x01000000)
priority <<= 3;
break;
+ case TYPE_LM:
+ /* LM in epilogue should never be scheduled. This
+ is due to literal access done in function body.
+ The usage of register 13 is not mentioned explicitly,
+ leading to scheduling 'LM' accross this instructions.
+ */
+ priority = 0x7fffffff;
+ break;
}
return priority;
int addr, naddr = 0, uids;
int chunk_max = 0;
- const char *asms;
-
int size = insn_current_address;
int *ltorg_uids;
warning ("no code label found");
}
}
- else if (GET_CODE (PATTERN (insn)) == ASM_INPUT && !TARGET_64BIT)
- {
- asms = XSTR (PATTERN (insn),0);
-
- if ((memcmp (asms,".section",8) == 0) ||
- (memcmp (asms,".text",5) == 0) ||
- (memcmp (asms,"\t.section",9) == 0) ||
- (memcmp (asms,"\t.text",6) == 0)) {
- ltorg_uids[max_ltorg++] = INSN_UID (insn);
- INSN_ADDRESSES_NEW (emit_insn_before (gen_rtx_ASM_INPUT (VOIDmode,
- ".align 4"), insn), -1);
- }
- }
}
ltorg_uids[max_ltorg] = 0;
for (insn=get_insns (),uids=0; insn;insn = next_real_insn (insn))
function_section (current_function_decl);
}
-
-#ifdef DWARF2_DEBUGGING_INFO
-extern char *dwarf2out_cfi_label PARAMS ((void));
-#endif
-
-/* Flag set in prologue, used in epilog to know
- if stack is allocated or not. */
-static int leaf_function_flag;
-
-/* Symbol references needed by the profile code;
- set up by the function prologue routine if necessary. */
-rtx s390_profile[10];
-
/* Number of elements of current constant pool. */
int s390_nr_constants;
return 0;
}
-/* Return true if urrent function is a leaf function,
- without automatics, alloca or vararg stuff. */
-
-static int
-cur_is_leaf_function ()
-{
- int lsize = get_frame_size () + current_function_outgoing_args_size
- + save_fprs_p () * 64;
-
- if (leaf_function_p () && ((lsize) == 0) &&
- ! (current_function_calls_alloca) &&
- ! (current_function_stdarg) && ! (current_function_varargs))
- return 1;
- return 0;
-}
-
-/* Return offset between argument pointer and frame pointer
- initially after prologue. */
-
-int
-s390_arg_frame_offset ()
-{
- int lsize = get_frame_size () + current_function_outgoing_args_size
- + save_fprs_p () * 64;
-
- if (cur_is_leaf_function ())
- return STACK_POINTER_OFFSET;
- else
- return 2*STACK_POINTER_OFFSET + lsize;
-}
-
-/* Output code to stdio stream FILE to save floating point
- registers on current stack, at offset OFFSET to the frame
- pointer register FP. */
-
-static int
-save_fprs (file, offset, fp)
- FILE *file;
- long offset;
- int fp;
-{
- int i;
-
- if (!TARGET_64BIT)
- return 0;
-
- for (i=24; i<=31; i++)
- {
- if (regs_ever_live[i] == 1)
- {
- fprintf (file, "\tstd\t%s,%ld(%s)\n", reg_names[i],
- (i-24) * 8 + offset, reg_names[fp]);
- }
- }
-
- return 1;
-}
-
-/* Output code to stdio stream FILE to restore floating point
- registers from current stack, at offset OFFSET to the frame
- pointer register FP. */
-
-static int
-restore_fprs (file, offset, fp)
- FILE *file;
- long offset;
- int fp;
-{
- int i;
-
- if (!TARGET_64BIT)
- return 0;
-
- if (!save_fprs_p ())
- return 0;
-
- if (offset < 0)
- {
- fp = 1;
- offset = 0;
- fprintf (file, "\tlgr\t%s,%s\n", reg_names[fp],
- reg_names[STACK_POINTER_REGNUM]);
- fprintf (file, "\taghi\t%s,-64\n", reg_names[fp]);
- }
-
- for (i=24; i<=31; i++)
- {
- if (regs_ever_live[i] == 1)
- {
- fprintf (file, "\tld\t%s,%ld(%s)\n", reg_names[i],
- (i-24) * 8 + offset, reg_names[fp]);
- }
- }
-
- return 1;
-}
-
/* Output main constant pool to stdio stream FILE. */
-static void
+void
s390_output_constant_pool (file)
FILE *file;
{
/* Output constant pool. */
- if (s390_nr_constants || regs_ever_live[BASE_REGISTER])
+ if (s390_nr_constants)
{
s390_pool_count = 0;
if (TARGET_64BIT)
s390_pool_count);
if (TARGET_64BIT)
function_section (current_function_decl);
-
- regs_ever_live[BASE_REGISTER] = 1;
}
}
-/* Add constant CTX to the constant pool at a late time
- (after the initial pass to count the number of constants
- was already done). Returns the resulting constant
- pool reference. */
+/* Find first call clobbered register unsused in a function.
+ This could be used as base register in a leaf function
+ or for holding the return address before epilogue. */
-static rtx
-s390_force_const_mem_late (cst)
- rtx cst;
+static int
+find_unused_clobbered_reg ()
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ if (!regs_ever_live[i])
+ return i;
+ return 0;
+}
+
+/* Fill FRAME with info about frame of current function. */
+
+static void
+s390_frame_info (frame)
+ struct s390_frame *frame;
+{
+ int i, j;
+ HOST_WIDE_INT fsize = get_frame_size ();
+
+ if (fsize > 0x7fff0000)
+ fatal_error ("Total size of local variables exceeds architecture limit.");
+
+ /* fprs 8 - 15 are caller saved for 64 Bit ABI. */
+ frame->save_fprs_p = save_fprs_p ();
+
+ frame->frame_size = fsize + frame->save_fprs_p * 64;
+
+ /* Does function need to setup frame and save area. */
+
+ if (! current_function_is_leaf
+ || frame->frame_size > 0
+ || current_function_calls_alloca
+ || current_function_stdarg
+ || current_function_varargs)
+ frame->frame_size += STARTING_FRAME_OFFSET;
+
+ /* If we need to allocate a frame, the stack pointer is changed. */
+
+ if (frame->frame_size > 0)
+ regs_ever_live[STACK_POINTER_REGNUM] = 1;
+
+ /* If there is (possibly) any pool entry, we need to
+ load base register. */
+
+ if (get_pool_size ()
+ || !CONST_OK_FOR_LETTER_P (frame->frame_size, 'K')
+ || (!TARGET_64BIT && current_function_uses_pic_offset_table))
+ regs_ever_live[BASE_REGISTER] = 1;
+
+ /* If we need the GOT pointer, remember to save/restore it. */
+
+ if (current_function_uses_pic_offset_table)
+ regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ /* Frame pointer needed. */
+
+ frame->frame_pointer_p = frame_pointer_needed;
+
+ /* Find first and last gpr to be saved. */
+
+ for (i = 6; i < 16; i++)
+ if (regs_ever_live[i])
+ break;
+
+ for (j = 15; j > i; j--)
+ if (regs_ever_live[j])
+ break;
+
+ if (i == 16)
+ {
+ /* Nothing to save / restore. */
+ frame->first_save_gpr = -1;
+ frame->first_restore_gpr = -1;
+ frame->last_save_gpr = -1;
+ frame->return_reg_saved_p = 0;
+ }
+ else
+ {
+ /* Save / Restore from gpr i to j. */
+ frame->first_save_gpr = i;
+ frame->first_restore_gpr = i;
+ frame->last_save_gpr = j;
+ frame->return_reg_saved_p = (j >= RETURN_REGNUM && i <= RETURN_REGNUM);
+ }
+
+ if (current_function_stdarg || current_function_varargs)
+ {
+ /* Varargs function need to save from gpr 2 to gpr 15. */
+ frame->first_save_gpr = 2;
+ }
+}
+
+/* Return offset between argument pointer and frame pointer
+ initially after prologue. */
+
+int
+s390_arg_frame_offset ()
{
- cst = force_const_mem (Pmode, cst);
+ struct s390_frame frame;
- s390_nr_constants++;
- regs_ever_live[BASE_REGISTER] = 1;
+ /* Compute frame_info. */
- emit_insn_before (gen_rtx (USE, Pmode, cst), get_insns ());
+ s390_frame_info (&frame);
- return cst;
+ return frame.frame_size + STACK_POINTER_OFFSET;
}
-/* Add a reference to the symbol NAME to the constant pool.
- FUNC specifies whether NAME refers to a function, while
- GLOBAL specifies whether NAME is a global symbol. Depending
- on these flags, the appopriate PLT or GOT references are
- generated. Returns the constant pool reference. */
+/* Emit insn to save fpr REGNUM at offset OFFSET relative
+ to register BASE. Return generated insn. */
static rtx
-s390_force_const_mem_symbol (name, func, global)
- const char *name;
- int func;
- int global;
+save_fpr (base, offset, regnum)
+ rtx base;
+ int offset;
+ int regnum;
{
- rtx symbol;
+ rtx addr;
+ addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
+ set_mem_alias_set (addr, s390_sr_alias_set);
- if (TARGET_64BIT)
- abort ();
+ return emit_move_insn (addr, gen_rtx_REG (DFmode, regnum));
+}
- symbol = gen_rtx (SYMBOL_REF, Pmode, name);
- SYMBOL_REF_FLAG (symbol) = !global;
+/* Emit insn to restore fpr REGNUM from offset OFFSET relative
+ to register BASE. Return generated insn. */
- if (flag_pic)
- {
- if (global)
- {
- current_function_uses_pic_offset_table = 1;
- symbol = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, symbol), func? 114 : 112);
- symbol = gen_rtx_CONST (VOIDmode, symbol);
- }
- else
- {
- symbol = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, symbol), 100);
- symbol = gen_rtx_CONST (VOIDmode, symbol);
- }
- }
+static rtx
+restore_fpr (base, offset, regnum)
+ rtx base;
+ int offset;
+ int regnum;
+{
+ rtx addr;
+ addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
+ set_mem_alias_set (addr, s390_sr_alias_set);
- return s390_force_const_mem_late (symbol);
+ return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
}
/* Output the function prologue assembly code to the
void
s390_function_prologue (file, lsize)
- FILE *file;
- HOST_WIDE_INT lsize;
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT lsize ATTRIBUTE_UNUSED;
{
- extern int profile_label_no;
- int i, j;
- long frame_size;
- rtx stack_label = 0, got_label = 0;
- char *l;
- const char *const b64 = TARGET_64BIT ? "g" : "";
+ if (get_pool_size () > S390_POOL_MAX)
+ s390_final_chunkify (1);
+ else
+ s390_final_chunkify (0);
+}
- /* Check for too large size of local variables */
+/* Output the function epilogue assembly code to the
+ stdio stream FILE. The local frame size is passed
+ in LSIZE. */
- if (lsize > 0x7fff0000)
- fatal_error ("total size of local variables exceeds architecture limit");
+void
+s390_function_epilogue (file, lsize)
+ FILE *file ATTRIBUTE_UNUSED;
+ HOST_WIDE_INT lsize ATTRIBUTE_UNUSED;
+{
+ current_function_uses_pic_offset_table = 0;
+ s390_pool_start_insn = NULL_RTX;
+ s390_pool_count = -1;
+ s390_function_count++;
+}
- /* Profile code (-p, -a, -ax needs some literals). */
+/* Expand the prologue into a bunch of separate insns. */
- if (profile_flag && !TARGET_64BIT)
- {
- static char label[128];
- sprintf (label, "%sP%d", LPREFIX, profile_label_no);
+void
+s390_emit_prologue ()
+{
+ struct s390_frame frame;
+ rtx insn, addr;
+ rtx temp_reg;
+ int i, limit;
- s390_profile[4] = s390_force_const_mem_symbol ("_mcount", 1, 1);
- s390_profile[9] = s390_force_const_mem_symbol (label, 0, 0);
- }
+ /* Compute frame_info. */
- if (get_pool_size () > S390_POOL_MAX)
- s390_final_chunkify (1);
+ s390_frame_info (&frame);
+
+ /* Choose best register to use for temp use within prologue. */
+
+ if (frame.return_reg_saved_p
+ && !has_hard_reg_initial_val (Pmode, RETURN_REGNUM))
+ temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
else
- s390_final_chunkify (0);
+ temp_reg = gen_rtx_REG (Pmode, 1);
- if (current_function_uses_pic_offset_table)
- regs_ever_live[12] = 1;
+ /* Save call saved gprs. */
- if (!TARGET_64BIT && current_function_uses_pic_offset_table)
+ if (frame.first_save_gpr != -1)
{
- got_label = s390_force_const_mem_symbol ("_GLOBAL_OFFSET_TABLE_", 0, 0);
- }
+ addr = plus_constant (stack_pointer_rtx,
+ frame.first_save_gpr * UNITS_PER_WORD);
+ addr = gen_rtx_MEM (Pmode, addr);
+ set_mem_alias_set (addr, s390_sr_alias_set);
- if ((frame_size =
- STARTING_FRAME_OFFSET + lsize + save_fprs_p () * 64) > 0x7fff)
- {
- stack_label = s390_force_const_mem_late (GEN_INT (frame_size));
- }
+ if (frame.first_save_gpr != frame.last_save_gpr )
+ {
+ insn = emit_insn (gen_store_multiple (addr,
+ gen_rtx_REG (Pmode, frame.first_save_gpr),
+ GEN_INT (frame.last_save_gpr
+ - frame.first_save_gpr + 1)));
- if (!optimize)
- {
- /* Stupid register allocation is stupid ...
- It does not always recognize the base register is used. */
-
- regs_ever_live[BASE_REGISTER] = 1;
- }
-
- if (cur_is_leaf_function ())
- {
- leaf_function_flag = 1;
- fprintf (file, "%s\tleaf function\n", ASM_COMMENT_START);
- fprintf (file, "%s\thas varargs %d\n", ASM_COMMENT_START,
- current_function_stdarg);
- fprintf (file, "%s\tincoming args (stack) %d\n", ASM_COMMENT_START,
- current_function_args_size);
- fprintf (file, "%s\tfunction length %d\n", ASM_COMMENT_START,
- insn_current_address);
- fprintf (file, "%s\tregister live ", ASM_COMMENT_START);
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- fprintf (file, "%d", regs_ever_live[i]);
- fputc ('\n',file);
-
- /* Save gprs 6 - 15 and fprs 4 and 6. */
- for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+ /* Set RTX_FRAME_RELATED_P for all sets within store multiple. */
- if (s390_nr_constants || regs_ever_live[13] || i != 13)
- {
- fprintf (file, "\tstm%s\t%s,%s,%d(%s)\n",
- b64, reg_names[i], reg_names[13],
- i * UNITS_PER_WORD,
- reg_names[STACK_POINTER_REGNUM]);
-#ifdef INCOMING_RETURN_ADDR_RTX
- if (dwarf2out_do_frame ())
+ limit = XVECLEN (PATTERN (insn), 0);
+
+ for (i = 0; i < limit; i++)
{
- l = dwarf2out_cfi_label ();
- dwarf2out_def_cfa (l, STACK_POINTER_REGNUM,
- STACK_POINTER_OFFSET);
- for (j = i; j <= 14; j++)
- dwarf2out_reg_save (l, j, (TARGET_64BIT ? (j-20) : (j-24))
- * UNITS_PER_WORD);
- if (regs_ever_live[18])
- dwarf2out_reg_save (l, 18, -16);
- if (regs_ever_live[19])
- dwarf2out_reg_save (l, 19, -8);
+ rtx x = XVECEXP (PATTERN (insn), 0, i);
+
+ if (GET_CODE (x) == SET)
+ RTX_FRAME_RELATED_P (x) = 1;
}
-#endif
}
-
- s390_output_constant_pool (file);
-
- /* Save fprs. */
-
- if (!TARGET_64BIT)
+ else
{
- if (regs_ever_live[18])
- fprintf (file, "\tstd\t4,80(%s)\n", reg_names[STACK_POINTER_REGNUM]);
- if (regs_ever_live[19])
- fprintf (file, "\tstd\t6,88(%s)\n", reg_names[STACK_POINTER_REGNUM]);
+ insn = emit_move_insn (addr,
+ gen_rtx_REG (Pmode, frame.first_save_gpr));
}
+ RTX_FRAME_RELATED_P (insn) = 1;
}
- else
- { /* No leaf function. */
- fprintf (file, "%s\tleaf function %d\n", ASM_COMMENT_START,
- leaf_function_p ());
- fprintf (file, "%s\tautomatics %d\n", ASM_COMMENT_START,
- (int)lsize);
- fprintf (file, "%s\toutgoing args %d\n", ASM_COMMENT_START,
- current_function_outgoing_args_size);
- fprintf (file, "%s\tneed frame pointer %d\n", ASM_COMMENT_START,
- frame_pointer_needed);
- fprintf (file, "%s\tcall alloca %d\n", ASM_COMMENT_START,
- current_function_calls_alloca);
- fprintf (file, "%s\thas varargs %d\n", ASM_COMMENT_START,
- current_function_stdarg || current_function_varargs);
- fprintf (file, "%s\tincoming args (stack) %d\n", ASM_COMMENT_START,
- current_function_args_size);
- fprintf (file, "%s\tfunction length %d\n", ASM_COMMENT_START,
- insn_current_address);
- fprintf (file, "%s\tregister live ", ASM_COMMENT_START);
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- fprintf (file, "%d", regs_ever_live[i]);
- fputc ('\n',file);
-
- /* Save gprs 6 - 15 and fprs 4 and 6. */
+
+ /* Dump constant pool and set constant pool register (13). */
+
+ insn = emit_insn (gen_lit ());
+
+ /* Save fprs for variable args. */
+
+ if (current_function_stdarg || current_function_varargs)
+ {
+ /* Save fpr 0 and 2. */
+
+ save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 32, 16);
+ save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 24, 17);
- if (current_function_stdarg || current_function_varargs)
- {
- i = 2;
- }
- else
+ if (TARGET_64BIT)
{
- for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+ /* Save fpr 4 and 6. */
+
+ save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 16, 18);
+ save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 8, 19);
}
+ }
- fprintf (file, "\tstm%s\t%s,%s,%d(%s)\n",
- b64, reg_names[i], reg_names[15], i * UNITS_PER_WORD,
- reg_names[STACK_POINTER_REGNUM]);
+ /* Save fprs 4 and 6 if used (31 bit ABI). */
-#ifdef INCOMING_RETURN_ADDR_RTX
- if (dwarf2out_do_frame ())
+ if (!TARGET_64BIT)
+ {
+ /* Save fpr 4 and 6. */
+ if (regs_ever_live[18])
{
- l = dwarf2out_cfi_label ();
- dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, STACK_POINTER_OFFSET);
- for (j = i; j <= 15; j++)
- dwarf2out_reg_save (l, j, (TARGET_64BIT ? (j-20) : (j-24)) *
- UNITS_PER_WORD);
- if (regs_ever_live[18])
- dwarf2out_reg_save (l, 18, -16);
- if (regs_ever_live[19])
- dwarf2out_reg_save (l, 19, -8);
+ insn = save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 16, 18);
+ RTX_FRAME_RELATED_P (insn) = 1;
}
-#endif
+ if (regs_ever_live[19])
+ {
+ insn = save_fpr (stack_pointer_rtx, STACK_POINTER_OFFSET - 8, 19);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ }
- s390_output_constant_pool (file);
+ /* Decrement stack pointer. */
- /* Save fprs. */
+ if (frame.frame_size > 0)
+ {
+ rtx frame_off = GEN_INT (-frame.frame_size);
- if (current_function_stdarg || current_function_varargs)
- {
- fprintf (file, "\tstd\t%s,%d(%s)\n",
- reg_names[16],
- STACK_POINTER_OFFSET-32,
- reg_names[STACK_POINTER_REGNUM]);
- fprintf (file, "\tstd\t%s,%d(%s)\n",
- reg_names[17],
- STACK_POINTER_OFFSET-24,
- reg_names[STACK_POINTER_REGNUM]);
- if (TARGET_64BIT)
- {
- fprintf (file, "\tstd\t%s,%d(%s)\n",
- reg_names[18],
- STACK_POINTER_OFFSET-16,
- reg_names[STACK_POINTER_REGNUM]);
- fprintf (file, "\tstd\t%s,%d(%s)\n",
- reg_names[19],
- STACK_POINTER_OFFSET-8,
- reg_names[STACK_POINTER_REGNUM]);
- }
- }
- if (!TARGET_64BIT)
+ /* Save incoming stack pointer into temp reg. */
+
+ if (TARGET_BACKCHAIN || frame.save_fprs_p)
{
- if (regs_ever_live[18])
- fprintf (file, "\tstd\t%s,%d(%s)\n",
- reg_names[18],
- STACK_POINTER_OFFSET-16,
- reg_names[STACK_POINTER_REGNUM]);
- if (regs_ever_live[19])
- fprintf (file, "\tstd\t%s,%d(%s)\n",
- reg_names[19],
- STACK_POINTER_OFFSET-8,
- reg_names[STACK_POINTER_REGNUM]);
+ insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
}
-
- if (save_fprs_p () && frame_size > 4095)
+ /* Substract frame size from stack pointer. */
+
+ frame_off = GEN_INT (-frame.frame_size);
+ if (!CONST_OK_FOR_LETTER_P (-frame.frame_size, 'K'))
+ frame_off = force_const_mem (Pmode, frame_off);
+
+ insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ GEN_INT (-frame.frame_size))),
+ REG_NOTES (insn));
+
+ /* Set backchain. */
+
+ if (TARGET_BACKCHAIN)
{
- int fp = 1;
- fprintf (file, "\tlgr\t%s,%s\n", reg_names[fp],
- reg_names[STACK_POINTER_REGNUM]);
- fprintf (file, "\taghi\t%s,-64\n", reg_names[fp]);
- save_fprs (file, 0, fp);
+ addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
+ set_mem_alias_set (addr, s390_sr_alias_set);
+ insn = emit_insn (gen_move_insn (addr, temp_reg));
}
+ }
- /* Decrement stack. */
+ /* Save fprs 8 - 15 (64 bit ABI). */
+
+ if (frame.save_fprs_p)
+ {
+ insn = emit_insn (gen_add2_insn (temp_reg, GEN_INT(-64)));
- if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
- || frame_pointer_needed
- || current_function_calls_alloca))
- {
+ for (i = 24; i < 32; i++)
+ if (regs_ever_live[i])
+ {
+ rtx addr = plus_constant (stack_pointer_rtx,
+ frame.frame_size - 64 + (i-24)*8);
+
+ insn = save_fpr (temp_reg, (i-24)*8, i);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (DFmode, addr),
+ gen_rtx_REG (DFmode, i)),
+ REG_NOTES (insn));
+ }
+ }
+
+ /* Set frame pointer, if needed. */
+
+ if (frame.frame_pointer_p)
+ {
+ insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
- fprintf (file, "\tl%sr\t%s,%s\n", b64,
- reg_names[1], reg_names[STACK_POINTER_REGNUM]);
- }
+ /* Set up got pointer, if needed. */
+
+ if (current_function_uses_pic_offset_table)
+ {
+ rtx got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ SYMBOL_REF_FLAG (got_symbol) = 1;
- if (stack_label)
+ if (TARGET_64BIT)
{
- rtx operands[2];
+ insn = emit_insn (gen_movdi (pic_offset_table_rtx,
+ got_symbol));
- operands[0] = stack_pointer_rtx;
- operands[1] = stack_label;
- if (TARGET_64BIT)
- output_asm_insn ("sg\t%0,%1", operands);
- else
- output_asm_insn ("s\t%0,%1", operands);
+ /* It can happen that the GOT pointer isn't really needed ... */
+ REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
+ REG_NOTES (insn));
}
else
{
- fprintf (file, "\ta%shi\t%s,-%ld\n",b64,
- reg_names[STACK_POINTER_REGNUM], frame_size);
- }
-#ifdef INCOMING_RETURN_ADDR_RTX
- if (dwarf2out_do_frame ())
- {
- if (frame_pointer_needed)
- dwarf2out_def_cfa ("", HARD_FRAME_POINTER_REGNUM,
- STACK_POINTER_OFFSET+frame_size);
- else
- dwarf2out_def_cfa ("", STACK_POINTER_REGNUM,
- STACK_POINTER_OFFSET+frame_size);
+ got_symbol = gen_rtx_UNSPEC (VOIDmode,
+ gen_rtvec (1, got_symbol), 100);
+ got_symbol = gen_rtx_CONST (VOIDmode, got_symbol);
+ got_symbol = force_const_mem (Pmode, got_symbol);
+ insn = emit_move_insn (pic_offset_table_rtx,
+ got_symbol);
+ insn = emit_insn (gen_add2_insn (pic_offset_table_rtx,
+ gen_rtx_REG (Pmode, BASE_REGISTER)));
+
+ /* We need the GOT pointer even if we don't know it ... */
+ emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
}
-#endif
+ }
+}
+/* Expand the epilogue into a bunch of separate insns. */
- /* Generate backchain. */
+void
+s390_emit_epilogue ()
+{
+ struct s390_frame frame;
+ rtx frame_pointer, return_reg;
+ int area_bottom, area_top, offset;
+ rtvec p;
- if (TARGET_BACKCHAIN || (frame_size + STACK_POINTER_OFFSET > 4095
- || frame_pointer_needed
- || current_function_calls_alloca))
- {
- fprintf (file, "\tst%s\t%s,0(%s)\n",
- b64, reg_names[1], reg_names[STACK_POINTER_REGNUM]);
- }
- }
+ /* Compute frame_info. */
+
+ s390_frame_info (&frame);
+
+ /* Check whether to use frame or stack pointer for restore. */
- if (frame_pointer_needed)
+ frame_pointer = frame.frame_pointer_p ?
+ hard_frame_pointer_rtx : stack_pointer_rtx;
+
+ /* Compute which parts of the save area we need to access. */
+
+ if (frame.first_restore_gpr != -1)
{
- fprintf (file, "\tl%sr\t%s,%s\n", b64,
- reg_names[FRAME_POINTER_REGNUM],
- reg_names[STACK_POINTER_REGNUM]);
+ area_bottom = frame.first_restore_gpr * UNITS_PER_WORD;
+ area_top = (frame.last_save_gpr + 1) * UNITS_PER_WORD;
+ }
+ else
+ {
+ area_bottom = INT_MAX;
+ area_top = INT_MIN;
}
- /* Load GOT if used and emit use insn that optimizer does not
- erase literal pool entry. */
-
- if (current_function_uses_pic_offset_table)
+ if (TARGET_64BIT)
{
- rtx operands[3];
- if (TARGET_64BIT)
+ if (frame.save_fprs_p)
{
- fprintf (file, "\tlarl\t%s,_GLOBAL_OFFSET_TABLE_\n",
- reg_names[PIC_OFFSET_TABLE_REGNUM]);
+ if (area_bottom > -64)
+ area_bottom = -64;
+ if (area_top < 0)
+ area_top = 0;
}
- else
+ }
+ else
+ {
+ if (regs_ever_live[18])
{
- operands[0] = gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM);
- operands[1] = got_label;
- operands[2] = gen_rtx (REG, Pmode, BASE_REGISTER);
- output_asm_insn ("l\t%0,%1\n\tar\t%0,%2", operands);
+ if (area_bottom > STACK_POINTER_OFFSET - 16)
+ area_bottom = STACK_POINTER_OFFSET - 16;
+ if (area_top < STACK_POINTER_OFFSET - 8)
+ area_top = STACK_POINTER_OFFSET - 8;
+ }
+ if (regs_ever_live[19])
+ {
+ if (area_bottom > STACK_POINTER_OFFSET - 8)
+ area_bottom = STACK_POINTER_OFFSET - 8;
+ if (area_top < STACK_POINTER_OFFSET)
+ area_top = STACK_POINTER_OFFSET;
}
}
- /* Save FPRs below save area. */
- if (frame_size <= 4095)
- save_fprs (file, frame_size - 64, STACK_POINTER_REGNUM);
+ /* Check whether we can access the register save area.
+ If not, increment the frame pointer as required. */
- return;
-}
+ if (area_top <= area_bottom)
+ {
+ /* Nothing to restore. */
+ }
+ else if (frame.frame_size + area_bottom >= 0
+ && frame.frame_size + area_top <= 4096)
+ {
+ /* Area is in range. */
+ offset = frame.frame_size;
+ }
+ else
+ {
+ rtx insn, frame_off;
-/* Output the function epilogue assembly code to the
- stdio stream FILE. The local frame size is passed
- in LSIZE. */
+ offset = area_bottom < 0 ? -area_bottom : 0;
+ frame_off = GEN_INT (frame.frame_size - offset);
-void
-s390_function_epilogue (file, lsize)
- FILE *file;
- HOST_WIDE_INT lsize;
-{
-/* Register is call clobbered and not used for eh or return. */
-#define FREE_REG 4
+ if (!CONST_OK_FOR_LETTER_P (INTVAL (frame_off), 'K'))
+ frame_off = force_const_mem (Pmode, frame_off);
- int i;
- long frame_size;
- int return_reg = RETURN_REGNUM;
- int fp, offset;
- const char *const b64 = TARGET_64BIT ? "g" : "";
+ insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
- frame_size = STARTING_FRAME_OFFSET + lsize + save_fprs_p () * 64;
-
- if (current_function_uses_pic_offset_table)
- regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
-
- if (leaf_function_flag)
+ /* Restore call saved fprs. */
+
+ if (TARGET_64BIT)
{
- for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+ int i;
- if (s390_nr_constants || regs_ever_live[13] || i != 13)
- {
- fprintf (file, "\tlm%s\t%s,%s,%d(%s)\n", b64,
- reg_names[i], reg_names[13],
- UNITS_PER_WORD * i,
- reg_names[STACK_POINTER_REGNUM]);
- }
- if (!TARGET_64BIT)
- {
- if (regs_ever_live[18])
- fprintf (file, "\tld\t%s,%d(%s)\n",
- reg_names[18],
- STACK_POINTER_OFFSET-16,
- reg_names[STACK_POINTER_REGNUM]);
- if (regs_ever_live[19])
- fprintf (file, "\tld\t%s,%d(%s)\n",
- reg_names[19],
- STACK_POINTER_OFFSET-8,
- reg_names[STACK_POINTER_REGNUM]);
- }
+ if (frame.save_fprs_p)
+ for (i = 24; i < 32; i++)
+ if (regs_ever_live[i])
+ restore_fpr (frame_pointer,
+ offset - 64 + (i-24) * 8, i);
}
else
{
- for (i = 6; i < 13 && (regs_ever_live[i] == 0); i++);
+ if (regs_ever_live[18])
+ restore_fpr (frame_pointer, offset + STACK_POINTER_OFFSET - 16, 18);
+ if (regs_ever_live[19])
+ restore_fpr (frame_pointer, offset + STACK_POINTER_OFFSET - 8, 19);
+ }
- if (frame_size + STACK_POINTER_OFFSET > 4095)
+ /* Return register. */
+
+ return_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
+
+ /* Restore call saved gprs. */
+
+ if (frame.first_restore_gpr != -1)
+ {
+ rtx addr;
+
+ /* Fetch return address from stack before load multiple,
+ this will do good for scheduling. */
+
+ if (frame.last_save_gpr >= RETURN_REGNUM
+ && frame.first_restore_gpr < RETURN_REGNUM)
{
- offset = 0;
- fp = STACK_POINTER_REGNUM;
+ int return_regnum = find_unused_clobbered_reg();
+ if (!return_regnum)
+ return_regnum = 4;
+ return_reg = gen_rtx_REG (Pmode, return_regnum);
+
+ addr = plus_constant (frame_pointer,
+ offset + RETURN_REGNUM * UNITS_PER_WORD);
+ addr = gen_rtx_MEM (Pmode, addr);
+ set_mem_alias_set (addr, s390_sr_alias_set);
+ emit_move_insn (return_reg, addr);
}
- else if (frame_pointer_needed || current_function_calls_alloca)
+
+ /* ??? As references to the base register are not made
+ explicit in insn RTX code, we have to add a barrier here
+ to prevent incorrect scheduling. */
+
+ emit_insn (gen_blockage());
+
+ addr = plus_constant (frame_pointer,
+ offset + frame.first_restore_gpr * UNITS_PER_WORD);
+ addr = gen_rtx_MEM (Pmode, addr);
+ set_mem_alias_set (addr, s390_sr_alias_set);
+
+ if (frame.first_restore_gpr != frame.last_save_gpr)
{
- offset = frame_size;
- fp = FRAME_POINTER_REGNUM;
+ emit_insn (gen_load_multiple (
+ gen_rtx_REG (Pmode, frame.first_restore_gpr),
+ addr,
+ GEN_INT (frame.last_save_gpr - frame.first_restore_gpr + 1)));
}
else
{
- offset = frame_size;
- fp = STACK_POINTER_REGNUM;
+ emit_move_insn (gen_rtx_REG (Pmode, frame.first_restore_gpr),
+ addr);
}
+ }
- /* Restore from offset below save area. */
+ /* Return to caller. */
- if (offset == 0)
- fprintf (file, "\tl%s\t%s,0(%s)\n", b64,
- reg_names[fp], reg_names[fp]);
- restore_fprs (file, offset-64, fp);
- return_reg = FREE_REG;
- fprintf (file, "\tl%s\t%s,%d(%s)\n", b64, reg_names[return_reg],
- UNITS_PER_WORD*RETURN_REGNUM+offset, reg_names[fp]);
- if (!TARGET_64BIT)
- {
- if (regs_ever_live[18])
- fprintf (file, "\tld\t%s,%d(%s)\n",
- reg_names[18],
- offset+STACK_POINTER_OFFSET-16, reg_names[fp]);
- if (regs_ever_live[19])
- fprintf (file, "\tld\t%s,%d(%s)\n",
- reg_names[19],
- offset+STACK_POINTER_OFFSET-8, reg_names[fp]);
- }
- fprintf (file, "\tlm%s\t%s,%s,%d(%s)\n", b64,
- reg_names[i], reg_names[15],
- (UNITS_PER_WORD * i) + offset, reg_names[fp]);
- }
+ p = rtvec_alloc (2);
- fprintf (file, "\tbr\t%s\n", reg_names[return_reg]);
-
- current_function_uses_pic_offset_table = 0;
- leaf_function_flag = 0;
- s390_pool_start_insn = NULL_RTX;
- s390_pool_count = -1;
- s390_function_count++;
- return;
+ RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
+ RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
+ emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
}
memory_address (Pmode,
plus_constant (addr, (TARGET_64BIT ? 28 : 16) ))), fnaddr);
}
+
+/* Return rtx for 64-bit constant formed from the 32-bit subwords
+ LOW and HIGH, independent of the host word size. */
+
+rtx
+s390_gen_rtx_const_DI (high, low)
+ int high;
+ int low;
+{
+#if HOST_BITS_PER_WIDE_INT >= 64
+ HOST_WIDE_INT val;
+ val = (HOST_WIDE_INT)high;
+ val <<= 32;
+ val |= (HOST_WIDE_INT)low;
+
+ return GEN_INT (val);
+#else
+#if HOST_BITS_PER_WIDE_INT >= 32
+ return immed_double_const ((HOST_WIDE_INT)low, (HOST_WIDE_INT)high, DImode);
+#else
+ abort ();
+#endif
+#endif
+}
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+void
+s390_function_profiler (file, labelno)
+ FILE *file;
+ int labelno;
+{
+ rtx op[7];
+
+ char label[128];
+ sprintf (label, "%sP%d", LPREFIX, labelno);
+
+ fprintf (file, "# function profiler \n");
+
+ op[0] = gen_rtx_REG (Pmode, RETURN_REGNUM);
+ op[1] = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
+ op[1] = gen_rtx_MEM (Pmode, plus_constant (op[1], UNITS_PER_WORD));
+
+ op[2] = gen_rtx_REG (Pmode, 1);
+ op[3] = gen_rtx_SYMBOL_REF (Pmode, label);
+ SYMBOL_REF_FLAG (op[3]) = 1;
+
+ op[4] = gen_rtx_SYMBOL_REF (Pmode, "_mcount");
+ if (flag_pic)
+ {
+ op[4] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[4]), 113);
+ op[4] = gen_rtx_CONST (Pmode, op[4]);
+ }
+
+ if (TARGET_64BIT)
+ {
+ output_asm_insn ("stg\t%0,%1", op);
+ output_asm_insn ("larl\t%2,%3", op);
+ output_asm_insn ("brasl\t%0,%4", op);
+ output_asm_insn ("lg\t%0,%1", op);
+ }
+ else if (!flag_pic)
+ {
+ op[6] = gen_label_rtx ();
+
+ output_asm_insn ("st\t%0,%1", op);
+ output_asm_insn ("bras\t%2,%l6", op);
+ output_asm_insn (".long\t%3", op);
+ output_asm_insn (".long\t%4", op);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
+ output_asm_insn ("l\t%0,0(%2)", op);
+ output_asm_insn ("l\t%2,4(%2)", op);
+ output_asm_insn ("basr\t%0,%0", op);
+ output_asm_insn ("l\t%0,%1", op);
+ }
+ else
+ {
+ op[5] = gen_label_rtx ();
+ op[6] = gen_label_rtx ();
+
+ output_asm_insn ("st\t%0,%1", op);
+ output_asm_insn ("bras\t%2,%l6", op);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[5]));
+ output_asm_insn (".long\t%3-%l5", op);
+ output_asm_insn (".long\t%4-%l5", op);
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (op[6]));
+ output_asm_insn ("lr\t%0,%2", op);
+ output_asm_insn ("a\t%0,0(%2)", op);
+ output_asm_insn ("a\t%2,4(%2)", op);
+ output_asm_insn ("basr\t%0,%0", op);
+ output_asm_insn ("l\t%0,%1", op);
+ }
+}
+
;;
;; s_operand -- Matches a valid S operand in a RS, SI or SS type instruction.
;;
-;; r_or_s_operand -- Matches a register or a valid S operand in a RS, SI
-;; or SS type instruction or a register
-;;
-
-;; Insn type. Used to default other attribute values.
;; Define an insn type attribute. This is used in function unit delay
;; computations.
-(define_attr "type" "integer,load,lr,la,store,imul,lmul,fmul,idiv,ldiv,fdiv,branch,jsr,other,o2,o3"
+(define_attr "type" "none,integer,load,lr,la,lm,stm,cs,vs,store,imul,lmul,fmul,idiv,ldiv,fdiv,branch,jsr,other,o2,o3"
(const_string "integer"))
;; Insn are devide in two classes:
;; Generic pipeline function unit.
+(define_function_unit "integer" 1 0
+ (eq_attr "type" "none") 0 0)
+
(define_function_unit "integer" 1 0
(eq_attr "type" "integer") 1 1)
(define_function_unit "integer" 1 0
(eq_attr "type" "store") 1 1)
+(define_function_unit "integer" 1 0
+ (eq_attr "type" "lm") 2 2)
+
+(define_function_unit "integer" 1 0
+ (eq_attr "type" "stm") 2 2)
+
+(define_function_unit "integer" 1 0
+ (eq_attr "type" "cs") 5 5)
+
+(define_function_unit "integer" 1 0
+ (eq_attr "type" "vs") 30 30)
+
(define_function_unit "integer" 1 0
(eq_attr "type" "jsr") 5 5)
(define_insn "*cmpdi_tm2"
[(set (reg 33)
(compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const1_operand" "")
- (match_operand:DI 2 "immediate_operand" "I"))
+ (match_operand:DI 1 "const_int_operand" "n")
+ (match_operand:DI 2 "const_int_operand" "n"))
(const_int 0)))]
- "s390_match_ccmode(insn, CCTmode) &&
- INTVAL(operands[2]) >= 0 && INTVAL(operands[2]) < 64"
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+ && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[1]) + INTVAL (operands[2]) <= 64
+ && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
+ == INTVAL (operands[2]) >> 4"
"*
{
- if (INTVAL (operands[2]) > 47)
- {
- operands[1] = GEN_INT (1 << (63 - INTVAL(operands[2])));
- return \"tmll\\t%0,%x1\";
- }
- else if (INTVAL (operands[2]) > 31)
- {
- operands[1] = GEN_INT (1 << (47 - INTVAL(operands[2])));
- return \"tmlh\\t%0,%x1\";
- }
- else if (INTVAL (operands[2]) > 15)
- {
- operands[1] = GEN_INT (1 << (31 - INTVAL(operands[2])));
- return \"tmhl\\t%0,%x1\";
- }
- operands[1] = GEN_INT (1 << (15 - INTVAL(operands[2])));
- return \"tmhh\\t%0,%x1\";
-}"
- [(set_attr "op_type" "RX")
- (set_attr "type" "integer")])
+ int part = INTVAL (operands[2]) >> 4;
+ int block = (1 << INTVAL (operands[1])) - 1;
+ int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
+ operands[2] = GEN_INT (block << shift);
-(define_insn "*cmpdi_tm"
+ switch (part)
+ {
+ case 0: return \"tmhh\\t%0,%x2\";
+ case 1: return \"tmhl\\t%0,%x2\";
+ case 2: return \"tmlh\\t%0,%x2\";
+ case 3: return \"tmll\\t%0,%x2\";
+ default: abort ();
+ }
+}"
+ [(set_attr "op_type" "RI")])
+
+(define_insn "*cmpdi_tm_reg"
[(set (reg 33)
(compare (and:DI (match_operand:DI 0 "register_operand" "%d")
- (match_operand:DI 1 "tmxx_operand" "Lm"))
+ (match_operand:DI 1 "immediate_operand" "n"))
(const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)"
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+ && s390_single_hi (operands[1], DImode, 0) >= 0"
"*
{
- unsigned HOST_WIDEST_INT i;
- if (GET_CODE (operands[1]) == MEM &&
- GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF &&
- CONSTANT_POOL_ADDRESS_P (XEXP (operands[1],0)))
- {
- operands[1] = get_pool_constant (XEXP (operands[1],0));
- }
-
- i = (unsigned HOST_WIDEST_INT) INTVAL (operands[1]);
+ int part = s390_single_hi (operands[1], DImode, 0);
+ operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
- if (i >= 0x1000000000000ULL)
- {
- operands[1] = GEN_INT (i >> 48);
- return \"tmhh\\t%0,%x1\";
- }
- else if (i > 0x100000000ULL)
+ switch (part)
{
- operands[1] = GEN_INT (i >> 32);
- return \"tmhl\\t%0,%x1\";
+ case 0: return \"tmhh\\t%0,%x1\";
+ case 1: return \"tmhl\\t%0,%x1\";
+ case 2: return \"tmlh\\t%0,%x1\";
+ case 3: return \"tmll\\t%0,%x1\";
+ default: abort ();
}
- else if (i >= 0x10000ULL)
- {
- operands[1] = GEN_INT (i >> 16);
- return \"tmlh\\t%0,%x1\";
- }
- else
- return \"tmll\\t%0,%x1\";
}"
- [(set_attr "op_type" "RX")
- (set_attr "type" "integer")])
+ [(set_attr "op_type" "RI")])
+
+(define_insn "*cmpdi_tm_mem"
+ [(set (reg 33)
+ (compare (and:DI (match_operand:DI 0 "s_operand" "%Qo")
+ (match_operand:DI 1 "immediate_operand" "n"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+ && s390_single_qi (operands[1], DImode, 0) >= 0"
+ "*
+{
+ int part = s390_single_qi (operands[1], DImode, 0);
+ operands[1] = GEN_INT (s390_extract_qi (operands[1], DImode, part));
+ operands[0] = gen_rtx_MEM (QImode,
+ plus_constant (XEXP (operands[0], 0), part));
+ return \"tm\\t%0,%b1\";
+}"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
(define_insn "*ltgr"
[(set (reg 33)
(match_dup 0))]
"s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
"ltgr\\t%2,%0"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "integer")])
+ [(set_attr "op_type" "RRE")])
(define_insn "*cmpdi_ccs_0_64"
[(set (reg 33)
(match_operand:DI 1 "const0_operand" "")))]
"s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
"ltgr\\t%0,%0"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "integer")])
+ [(set_attr "op_type" "RRE")])
(define_insn "*cmpdi_ccs_0_31"
[(set (reg 33)
(match_operand:DI 1 "const0_operand" "")))]
"s390_match_ccmode(insn, CCSmode)"
"srda\\t%0,0"
- [(set_attr "op_type" "RS")
- (set_attr "type" "integer")])
+ [(set_attr "op_type" "RS")])
(define_insn "*cmpdi_ccs"
[(set (reg 33)
(define_insn "*cmpdi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:DI 0 "s_operand" "oQ")
- (match_operand:DI 1 "s_operand" "oQ")))]
+ (compare (match_operand:DI 0 "s_imm_operand" "oQ")
+ (match_operand:DI 1 "s_imm_operand" "oQ")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(8,%R0),%1"
[(set_attr "op_type" "SS")
; SI instructions
-(define_insn "*cmpsi_cct"
+(define_insn "*cmpsi_tm2"
[(set (reg 33)
(compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const1_operand" "")
- (match_operand:SI 2 "immediate_operand" "I"))
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
(const_int 0)))]
- "s390_match_ccmode(insn, CCTmode) &&
- INTVAL(operands[2]) >= 0 && INTVAL(operands[2]) < 32"
+ "s390_match_ccmode(insn, CCTmode)
+ && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
+ && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
+ == INTVAL (operands[2]) >> 4"
"*
{
- if (INTVAL (operands[2]) > 15)
+ int part = INTVAL (operands[2]) >> 4;
+ int block = (1 << INTVAL (operands[1])) - 1;
+ int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
+
+ operands[2] = GEN_INT (block << shift);
+
+ switch (part)
{
- operands[1] = GEN_INT (1 << (31 - INTVAL(operands[2])));
- return \"tml\\t%0,%x1\";
+ case 0: return \"tmh\\t%0,%x2\";
+ case 1: return \"tml\\t%0,%x2\";
+ default: abort ();
}
- operands[1] = GEN_INT (1 << (15 - INTVAL(operands[2])));
- return \"tmh\\t%0,%x1\";
}"
[(set_attr "op_type" "RI")])
-(define_insn "*cmpsi_tm"
+(define_insn "*cmpsi_tm_reg"
[(set (reg 33)
(compare (and:SI (match_operand:SI 0 "register_operand" "%d")
- (match_operand:SI 1 "tmxx_operand" "Lm"))
+ (match_operand:SI 1 "immediate_operand" "n"))
(const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)"
+ "s390_match_ccmode(insn, CCTmode)
+ && s390_single_hi (operands[1], SImode, 0) >= 0"
"*
{
- unsigned long i;
- if (GET_CODE (operands[1]) == MEM &&
- GET_CODE (XEXP (operands[1],0)) == SYMBOL_REF &&
- CONSTANT_POOL_ADDRESS_P (XEXP (operands[1],0)))
- {
- operands[1] = get_pool_constant (XEXP (operands[1],0));
- }
+ int part = s390_single_hi (operands[1], SImode, 0);
+ operands[1] = GEN_INT (s390_extract_hi (operands[1], SImode, part));
- i = (unsigned long) INTVAL (operands[1]);
- if (i > 0xffff)
+ switch (part)
{
- operands[1] = GEN_INT (i / 0x10000);
- return \"tmh\\t%0,%x1\";
+ case 0: return \"tmh\\t%0,%x1\";
+ case 1: return \"tml\\t%0,%x1\";
+ default: abort ();
}
- return \"tml\\t%0,%x1\";
}"
- [(set_attr "op_type" "RX")])
+ [(set_attr "op_type" "RI")])
+
+(define_insn "*cmpsi_tm_mem"
+ [(set (reg 33)
+ (compare (and:SI (match_operand:SI 0 "s_operand" "%Qo")
+ (match_operand:SI 1 "immediate_operand" "n"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode)
+ && s390_single_qi (operands[1], SImode, 0) >= 0"
+ "*
+{
+ int part = s390_single_qi (operands[1], SImode, 0);
+ operands[1] = GEN_INT (s390_extract_qi (operands[1], SImode, part));
+
+ operands[0] = gen_rtx_MEM (QImode,
+ plus_constant (XEXP (operands[0], 0), part));
+ return \"tm\\t%0,%b1\";
+}"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
(define_insn "*ltr"
[(set (reg 33)
(define_insn "*cmpsi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:SI 0 "s_operand" "oQ")
- (match_operand:SI 1 "s_operand" "oQ")))]
+ (compare (match_operand:SI 0 "s_imm_operand" "oQ")
+ (match_operand:SI 1 "s_imm_operand" "oQ")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(4,%R0),%1"
[(set_attr "op_type" "SS")
(set_attr "atype" "mem")])
+
; HI instructions
+(define_insn "*cmphi_tm_sub"
+ [(set (reg 33)
+ (compare (and:SI (subreg:SI (match_operand:HI 0 "s_operand" "%Qo") 0)
+ (match_operand:SI 1 "immediate_operand" "n"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode)
+ && s390_single_qi (operands[1], HImode, 0) >= 0"
+ "*
+{
+ int part = s390_single_qi (operands[1], HImode, 0);
+ operands[1] = GEN_INT (s390_extract_qi (operands[1], HImode, part));
+
+ operands[0] = gen_rtx_MEM (QImode,
+ plus_constant (XEXP (operands[0], 0), part));
+ return \"tm\\t%0,%b1\";
+}"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
+
(define_insn "*icm3"
[(set (reg 33)
(compare (match_operand:HI 0 "s_operand" "Qo")
(define_insn "*cmphi_ccu"
[(set (reg 33)
(compare (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "s_operand" "Qo")))]
+ (match_operand:HI 1 "s_imm_operand" "Qo")))]
"s390_match_ccmode(insn, CCUmode)"
"clm\\t%0,3,%1"
[(set_attr "op_type" "RS")
(define_insn "*cmphi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "oQ")
- (match_operand:HI 1 "s_operand" "oQ")))]
+ (compare (match_operand:HI 0 "s_imm_operand" "oQ")
+ (match_operand:HI 1 "s_imm_operand" "oQ")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(2,%R0),%1"
[(set_attr "op_type" "SS")
; QI instructions
+(define_insn "*cmpqi_tm2"
+ [(set (reg 33)
+ (compare (zero_extract:SI (match_operand:QI 0 "s_operand" "Qo")
+ (match_operand:SI 1 "const_int_operand" "n")
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode)
+ && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
+ && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
+ "*
+{
+ int block = (1 << INTVAL (operands[1])) - 1;
+ int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
+
+ operands[2] = GEN_INT (block << shift);
+ return \"tm\\t%0,%b2\";
+}"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
+
+(define_insn "*cmpqi_tm"
+ [(set (reg 33)
+ (compare (and:QI (match_operand:QI 0 "nonimmediate_operand" "%d,Q")
+ (match_operand:QI 1 "immediate_operand" "n,n"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ tml\\t%0,%b1
+ tm\\t%0,%b1"
+ [(set_attr "op_type" "RI,SI")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*cmpqi_tm_sub"
+ [(set (reg 33)
+ (compare (and:SI (subreg:SI (match_operand:QI 0 "s_operand" "%Qo") 0)
+ (match_operand:SI 1 "immediate_operand" "n"))
+ (const_int 0)))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "tm\\t%0,%b1"
+ [(set_attr "op_type" "SI")
+ (set_attr "atype" "mem")])
+
(define_insn "*icm1"
[(set (reg 33)
(compare (match_operand:QI 0 "s_operand" "Qo")
(clobber (match_scratch:QI 2 "=d"))]
"s390_match_ccmode(insn, CCSmode)"
"icm\\t%2,1,%0"
- [(set_attr "op_type" "RS")])
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")])
(define_insn "*cmpqi_ccu_0"
[(set (reg 33)
(define_insn "*cmpqi_ccu"
[(set (reg 33)
(compare (match_operand:QI 0 "register_operand" "d")
- (match_operand:QI 1 "s_operand" "Qo")))]
+ (match_operand:QI 1 "s_imm_operand" "Qo")))]
"s390_match_ccmode(insn, CCUmode)"
"clm\\t%0,1,%1"
[(set_attr "op_type" "RS")
(define_insn "*cmpqi_ccu_immed"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Qo")
- (match_operand:QI 1 "immediate_operand" "")))]
+ (compare (match_operand:QI 0 "s_operand" "Qo")
+ (match_operand:QI 1 "const_int_operand" "n")))]
"s390_match_ccmode(insn, CCUmode) &&
INTVAL(operands[1]) >= 0 && INTVAL(operands[1]) < 256"
"cli\\t%0,%1"
(define_insn "*cmpqi_ccu_mem"
[(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "oQ")
- (match_operand:QI 1 "s_operand" "oQ")))]
+ (compare (match_operand:QI 0 "s_imm_operand" "oQ")
+ (match_operand:QI 1 "s_imm_operand" "oQ")))]
"s390_match_ccmode(insn, CCUmode)"
"clc\\t%O0(1,%R0),%1"
[(set_attr "op_type" "SS")
(define_insn "*cmpdf_ccs"
[(set (reg 33)
(compare (match_operand:DF 0 "register_operand" "f,f")
- (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+ (match_operand:DF 1 "general_operand" "f,m")))]
"s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
cdbr\\t%0,%1
(define_insn "*cmpdf_ccs_ibm"
[(set (reg 33)
(compare (match_operand:DF 0 "register_operand" "f,f")
- (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+ (match_operand:DF 1 "general_operand" "f,m")))]
"s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
cdr\\t%0,%1
(define_insn "*cmpsf_ccs"
[(set (reg 33)
(compare (match_operand:SF 0 "register_operand" "f,f")
- (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+ (match_operand:SF 1 "general_operand" "f,m")))]
"s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
cebr\\t%0,%1
(define_insn "*cmpsf_ccs"
[(set (reg 33)
(compare (match_operand:SF 0 "register_operand" "f,f")
- (match_operand:SF 1 "nonimmediate_operand" "f,m")))]
+ (match_operand:SF 1 "general_operand" "f,m")))]
"s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
cer\\t%0,%1
; movti instruction pattern(s).
;
+(define_insn "*movti_ss"
+ [(set (match_operand:TI 0 "s_operand" "=Qo")
+ (match_operand:TI 1 "s_imm_operand" "Qo"))]
+ ""
+ "mvc\\t%O0(16,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
(define_insn "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=d,d,d,m,Q")
- (match_operand:TI 1 "general_operand" "d,K,m,d,Q"))]
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,m")
+ (match_operand:TI 1 "general_operand" "Q,d,dKm,d"))]
"TARGET_64BIT"
- "*
+ "@
+ lmg\\t%0,%N0,%1
+ stmg\\t%1,%N1,%0
+ #
+ #"
+ [(set_attr "op_type" "RSE,RSE,NN,NN")
+ (set_attr "atype" "mem")])
+
+(define_split
+ [(set (match_operand:TI 0 "nonimmediate_operand" "")
+ (match_operand:TI 1 "general_operand" ""))]
+ "TARGET_64BIT && reload_completed
+ && !s_operand (operands[0], VOIDmode)
+ && !s_operand (operands[1], VOIDmode)
+ && (register_operand (operands[0], VOIDmode)
+ || register_operand (operands[1], VOIDmode))
+ && (!register_operand (operands[0], VOIDmode)
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
+ operands[1])
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, TImode),
+ operands[1]))"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
{
- switch (which_alternative)
+ if (!register_operand (operands[0], VOIDmode)
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
+ operands[1]))
{
- case 0: /* d <- d */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"lgr\\t%M0,%M1\;lgr\\t%0,%1\";
- else
- return \"lgr\\t%0,%1\;lgr\\t%M0,%M1\";
-
- case 1: /* d <- K */
- if (INTVAL(operands[1]) < 0)
- return \"lghi\\t%0,-1\;lghi\\t%M0,%h1\";
- else
- return \"lghi\\t%0,0\;lghi\\t%M0,%h1\";
-
- case 2: /* d <- m */
- if (s_operand (operands[1], GET_MODE (operands[1])))
- return \"lmg\\t%0,%M0,%1\";
- else
- return \"la\\t%M0,%1\;lmg\\t%0,%M0,0(%M0)\";
-
- case 3: /* m <- d */
- if (!s_operand (operands[0], GET_MODE (operands[0])))
- return \"stg\\t%1,%0\;stg\\t%M1,%M0\";
- else
- return \"stmg\\t%1,%M1,%0\";
-
- case 4: /* m <- m */
- return \"mvc\\t%O0(16,%R0),%1\";
-
- default:
- abort();
+ operands[2] = operand_subword (operands[0], 0, 0, TImode);
+ operands[3] = operand_subword (operands[0], 1, 0, TImode);
+ operands[4] = operand_subword (operands[1], 0, 0, TImode);
+ operands[5] = operand_subword (operands[1], 1, 0, TImode);
}
-}"
- [(set_attr "op_type" "NN,NN,RS,RS,SS")
- (set_attr "atype" "reg,reg,mem,mem,mem")
- (set_attr "type" "o2")
- (set_attr "length" "12,8,10,10,*")])
+ else
+ {
+ operands[2] = operand_subword (operands[0], 1, 0, TImode);
+ operands[3] = operand_subword (operands[0], 0, 0, TImode);
+ operands[4] = operand_subword (operands[1], 1, 0, TImode);
+ operands[5] = operand_subword (operands[1], 0, 0, TImode);
+ }
+}")
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (match_operand:TI 1 "memory_operand" ""))]
+ "TARGET_64BIT && reload_completed
+ && !s_operand (operands[1], VOIDmode)"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (mem:TI (match_dup 2)))]
+ "operands[2] = operand_subword (operands[0], 0, 0, TImode);
+ operands[3] = XEXP (operands[1], 0);")
;
; movdi instruction pattern(s).
""
"
{
- if (CONSTANT_P (operands[1])
- && !LEGITIMATE_CONSTANT_P (operands[1]))
- operands[1] = force_const_mem (DImode, operands[1]);
-
+ /* Handle PIC symbolic constants. */
if (TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1]))
emit_pic_move (operands, DImode);
+
+ /* During and after reload, we need to force constants
+ to the literal pool ourselves, if necessary. */
+ if ((reload_in_progress || reload_completed)
+ && CONSTANT_P (operands[1])
+ && (!legitimate_reload_constant_p (operands[1])
+ || fp_operand (operands[0], VOIDmode)))
+ operands[1] = force_const_mem (DImode, operands[1]);
}")
+(define_insn "*movdi_lhi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (match_operand:DI 1 "immediate_operand" "K"))]
+ "TARGET_64BIT
+ && GET_CODE (operands[1]) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
+ && !fp_operand (operands[0], VOIDmode)"
+ "lghi\\t%0,%h1"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
+(define_insn "*movdi_lli"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (match_operand:DI 1 "immediate_operand" "n"))]
+ "TARGET_64BIT && s390_single_hi (operands[1], DImode, 0) >= 0
+ && !fp_operand (operands[0], VOIDmode)"
+ "*
+{
+ int part = s390_single_hi (operands[1], DImode, 0);
+ operands[1] = GEN_INT (s390_extract_hi (operands[1], DImode, part));
+
+ switch (part)
+ {
+ case 0: return \"llihh\\t%0,%x1\";
+ case 1: return \"llihl\\t%0,%x1\";
+ case 2: return \"llilh\\t%0,%x1\";
+ case 3: return \"llill\\t%0,%x1\";
+ default: abort ();
+ }
+}"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
+(define_insn "*movdi_larl"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (match_operand:DI 1 "larl_operand" "X"))]
+ "TARGET_64BIT
+ && !fp_operand (operands[0], VOIDmode)"
+ "larl\\t%0,%1"
+ [(set_attr "op_type" "RIL")
+ (set_attr "atype" "reg")
+ (set_attr "type" "la")])
+
+(define_insn "*movdi_ss"
+ [(set (match_operand:DI 0 "s_operand" "=Qo")
+ (match_operand:DI 1 "s_imm_operand" "Qo"))]
+ ""
+ "mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
(define_insn "*movdi_64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,m,Q")
- (match_operand:DI 1 "general_operand" "d,K,S,m,d,Q"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,m,f,f,m")
+ (match_operand:DI 1 "general_operand" "d,m,d,f,m,f"))]
"TARGET_64BIT"
"@
lgr\\t%0,%1
- lghi\\t%0,%h1
- larl\\t%0,%1
lg\\t%0,%1
stg\\t%1,%0
- mvc\\t%O0(8,%R0),%1"
- [(set_attr "op_type" "RRE,RI,RIL,RXE,RXE,SS")
- (set_attr "type" "integer,integer,la,integer,integer,integer")
- (set_attr "atype" "reg,reg,reg,mem,mem,mem")])
+ ldr\\t%0,%1
+ ld\\t%0,%1
+ std\\t%1,%0"
+ [(set_attr "op_type" "RR,RXE,RXE,RR,RX,RX")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
(define_insn "*movdi_31"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,Q")
- (match_operand:DI 1 "general_operand" "d,K,m,d,Q"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,m,f,f,m")
+ (match_operand:DI 1 "general_operand" "Q,d,dKm,d,f,m,f"))]
"!TARGET_64BIT"
- "*
+ "@
+ lm\\t%0,%N0,%1
+ stm\\t%1,%N1,%0
+ #
+ #
+ ldr\\t%0,%1
+ ld\\t%0,%1
+ std\\t%1,%0"
+ [(set_attr "op_type" "RS,RS,NN,NN,RR,RX,RX")
+ (set_attr "atype" "mem,mem,*,*,reg,mem,mem")])
+
+(define_split
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && !fp_operand (operands[0], VOIDmode)
+ && !fp_operand (operands[1], VOIDmode)
+ && !s_operand (operands[0], VOIDmode)
+ && !s_operand (operands[1], VOIDmode)
+ && (register_operand (operands[0], VOIDmode)
+ || register_operand (operands[1], VOIDmode))
+ && (!register_operand (operands[0], VOIDmode)
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
+ operands[1])
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DImode),
+ operands[1]))"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
{
- switch (which_alternative)
+ if (!register_operand (operands[0], VOIDmode)
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
+ operands[1]))
{
- case 0: /* d <- d */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
- else
- return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
-
- case 1: /* d <- K */
- if (INTVAL (operands[1]) < 0)
- return \"lhi\\t%0,-1\;lhi\\t%N0,%h1\";
- else
- return \"lhi\\t%0,0\;lhi\\t%N0,%h1\";
-
- case 2: /* d <- m */
- if (s_operand (operands[1], GET_MODE (operands[1])))
- return \"lm\\t%0,%N0,%1\";
- else
- return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
-
- case 3: /* m <- d */
- if (s_operand (operands[0], GET_MODE (operands[0])))
- return \"stm\\t%1,%N1,%0\";
- else
- return \"st\\t%1,%0\;st\\t%N1,%N0\";
-
- case 4: /* m <- m */
- return \"mvc\\t%O0(8,%R0),%1\";
-
- default:
- abort();
- }
-}"
- [(set_attr "op_type" "NN,NN,RS,RS,SS")
- (set_attr "atype" "reg,reg,mem,mem,mem")
- (set_attr "type" "o2")
- (set_attr "length" "4,8,8,8,*")])
+ operands[2] = operand_subword (operands[0], 0, 0, DImode);
+ operands[3] = operand_subword (operands[0], 1, 0, DImode);
+ operands[4] = operand_subword (operands[1], 0, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1, 0, DImode);
+ }
+ else
+ {
+ operands[2] = operand_subword (operands[0], 1, 0, DImode);
+ operands[3] = operand_subword (operands[0], 0, 0, DImode);
+ operands[4] = operand_subword (operands[1], 1, 0, DImode);
+ operands[5] = operand_subword (operands[1], 0, 0, DImode);
+ }
+}")
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "memory_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && !fp_operand (operands[0], VOIDmode)
+ && !fp_operand (operands[1], VOIDmode)
+ && !s_operand (operands[1], VOIDmode)"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (mem:DI (match_dup 2)))]
+ "operands[2] = operand_subword (operands[0], 1, 0, DImode);
+ operands[3] = XEXP (operands[1], 0);")
;
; movsi instruction pattern(s).
""
"
{
- if (CONSTANT_P (operands[1])
- && !LEGITIMATE_CONSTANT_P (operands[1]))
- operands[1] = force_const_mem (SImode, operands[1]);
-
- if (flag_pic && SYMBOLIC_CONST (operands[1]))
+ /* Handle PIC symbolic constants. */
+ if (!TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1]))
emit_pic_move (operands, SImode);
/* expr.c tries to load an effective address using
if (operands[1] == operands[0])
DONE;
}
+
+ /* During and after reload, we need to force constants
+ to the literal pool ourselves, if necessary. */
+ if ((reload_in_progress || reload_completed)
+ && CONSTANT_P (operands[1])
+ && (!legitimate_reload_constant_p (operands[1])
+ || fp_operand (operands[0], VOIDmode)))
+ operands[1] = force_const_mem (SImode, operands[1]);
}")
+(define_insn "*movsi_lhi"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (match_operand:SI 1 "immediate_operand" "K"))]
+ "GET_CODE (operands[1]) == CONST_INT
+ && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')
+ && !fp_operand (operands[0], VOIDmode)"
+ "lhi\\t%0,%h1"
+ [(set_attr "op_type" "RI")])
+
+(define_insn "*movsi_lli"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (match_operand:SI 1 "immediate_operand" "n"))]
+ "TARGET_64BIT && s390_single_hi (operands[1], SImode, 0) >= 0
+ && !fp_operand (operands[0], VOIDmode)"
+ "*
+{
+ int part = s390_single_hi (operands[1], SImode, 0);
+ operands[1] = GEN_INT (s390_extract_hi (operands[1], SImode, part));
+
+ switch (part)
+ {
+ case 0: return \"llilh\\t%0,%x1\";
+ case 1: return \"llill\\t%0,%x1\";
+ default: abort ();
+ }
+}"
+ [(set_attr "op_type" "RI")])
+
+(define_insn "*movsi_ss"
+ [(set (match_operand:SI 0 "s_operand" "=Qo")
+ (match_operand:SI 1 "s_imm_operand" "Qo"))]
+ ""
+ "mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
(define_insn "*movsi"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,m,Q")
- (match_operand:SI 1 "general_operand" "d,K,m,d,Q"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,m,f,f,m")
+ (match_operand:SI 1 "general_operand" "d,m,d,f,m,f"))]
""
"@
lr\\t%0,%1
- lhi\\t%0,%h1
l\\t%0,%1
st\\t%1,%0
- mvc\\t%O0(4,%R0),%1"
- [(set_attr "op_type" "RR,RI,RX,RX,SS")
- (set_attr "type" "lr,*,load,store,store")
- (set_attr "atype" "reg,reg,mem,mem,mem")])
+ ler\\t%0,%1
+ le\\t%0,%1
+ ste\\t%1,%0"
+ [(set_attr "op_type" "RR,RX,RX,RR,RX,RX")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
;
(define_insn "movhi"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m")
- (match_operand:HI 1 "r_or_x_or_im16_operand" "d,K,m,d"))]
+ (match_operand:HI 1 "general_operand" "d,n,m,d"))]
""
"@
lr\\t%0,%1
[(set_attr "op_type" "RR,RI,RX,RX")
(set_attr "atype" "reg,reg,mem,mem")])
+
;
; movqi instruction pattern(s).
;
(define_insn "movqi_64"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
- (match_operand:QI 1 "general_operand" "d,K,m,d,n"))]
+ (match_operand:QI 1 "general_operand" "d,n,m,d,n"))]
"TARGET_64BIT"
"@
lr\\t%0,%1
- llill\\t%0,%x1
+ lhi\\t%0,%b1
llgc\\t%0,%1
stc\\t%1,%0
mvi\\t%0,%b1"
[(set_attr "op_type" "RR,RI,RXE,RX,SI")
(set_attr "atype" "reg,reg,mem,mem,mem")])
+
(define_insn "movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,Q")
- (match_operand:QI 1 "r_or_x_or_im16_operand" "d,n,m,d,n"))]
+ (match_operand:QI 1 "general_operand" "d,n,m,d,n"))]
""
"@
lr\\t%0,%1
- lhi\\t%0,%c1
+ lhi\\t%0,%b1
ic\\t%0,%1
stc\\t%1,%0
mvi\\t%0,%b1"
- [(set_attr "op_type" "RR,RX,RX,RX,SI")
+ [(set_attr "op_type" "RR,RI,RX,RX,SI")
(set_attr "atype" "reg,reg,mem,mem,mem")])
+
;
; moveqstrictqi instruction pattern(s).
;
(define_insn "*movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d,m"))
- (match_operand:QI 1 "nonimmediate_operand" "m,d"))]
+ [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
+ (match_operand:QI 1 "memory_operand" "m"))]
""
- "@
- ic\\t%0,%1
- stc\\t%1,%0"
- [(set_attr "op_type" "RX,RX")
- (set_attr "atype" "mem,mem")])
-
+ "ic\\t%0,%1"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")])
;
; movstricthi instruction pattern(s).
;
(define_insn "*movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "r_or_s_operand" "+d,Q"))
- (match_operand:HI 1 "r_or_s_operand" "Q,d"))
+ [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
+ (match_operand:HI 1 "s_imm_operand" "Qo"))
(clobber (reg:CC 33))]
""
- "@
- icm\\t%0,3,%1
- stcm\\t%1,3,%0"
- [(set_attr "op_type" "RS,RS")
+ "icm\\t%0,3,%1"
+ [(set_attr "op_type" "RS")
(set_attr "atype" "mem")])
;
(define_insn "movestrictsi"
- [(set (strict_low_part (match_operand:SI 0 "nonimmediate_operand" "+d,d,m"))
- (match_operand:SI 1 "nonimmediate_operand" "d,m,d"))]
+ [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d"))
+ (match_operand:SI 1 "general_operand" "d,m"))]
"TARGET_64BIT"
"@
lr\\t%0,%1
- l\\t%0,%1
- st\\t%1,%0"
- [(set_attr "op_type" "RR,RS,RS")
- (set_attr "atype" "reg,mem,mem")])
+ l\\t%0,%1"
+ [(set_attr "op_type" "RR,RS")
+ (set_attr "atype" "reg,mem")])
;
""
"
{
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = force_const_mem (DFmode, operands[1]);
+ /* During and after reload, we need to force constants
+ to the literal pool ourselves, if necessary. */
+ if ((reload_in_progress || reload_completed)
+ && CONSTANT_P (operands[1]))
+ operands[1] = force_const_mem (DFmode, operands[1]);
}")
+(define_insn "*movdf_ss"
+ [(set (match_operand:DF 0 "s_operand" "=Qo")
+ (match_operand:DF 1 "s_imm_operand" "Qo"))]
+ ""
+ "mvc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
(define_insn "*movdf_64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
- (match_operand:DF 1 "general_operand" "f,m,f,m,d,d,Q"))]
- "TARGET_64BIT && TARGET_HARD_FLOAT"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,d,m")
+ (match_operand:DF 1 "general_operand" "f,m,f,d,m,d"))]
+ "TARGET_64BIT"
"@
ldr\\t%0,%1
ld\\t%0,%1
std\\t%1,%0
- lg\\t%0,%1
- stg\\t%1,%0
lgr\\t%0,%1
- mvc\\t%O0(8,%R0),%1"
- [(set_attr "op_type" "RR,RX,RX,RXE,RXE,RR,SS")
- (set_attr "atype" "reg,mem,mem,mem,mem,mem,mem")])
+ lg\\t%0,%1
+ stg\\t%1,%0"
+ [(set_attr "op_type" "RR,RX,RX,RR,RXE,RXE")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
(define_insn "*movdf_31"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
- (match_operand:DF 1 "general_operand" "f,m,f,m,d,d,Q"))]
- "TARGET_HARD_FLOAT"
- "*
-{
- switch (which_alternative)
- {
- case 0: /* f <- f */
- return \"ldr\\t%0,%1\";
-
- case 1: /* f <- m */
- return \"ld\\t%0,%1\";
-
- case 2: /* m <- f */
- return \"std\\t%1,%0\";
-
- case 3: /* d <- m */
- if (s_operand (operands[1], GET_MODE (operands[1])))
- return \"lm\\t%0,%N0,%1\";
- else
- return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
-
- case 4: /* m <- d */
- if (s_operand (operands[0], GET_MODE (operands[0])))
- return \"stm\\t%1,%N1,%0\";
- else
- return \"st\\t%1,%0\;st\\t%N1,%N0\";
-
- case 5: /* d <- d */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
- else
- return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
-
- case 6: /* m <- m */
- return \"mvc\\t%O0(8,%R0),%1\";
-
- default:
- abort();
- }
-}"
- [(set_attr "op_type" "RR,RX,RX,RS,RS,NN,SS")
- (set_attr "atype" "reg,mem,mem,mem,mem,reg,mem")
- (set_attr "length" "*,*,*,*,*,4,*")])
-
-(define_insn "*movdf_soft_64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=d,m,d,Q")
- (match_operand:DF 1 "general_operand" "m,d,d,Q"))]
- "TARGET_64BIT && TARGET_SOFT_FLOAT"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,m")
+ (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKm,d"))]
+ "!TARGET_64BIT"
"@
- lg\\t%0,%1
- stg\\t%1,%0
- lgr\\t%0,%1
- mvc\\t%O0(8,%R0),%1"
- [(set_attr "op_type" "RXE,RXE,RR,SS")
- (set_attr "atype" "mem,mem,mem,mem")])
-
-(define_insn "*movdf_soft_31"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=!d,d,m,Q")
- (match_operand:DF 1 "general_operand" "!d,m,d,Q"))]
- "TARGET_SOFT_FLOAT"
- "*
+ ldr\\t%0,%1
+ ld\\t%0,%1
+ std\\t%1,%0
+ lm\\t%0,%N0,%1
+ stm\\t%1,%N1,%0
+ #
+ #"
+ [(set_attr "op_type" "RR,RX,RX,RS,RS,NN,NN")
+ (set_attr "atype" "reg,mem,mem,mem,mem,*,*")])
+
+(define_split
+ [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && !fp_operand (operands[0], VOIDmode)
+ && !fp_operand (operands[1], VOIDmode)
+ && !s_operand (operands[0], VOIDmode)
+ && !s_operand (operands[1], VOIDmode)
+ && (register_operand (operands[0], VOIDmode)
+ || register_operand (operands[1], VOIDmode))
+ && (!register_operand (operands[0], VOIDmode)
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
+ operands[1])
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DFmode),
+ operands[1]))"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
{
- switch (which_alternative)
+ if (!register_operand (operands[0], VOIDmode)
+ || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
+ operands[1]))
{
- case 0: /* d <- d */
- if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
- return \"lr\\t%N0,%N1\;lr\\t%0,%1\";
- else
- return \"lr\\t%0,%1\;lr\\t%N0,%N1\";
-
- case 1: /* d <- m */
- if (s_operand (operands[1], GET_MODE (operands[1])))
- return \"lm\\t%0,%N0,%1\";
- else
- return \"la\\t%N0,%1\;lm\\t%0,%N0,0(%N0)\";
-
- case 2: /* m <- d */
- if (s_operand (operands[0], GET_MODE (operands[0])))
- return \"stm\\t%1,%N1,%0\";
- else
- return \"st\\t%1,%0\;st\\t%N1,%N0\";
-
- case 3: /* m <- m */
- return \"mvc\\t%O0(8,%R0),%1\";
-
- default:
- abort();
+ operands[2] = operand_subword (operands[0], 0, 0, DFmode);
+ operands[3] = operand_subword (operands[0], 1, 0, DFmode);
+ operands[4] = operand_subword (operands[1], 0, 0, DFmode);
+ operands[5] = operand_subword (operands[1], 1, 0, DFmode);
}
-}"
- [(set_attr "op_type" "NN,RS,RS,SS")
- (set_attr "atype" "reg,mem,mem,mem")
- (set_attr "length" "8,*,*,*")])
+ else
+ {
+ operands[2] = operand_subword (operands[0], 1, 0, DFmode);
+ operands[3] = operand_subword (operands[0], 0, 0, DFmode);
+ operands[4] = operand_subword (operands[1], 1, 0, DFmode);
+ operands[5] = operand_subword (operands[1], 0, 0, DFmode);
+ }
+}")
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (match_operand:DF 1 "memory_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && !fp_operand (operands[0], VOIDmode)
+ && !fp_operand (operands[1], VOIDmode)
+ && !s_operand (operands[1], VOIDmode)"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (mem:DI (match_dup 2)))]
+ "operands[2] = operand_subword (operands[0], 1, 0, DFmode);
+ operands[3] = XEXP (operands[1], 0);")
;
; movsf instruction pattern(s).
""
"
{
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = force_const_mem (SFmode, operands[1]);
+ /* During and after reload, we need to force constants
+ to the literal pool ourselves, if necessary. */
+ if ((reload_in_progress || reload_completed)
+ && CONSTANT_P (operands[1]))
+ operands[1] = force_const_mem (SFmode, operands[1]);
}")
-(define_insn "*movsf_64"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
- (match_operand:SF 1 "general_operand" "f,m,f,m,d,d,Q"))]
- "TARGET_64BIT && TARGET_HARD_FLOAT"
- "@
- ler\\t%0,%1
- le\\t%0,%1
- ste\\t%1,%0
- llgf\\t%0,%1
- st\\t%1,%0
- lgr\\t%0,%1
- mvc\\t%O0(4,%R0),%1"
- [(set_attr "op_type" "RR,RX,RX,RXE,RX,RR,SS")
- (set_attr "atype" "reg,mem,mem,mem,mem,reg,mem")])
+(define_insn "*movsf_ss"
+ [(set (match_operand:SF 0 "s_operand" "=Qo")
+ (match_operand:SF 1 "s_imm_operand" "Qo"))]
+ ""
+ "mvc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
-(define_insn "*movsf_31"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,m,d,Q")
- (match_operand:SF 1 "general_operand" "f,m,f,m,d,d,Q"))]
- "TARGET_HARD_FLOAT"
+(define_insn "*movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,m,d,d,m")
+ (match_operand:SF 1 "general_operand" "f,m,f,d,m,d"))]
+ ""
"@
ler\\t%0,%1
le\\t%0,%1
ste\\t%1,%0
- l\\t%0,%1
- st\\t%1,%0
- lr\\t%0,%1
- mvc\\t%O0(4,%R0),%1"
- [(set_attr "op_type" "RR,RX,RX,RX,RX,RR,SS")
- (set_attr "atype" "reg,mem,mem,mem,mem,reg,mem")])
-
-(define_insn "*movsf_soft"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m,Q")
- (match_operand:SF 1 "general_operand" "d,m,d,Q"))]
- "TARGET_SOFT_FLOAT"
- "@
lr\\t%0,%1
l\\t%0,%1
- st\\t%1,%0
- mvc\\t%O0(4,%R0),%1"
- [(set_attr "op_type" "RR,RX,RX,SS")
- (set_attr "atype" "reg,mem,mem,mem")])
+ st\\t%1,%0"
+ [(set_attr "op_type" "RR,RX,RX,RR,RX,RX")
+ (set_attr "atype" "reg,mem,mem,reg,mem,mem")])
+
;
; load_multiple pattern(s).
;
int regno;
int count;
rtx from;
- int i;
+ int i, off;
/* Support only loading a constant number of fixed-point registers from
memory and only bother with this if more than two */
if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) <= 2
+ || INTVAL (operands[2]) < 2
|| INTVAL (operands[2]) > 16
|| GET_CODE (operands[1]) != MEM
|| GET_CODE (operands[0]) != REG
regno = REGNO (operands[0]);
operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- from = force_reg (Pmode, XEXP (operands[1], 0));
+ if (no_new_pseudos)
+ {
+ if (GET_CODE (XEXP (operands[1], 0)) == REG)
+ {
+ from = XEXP (operands[1], 0);
+ off = 0;
+ }
+ else if (GET_CODE (XEXP (operands[1], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT)
+ {
+ from = XEXP (XEXP (operands[1], 0), 0);
+ off = INTVAL (XEXP (XEXP (operands[1], 0), 1));
+ }
+ else
+ FAIL;
+
+ if (from == frame_pointer_rtx || from == arg_pointer_rtx)
+ FAIL;
+ }
+ else
+ {
+ from = force_reg (Pmode, XEXP (operands[1], 0));
+ off = 0;
+ }
for (i = 0; i < count; i++)
XVECEXP (operands[3], 0, i)
= gen_rtx_SET (VOIDmode, gen_rtx_REG (Pmode, regno + i),
change_address (operands[1], Pmode,
- plus_constant (from, i * 4)));
+ plus_constant (from,
+ off + i * UNITS_PER_WORD)));
}")
(define_insn "*load_multiple_di"
return \"lmg\\t%1,%0,%2\";
}"
[(set_attr "op_type" "RXE")
- (set_attr "atype" "mem")])
+ (set_attr "atype" "mem")
+ (set_attr "type" "lm")])
(define_insn "*load_multiple_si"
[(match_parallel 0 "load_multiple_operation"
return \"lm\\t%1,%0,%2\";
}"
[(set_attr "op_type" "RXE")
- (set_attr "atype" "mem")])
+ (set_attr "atype" "mem")
+ (set_attr "type" "lm")])
;
; store multiple pattern(s).
int regno;
int count;
rtx to;
- int i;
+ int i, off;
/* Support only storing a constant number of fixed-point registers to
memory and only bother with this if more than two. */
if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) <= 2
+ || INTVAL (operands[2]) < 2
|| INTVAL (operands[2]) > 16
|| GET_CODE (operands[0]) != MEM
|| GET_CODE (operands[1]) != REG
regno = REGNO (operands[1]);
operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- to = force_reg (Pmode, XEXP (operands[0], 0));
+
+ if (no_new_pseudos)
+ {
+ if (GET_CODE (XEXP (operands[0], 0)) == REG)
+ {
+ to = XEXP (operands[0], 0);
+ off = 0;
+ }
+ else if (GET_CODE (XEXP (operands[0], 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (operands[0], 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
+ {
+ to = XEXP (XEXP (operands[0], 0), 0);
+ off = INTVAL (XEXP (XEXP (operands[0], 0), 1));
+ }
+ else
+ FAIL;
+
+ if (to == frame_pointer_rtx || to == arg_pointer_rtx)
+ FAIL;
+ }
+ else
+ {
+ to = force_reg (Pmode, XEXP (operands[0], 0));
+ off = 0;
+ }
for (i = 0; i < count; i++)
XVECEXP (operands[3], 0, i)
= gen_rtx_SET (VOIDmode,
change_address (operands[0], Pmode,
- plus_constant (to, i * 4)),
+ plus_constant (to,
+ off + i * UNITS_PER_WORD)),
gen_rtx_REG (Pmode, regno + i));
}")
}"
[(set_attr "op_type" "RXE")
(set_attr "atype" "mem")
- (set_attr "type" "other")])
+ (set_attr "type" "stm")])
(define_insn "*store_multiple_si"
}"
[(set_attr "op_type" "RXE")
(set_attr "atype" "mem")
- (set_attr "type" "other")])
+ (set_attr "type" "stm")])
;;
;; String instructions.
/* Load up the address+length pairs. */
- emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr0);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 8), len);
+ emit_move_insn (gen_highpart (DImode, reg0), addr0);
+ emit_move_insn (gen_lowpart (DImode, reg0), len);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 0), addr1);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 8), len);
+ emit_move_insn (gen_highpart (DImode, reg1), addr1);
+ emit_move_insn (gen_lowpart (DImode, reg1), len);
/* MOVE */
- emit_insn (gen_movstrdi_64 (reg0, reg1));
+ emit_insn (gen_movstrdi_64 (reg0, reg1, reg0, reg1));
DONE;
}
else
emit_move_insn (reg0, addr0);
emit_move_insn (reg1, addr1);
emit_insn (gen_adddi3 (len, len, constm1_rtx));
- emit_insn (gen_movstrdix_64 (reg0, reg1, len));
+ emit_insn (gen_movstrdix_64 (reg0, reg1, reg0, reg1, len));
emit_label (label);
DONE;
}
/* Load up the address+length pairs. */
- emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 0), addr0);
- emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 4), len);
+ emit_move_insn (gen_highpart (SImode, reg0), addr0);
+ emit_move_insn (gen_lowpart (SImode, reg0), len);
- emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), addr1);
- emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 4), len);
+ emit_move_insn (gen_highpart (SImode, reg1), addr1);
+ emit_move_insn (gen_lowpart (SImode, reg1), len);
/* MOVE */
- emit_insn (gen_movstrsi_31 (reg0, reg1));
+ emit_insn (gen_movstrsi_31 (reg0, reg1, reg0, reg1));
DONE;
}
else
emit_move_insn (reg0, addr0);
emit_move_insn (reg1, addr1);
emit_insn (gen_addsi3 (len, len, constm1_rtx));
- emit_insn (gen_movstrsix_31 (reg0, reg1, len));
+ emit_insn (gen_movstrsix_31 (reg0, reg1, reg0, reg1, len));
emit_label (label);
DONE;
}
; Move a block that is more than 256 bytes in lenght or length in register
(define_insn "movstrdix_64"
- [(set (mem:BLK (match_operand:DI 0 "register_operand" "a"))
- (mem:BLK (match_operand:DI 1 "register_operand" "a")))
- (use (match_operand:DI 2 "register_operand" "a"))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
- (clobber (match_scratch:DI 3 "=&a"))
+ [(clobber (match_operand:DI 0 "register_operand" "=a"))
+ (clobber (match_operand:DI 1 "register_operand" "=a"))
+ (set (mem:BLK (match_operand:DI 2 "register_operand" "0"))
+ (mem:BLK (match_operand:DI 3 "register_operand" "1")))
+ (use (match_operand:DI 4 "register_operand" "a"))
+ (clobber (match_scratch:DI 5 "=&a"))
(clobber (reg:CC 33))]
""
"*
xop[0] = gen_label_rtx ();
xop[1] = gen_label_rtx ();
xop[2] = gen_label_rtx ();
- xop[3] = operands[3];
- output_asm_insn (\"srag\\t%3,%2,8\",operands);
- output_asm_insn (\"jz\\t%l1\",xop);
+ xop[3] = operands[5];
+ output_asm_insn (\"srag\\t%5,%4,8\", operands);
+ output_asm_insn (\"jz\\t%l1\", xop);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (xop[0]));
- output_asm_insn (\"mvc\\t0(256,%0),0(%1)\",operands);
- output_asm_insn (\"la\\t%0,256(%0)\",operands);
- output_asm_insn (\"la\\t%1,256(%1)\",operands);
- xop[3] = operands[3];
- output_asm_insn (\"brct\\t%3,%l0\",xop);
+ output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands);
+ output_asm_insn (\"la\\t%0,256(%0)\", operands);
+ output_asm_insn (\"la\\t%1,256(%1)\", operands);
+ output_asm_insn (\"brct\\t%3,%l0\", xop);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (xop[1]));
- xop[3] = operands[3];
- output_asm_insn (\"bras\\t%3,%l2\",xop);
- output_asm_insn (\"mvc\\t0(1,%0),0(%1)\",operands);
+ output_asm_insn (\"bras\\t%3,%l2\", xop);
+ output_asm_insn (\"mvc\\t0(1,%0),0(%1)\", operands);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (xop[2]));
- return \"ex\\t%2,0(%3)\";
+ return \"ex\\t%4,0(%5)\";
}"
[(set_attr "op_type" "NN")
(set_attr "atype" "mem")
(set_attr "length" "44")])
(define_insn "movstrsix_31"
- [(set (mem:BLK (match_operand:SI 0 "register_operand" "a"))
- (mem:BLK (match_operand:SI 1 "register_operand" "a")))
- (use (match_operand:SI 2 "register_operand" "a"))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
- (clobber (match_scratch:SI 3 "=&a"))
+ [(clobber (match_operand:SI 0 "register_operand" "=a"))
+ (clobber (match_operand:SI 1 "register_operand" "=a"))
+ (set (mem:BLK (match_operand:SI 2 "register_operand" "0"))
+ (mem:BLK (match_operand:SI 3 "register_operand" "1")))
+ (use (match_operand:SI 4 "register_operand" "a"))
+ (clobber (match_scratch:SI 5 "=&a"))
(clobber (reg:CC 33))]
""
"*
xop[0] = gen_label_rtx ();
xop[1] = gen_label_rtx ();
xop[2] = gen_label_rtx ();
- xop[3] = operands[3];
- output_asm_insn (\"lr\\t%3,%2\",operands);
- output_asm_insn (\"sra\\t%3,8\",operands);
- output_asm_insn (\"jz\\t%l1\",xop);
+ xop[3] = operands[5];
+ output_asm_insn (\"lr\\t%5,%4\", operands);
+ output_asm_insn (\"sra\\t%5,8\", operands);
+ output_asm_insn (\"jz\\t%l1\", xop);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (xop[0]));
- output_asm_insn (\"mvc\\t0(256,%0),0(%1)\",operands);
- output_asm_insn (\"la\\t%0,256(%0)\",operands);
- output_asm_insn (\"la\\t%1,256(%1)\",operands);
- xop[3] = operands[3];
- output_asm_insn (\"brct\\t%3,%l0\",xop);
+ output_asm_insn (\"mvc\\t0(256,%0),0(%1)\", operands);
+ output_asm_insn (\"la\\t%0,256(%0)\", operands);
+ output_asm_insn (\"la\\t%1,256(%1)\", operands);
+ output_asm_insn (\"brct\\t%3,%l0\", xop);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (xop[1]));
- xop[3] = operands[3];
- output_asm_insn (\"bras\\t%3,%l2\",xop);
- output_asm_insn (\"mvc\\t0(1,%0),0(%1)\",operands);
+ output_asm_insn (\"bras\\t%3,%l2\", xop);
+ output_asm_insn (\"mvc\\t0(1,%0),0(%1)\", operands);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
CODE_LABEL_NUMBER (xop[2]));
- return \"ex\\t%2,0(%3)\";
+ return \"ex\\t%4,0(%5)\";
}"
[(set_attr "op_type" "NN")
(set_attr "length" "42")
; Move a block that is larger than 255 bytes in length.
(define_insn "movstrdi_64"
- [(set (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
- (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0)))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
+ [(clobber (match_operand:TI 0 "register_operand" "=d"))
+ (clobber (match_operand:TI 1 "register_operand" "=d"))
+ (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
+ (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0)))
(clobber (reg:CC 33))]
""
"mvcle\\t%0,%1,0\;jo\\t.-4"
(set_attr "length" "8")])
(define_insn "movstrsi_31"
- [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
- (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0)))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
+ [(clobber (match_operand:DI 0 "register_operand" "=d"))
+ (clobber (match_operand:DI 1 "register_operand" "=d"))
+ (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
+ (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0)))
(clobber (reg:CC 33))]
""
"mvcle\\t%0,%1,0\;jo\\t.-4"
/* Load up the address+length pairs. */
- emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 8), len);
+ emit_move_insn (gen_highpart (DImode, reg0), addr);
+ emit_move_insn (gen_lowpart (DImode, reg0), len);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 8), const0_rtx);
+ emit_move_insn (gen_lowpart (DImode, reg1), const0_rtx);
/* Clear! */
- emit_insn (gen_clrstrsi_64 (reg0, reg1));
+ emit_insn (gen_clrstrsi_64 (reg0, reg1, reg0, reg1));
DONE;
}
}")
/* Load up the address+length pairs. */
- emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 0), addr);
- emit_move_insn (gen_rtx_SUBREG (SImode, reg0, 4), len);
+ emit_move_insn (gen_highpart (SImode, reg0), addr);
+ emit_move_insn (gen_lowpart (SImode, reg0), len);
- emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 4), const0_rtx);
+ emit_move_insn (gen_lowpart (SImode, reg1), const0_rtx);
/* CLear! */
- emit_insn (gen_clrstrsi_31 (reg0, reg1));
+ emit_insn (gen_clrstrsi_31 (reg0, reg1, reg0, reg1));
DONE;
}
}")
""
"xc\\t%O0(%1,%R0),%0"
[(set_attr "op_type" "RS")
+ (set_attr "type" "cs")
(set_attr "atype" "mem")])
; Clear memory with length greater 256 bytes or lenght not constant
(define_insn "clrstrsi_64"
- [(set (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
+ [(clobber (match_operand:TI 0 "register_operand" "=d"))
+ (clobber (match_operand:TI 1 "register_operand" "=d"))
+ (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
(const_int 0))
- (use (match_operand:TI 1 "register_operand" "d"))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
+ (use (match_operand:TI 3 "register_operand" "1"))
(clobber (reg:CC 33))]
"TARGET_64BIT"
"mvcle\\t%0,%1,0\;jo\\t.-4"
[(set_attr "op_type" "NN")
(set_attr "atype" "mem")
- (set_attr "type" "other")
+ (set_attr "type" "vs")
(set_attr "length" "8")])
(define_insn "clrstrsi_31"
- [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
+ [(clobber (match_operand:DI 0 "register_operand" "=d"))
+ (clobber (match_operand:DI 1 "register_operand" "=d"))
+ (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
(const_int 0))
- (use (match_operand:DI 1 "register_operand" "d"))
- (clobber (match_dup 0))
- (clobber (match_dup 1))
+ (use (match_operand:DI 3 "register_operand" "1"))
(clobber (reg:CC 33))]
"!TARGET_64BIT"
"mvcle\\t%0,%1,0\;jo\\t.-4"
[(set_attr "op_type" "NN")
(set_attr "atype" "mem")
- (set_attr "type" "other")
+ (set_attr "type" "vs")
(set_attr "length" "8")])
;
len = force_reg (DImode, len);
/* Load up the address+length pairs. */
- emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 0), addr0);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg0, 8), len);
+ emit_move_insn (gen_highpart (DImode, reg0), addr0);
+ emit_move_insn (gen_lowpart (DImode, reg0), len);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 0), addr1);
- emit_move_insn (gen_rtx_SUBREG (DImode, reg1, 8), len);
+ emit_move_insn (gen_highpart (DImode, reg1), addr1);
+ emit_move_insn (gen_lowpart (DImode, reg1), len);
/* Compare! */
- emit_insn (gen_cmpstr_64 (reg0, reg1));
+ emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
emit_insn (gen_cmpint_di (operands[0]));
DONE;
}
len = force_reg (Pmode, len);
/* Load up the address+length pairs. */
- emit_move_insn (gen_rtx_SUBREG (Pmode, reg0, 0), addr0);
- emit_move_insn (gen_rtx_SUBREG (Pmode, reg0,
- GET_MODE_SIZE (Pmode)), len);
+ emit_move_insn (gen_highpart (Pmode, reg0), addr0);
+ emit_move_insn (gen_lowpart (Pmode, reg0), len);
- emit_move_insn (gen_rtx_SUBREG (Pmode, reg1, 0), addr1);
- emit_move_insn (gen_rtx_SUBREG (Pmode, reg1,
- GET_MODE_SIZE (Pmode)), len);
+ emit_move_insn (gen_highpart (Pmode, reg1), addr1);
+ emit_move_insn (gen_lowpart (Pmode, reg1), len);
/* Compare! */
if (TARGET_64BIT)
- emit_insn (gen_cmpstr_64 (reg0, reg1));
+ emit_insn (gen_cmpstr_64 (reg0, reg1, reg0, reg1));
else
- emit_insn (gen_cmpstr_31 (reg0, reg1));
+ emit_insn (gen_cmpstr_31 (reg0, reg1, reg0, reg1));
emit_insn (gen_cmpint_si (operands[0]));
DONE;
"clc\\t%O0(%c2,%R0),%1"
[(set_attr "op_type" "SS")
(set_attr "atype" "mem")
- (set_attr "type" "other")])
+ (set_attr "type" "cs")])
; Compare a block that is larger than 255 bytes in length.
(define_insn "cmpstr_64"
- [(set (reg:CCS 33)
- (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 0 "register_operand" "d") 0))
- (mem:BLK (subreg:DI (match_operand:TI 1 "register_operand" "d") 0))))
- (clobber (subreg:DI (match_dup 0) 0))
- (clobber (subreg:DI (match_dup 0) 8))
- (clobber (subreg:DI (match_dup 1) 0))
- (clobber (subreg:DI (match_dup 1) 8))]
+ [(clobber (match_operand:TI 0 "register_operand" "=d"))
+ (clobber (match_operand:TI 1 "register_operand" "=d"))
+ (set (reg:CCS 33)
+ (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
+ (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0))))]
"TARGET_64BIT"
"clcl\\t%0,%1"
[(set_attr "op_type" "RR")
(set_attr "atype" "mem")
- (set_attr "type" "other")])
+ (set_attr "type" "vs")])
(define_insn "cmpstr_31"
- [(set (reg:CCS 33)
- (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "d") 0))
- (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "d") 0))))
- (clobber (subreg:SI (match_dup 0) 0))
- (clobber (subreg:SI (match_dup 0) 4))
- (clobber (subreg:SI (match_dup 1) 0))
- (clobber (subreg:SI (match_dup 1) 4))]
+ [(clobber (match_operand:DI 0 "register_operand" "=d"))
+ (clobber (match_operand:DI 1 "register_operand" "=d"))
+ (set (reg:CCS 33)
+ (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
+ (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0))))]
"!TARGET_64BIT"
"clcl\\t%0,%1"
[(set_attr "op_type" "RR")
(set_attr "atype" "mem")
- (set_attr "type" "other")])
+ (set_attr "type" "vs")])
; Convert condition code to integer in range (-1, 0, 1)
(set_attr "atype" "reg")
(set_attr "type" "other")])
+
;;
;;- Conversion instructions.
;;
+(define_insn "*sethighqisi"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (clobber (reg:CC 33))]
+ ""
+ "icm\\t%0,8,%1"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*sethighhisi"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:HI 1 "s_operand" "Qo")] 10))
+ (clobber (reg:CC 33))]
+ ""
+ "icm\\t%0,12,%1"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*sethighqidi_64"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "icmh\\t%0,8,%1"
+ [(set_attr "op_type" "RSE")
+ (set_attr "atype" "mem")])
+
+(define_insn "*sethighqidi_31"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (unspec:DI [(match_operand:QI 1 "s_operand" "Qo")] 10))
+ (clobber (reg:CC 33))]
+ "!TARGET_64BIT"
+ "icm\\t%0,8,%1"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "mem")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extract:SI (match_operand:QI 1 "s_operand" "")
+ (match_operand 2 "const_int_operand" "")
+ (const_int 0)))]
+ "!TARGET_64BIT && !reload_completed
+ && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8"
+ [(parallel
+ [(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
+ (clobber (reg:CC 33))])
+ (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+ "
+{
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+ operands[1] = change_address (operands[1], QImode, 0);
+}")
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extract:SI (match_operand:QI 1 "s_operand" "")
+ (match_operand 2 "const_int_operand" "")
+ (const_int 0)))]
+ "!TARGET_64BIT && !reload_completed
+ && INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16"
+ [(parallel
+ [(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
+ (clobber (reg:CC 33))])
+ (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+ "
+{
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+ operands[1] = change_address (operands[1], HImode, 0);
+}")
+
;
; extendsidi2 instruction pattern(s).
;
-(define_insn "extendsidi2"
+(define_expand "extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ rtx insns, subword;
+
+ operands[1] = force_reg (SImode, operands[1]);
+ subword = operand_subword (operands[0], 0, 1, DImode);
+
+ start_sequence ();
+ emit_move_insn (subword, operands[1]);
+ emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (32)));
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_no_conflict_block (insns, operands[0], operands[1], 0,
+ gen_rtx_SIGN_EXTEND (DImode, operands[1]));
+
+ /* Avoid having the REG_RETVAL destroyed by someone attaching
+ other REG_EQUAL notes. */
+ emit_move_insn (operands[0], operands[0]);
+ DONE;
+ }
+}
+")
+
+(define_insn "*extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")))]
"TARGET_64BIT"
[(set_attr "op_type" "RRE,RXE")
(set_attr "atype" "reg,mem")])
-
;
; extendhidi2 instruction pattern(s).
;
-(define_insn "extendhidi2"
+(define_expand "extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_extendhisi2 (tmp, operands[1]));
+ emit_insn (gen_extendsidi2 (operands[0], tmp));
+ DONE;
+ }
+ else
+ {
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (48)));
+ emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (48)));
+ DONE;
+ }
+}
+")
+
+(define_insn "*extendhidi2"
[(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:HI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
+ (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_64BIT"
- "sllg\\t%0,%1,48\;srag\\t%0,%0,48"
- [(set_attr "op_type" "NN")
- (set_attr "length" "12")
- (set_attr "type" "o2")])
+ "lgh\\t%0,%1"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")])
;
; extendqidi2 instruction pattern(s).
;
-(define_insn "extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:QI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "sllg\\t%0,%1,56\;srag\\t%0,%0,56"
- [(set_attr "op_type" "NN")
- (set_attr "length" "12")
- (set_attr "type" "o2")])
+(define_expand "extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_extendqisi2 (tmp, operands[1]));
+ emit_insn (gen_extendsidi2 (operands[0], tmp));
+ DONE;
+ }
+ else
+ {
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (56)));
+ emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (56)));
+ DONE;
+ }
+}
+")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (sign_extend:DI (match_operand:QI 1 "s_operand" "")))]
+ "TARGET_64BIT && !reload_completed"
+ [(parallel
+ [(set (match_dup 0) (unspec:DI [(match_dup 1)] 10))
+ (clobber (reg:CC 33))])
+ (parallel
+ [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
+ (clobber (reg:CC 33))])]
+ "")
;
; extendhisi2 instruction pattern(s).
;
-(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=d,!d,d")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,d,m")))
- (clobber (reg:CC 33))]
+(define_expand "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
""
- "@
- sll\\t%1,16\;sra\\t%1,16
- lr\\t%0,%1\;sll\\t%0,16\;sra\\t%0,16
- lh\\t%0,%1"
- [(set_attr "op_type" "NN,NN,RX")
- (set_attr "type" "o2,o3,integer")
- (set_attr "atype" "reg,reg,mem")
- (set_attr "length" "8,10,*")])
+ "
+{
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ emit_insn (gen_ashlsi3 (operands[0], operands[1], GEN_INT (16)));
+ emit_insn (gen_ashrsi3 (operands[0], operands[0], GEN_INT (16)));
+ DONE;
+}
+")
+(define_insn "*extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ ""
+ "lh\\t%0,%1"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")])
;
; extendqisi2 instruction pattern(s).
;
-(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (sign_extend:SI (match_operand:QI 1 "r_or_s_operand" "0,Q")))
- (clobber (reg:CC 33))]
+(define_expand "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
""
- "@
- sll\\t%0,24\;sra\\t%0,24
- icm\\t%0,8,%1\;sra\\t%0,24"
- [(set_attr "op_type" "NN,NN")
- (set_attr "type" "o2")
- (set_attr "atype" "reg,mem")
- (set_attr "length" "8,8")])
+ "
+{
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ emit_insn (gen_ashlsi3 (operands[0], operands[1], GEN_INT (24)));
+ emit_insn (gen_ashrsi3 (operands[0], operands[0], GEN_INT (24)));
+ DONE;
+}
+")
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (sign_extend:SI (match_operand:QI 1 "s_operand" "")))]
+ "!reload_completed"
+ [(parallel
+ [(set (match_dup 0) (unspec:SI [(match_dup 1)] 10))
+ (clobber (reg:CC 33))])
+ (parallel
+ [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
+ (clobber (reg:CC 33))])]
+ "")
;
; extendqihi2 instruction pattern(s).
;
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (sign_extend:HI (match_operand:QI 1 "r_or_s_operand" "0,Q")))
- (clobber (reg:CC 33))]
- ""
- "@
- sll\\t%0,24\;sra\\t%0,24
- icm\\t%0,8,%1\;sra\\t%0,24"
- [(set_attr "op_type" "NN,NN")
- (set_attr "type" "o2")
- (set_attr "atype" "reg,mem")
- (set_attr "length" "8,8")])
-
;
; zero_extendsidi2 instruction pattern(s).
;
-(define_insn "zero_extendsidi2"
+(define_expand "zero_extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ rtx insns, subword;
+
+ operands[1] = force_reg (SImode, operands[1]);
+ subword = operand_subword (operands[0], 0, 1, DImode);
+
+ start_sequence ();
+ emit_move_insn (subword, operands[1]);
+ emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (32)));
+ insns = get_insns ();
+ end_sequence ();
+
+ emit_no_conflict_block (insns, operands[0], operands[1], 0,
+ gen_rtx_ZERO_EXTEND (DImode, operands[1]));
+
+ /* Avoid having the REG_RETVAL destroyed by someone attaching
+ other REG_EQUAL notes. */
+ emit_move_insn (operands[0], operands[0]);
+ DONE;
+ }
+}
+")
+
+(define_insn "*zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m")))]
"TARGET_64BIT"
[(set_attr "op_type" "RRE,RXE")
(set_attr "atype" "reg,mem")])
-
;
; zero_extendhidi2 instruction pattern(s).
;
-(define_insn "zero_extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "=!d,d")
- (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+(define_expand "zero_extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendhisi2 (tmp, operands[1]));
+ emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
+ DONE;
+ }
+ else
+ {
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (48)));
+ emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (48)));
+ DONE;
+ }
+}
+")
+
+(define_insn "*zero_extendhidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_64BIT"
- "@
- llgfr\\t%0,%1\;iilh\\t%0,0
- llgh\\t%0,%1"
- [(set_attr "op_type" "NN,RXE")
- (set_attr "type" "o2,integer")
- (set_attr "atype" "reg,mem")
- (set_attr "length" "12,*")])
+ "llgh\\t%0,%1"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")])
;
; zero_extendqidi2 instruction pattern(s)
;
-(define_insn "zero_extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "=!d,d")
- (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "d,m")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "@
- sllg\\t%0,%1,56\;srlg\\t%0,%0,56
- llgc\\t%0,%1"
- [(set_attr "op_type" "NN,RXE")
- (set_attr "type" "o2,integer")
- (set_attr "atype" "reg,mem")
- (set_attr "length" "12,*")])
+(define_expand "zero_extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
+ ""
+ "
+{
+ if (!TARGET_64BIT)
+ {
+ rtx tmp = gen_reg_rtx (SImode);
+ emit_insn (gen_zero_extendqisi2 (tmp, operands[1]));
+ emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
+ DONE;
+ }
+ else
+ {
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (56)));
+ emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (56)));
+ DONE;
+ }
+}
+")
+(define_insn "*zero_extendqidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (zero_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
+ "TARGET_64BIT"
+ "llgc\\t%0,%1"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")])
;
; zero_extendhisi2 instruction pattern(s).
(define_expand "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "r_or_s_operand" "")))]
+ (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
""
"
{
- if (!TARGET_64BIT)
- {
- emit_insn (gen_zero_extendhisi2_31 (operands[0], operands[1],
- force_const_mem (SImode, const0_rtx)));
- DONE;
- }
-}")
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ emit_insn (gen_andsi3 (operands[0], operands[1], GEN_INT (0xffff)));
+ DONE;
+}
+")
(define_insn "*zero_extendhisi2_64"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,m")))]
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
"TARGET_64BIT"
- "@
- iilh\\t%0,0
- llgh\\t%0,%1"
- [(set_attr "op_type" "RI,RXE")
- (set_attr "atype" "reg,mem")])
-
-(define_insn "zero_extendhisi2_31"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (zero_extend:SI (match_operand:HI 1 "r_or_s_operand" "0,Q")))
- (use (match_operand:SI 2 "memory_operand" "m,m"))
- (clobber (reg:CC 33))]
- ""
- "@
- icm\\t%0,12,%2
- icm\\t%0,12,%1\;srl\\t%0,16"
- [(set_attr "op_type" "RX,NN")
- (set_attr "type" "integer,o2")
- (set_attr "atype" "reg,mem")
- (set_attr "length" "*,8")])
-
-
+ "llgh\\t%0,%1"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")])
+
;
; zero_extendqisi2 instruction pattern(s).
;
-(define_insn "*zero_extendqisi2_mem_31"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))
- (use (match_operand:SI 2 "memory_operand" "m" ))
- (clobber (reg:CC 33))]
+(define_expand "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
""
- "sr\\t%0,%0\;ic\\t%0,%1"
- [(set_attr "op_type" "NN")
- (set_attr "type" "o2")
- (set_attr "atype" "mem")
- (set_attr "length" "6")])
+ "
+{
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ emit_insn (gen_andsi3 (operands[0], operands[1], GEN_INT (0xff)));
+ DONE;
+}
+")
-(define_insn "zero_extendqisi2_reg_31"
+(define_insn "*zero_extendqisi2_64"
[(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extend:SI (match_operand:QI 1 "register_operand" "0")))
- (use (match_operand:SI 2 "memory_operand" "m" ))
- (clobber (reg:CC 33))]
- ""
- "icm\\t%0,14,%2"
- [(set_attr "op_type" "RX")
+ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ "TARGET_64BIT"
+ "llgc\\t%0,%1"
+ [(set_attr "op_type" "RXE")
(set_attr "atype" "mem")])
+
+;
+; zero_extendqihi2 instruction pattern(s).
+;
-(define_insn "*zero_extendqisi2_64"
- [(set (match_operand:SI 0 "register_operand" "=!d,d")
- (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "")
+ (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
"TARGET_64BIT"
- "@
- sllg\\t%0,%1,56\;srlg\\t%0,%0,56
- llgc\\t%0,%1"
- [(set_attr "op_type" "NN,RXE")
- (set_attr "type" "o2,integer")
- (set_attr "atype" "reg,mem")
- (set_attr "length" "12,*")])
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "r_or_s_operand" "")))]
- ""
"
{
- if (!TARGET_64BIT)
- {
- emit_insn (gen_zero_extendqisi2_reg_31 (operands[0], operands[1],
- force_const_mem (SImode, const0_rtx)));
- DONE;
- }
-}")
-
-
-;
-; zero_extendqihi2 instruction pattern(s).
-;
-
-(define_insn "zero_extendqihi2_64"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,m")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "@
- nill\\t%0,0x00FF
- llgc\\t%0,%1"
- [(set_attr "op_type" "RI,RXE")
- (set_attr "atype" "reg,mem")])
-
-(define_insn "zero_extendqihi2_31"
- [(set (match_operand:HI 0 "register_operand" "=d,&d")
- (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,m")))
- (use (match_operand:SI 2 "memory_operand" "m,m"))
- (clobber (reg:CC 33))]
- ""
- "@
- icm\\t%0,14,%2
- sr\\t%0,%0\;ic\\t%0,%1"
- [(set_attr "op_type" "RX,NN")
- (set_attr "atype" "reg,mem")
- (set_attr "length" "*,8")])
-
-(define_expand "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "")
- (zero_extend:HI (match_operand:QI 1 "general_operand" "")))]
- ""
- "
-{
- if (!TARGET_64BIT)
- {
- emit_insn (gen_zero_extendqihi2_31 (operands[0], operands[1],
- force_const_mem (SImode, const0_rtx)));
- DONE;
- }
- else
- {
- emit_insn (gen_zero_extendqihi2_64 (operands[0], operands[1]));
- DONE;
- }
-}")
-
-
-;
-; truncdisi2 instruction pattern(s).
-;
-
-(define_insn "truncdisi2"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (truncate:SI (match_operand:DI 1 "register_operand" "d")))]
- "TARGET_64BIT"
- "llgfr\\t%0,%1"
- [(set_attr "op_type" "RRE")])
-
-
-;
-; truncdihi2 instruction pattern(s).
-;
-
-(define_insn "truncdihi2"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (truncate:HI (match_operand:DI 1 "register_operand" "d")))]
- "TARGET_64BIT"
- "llgfr\\t%0,%1\;iilh\\t%0,0"
- [(set_attr "op_type" "NN")
- (set_attr "length" "10")])
-
-
-;
-; truncdiqi2 instruction pattern(s).
-;
-
-(define_insn "truncdiqi2"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (truncate:QI (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "sllg\\t%0,%1,56\;srlg\\t%0,%0,56"
- [(set_attr "op_type" "NN")
- (set_attr "type" "o2")
- (set_attr "length" "12")])
-
-
-;
-; truncsihi2 instruction pattern(s).
-;
-
-(define_expand "truncsihi2"
- [(set (match_operand:HI 0 "register_operand" "")
- (truncate:HI (match_operand:SI 1 "register_operand" "")))]
- ""
- "
-{
- if (!TARGET_64BIT)
- {
- emit_insn (gen_do_truncsihi2 (operands[0], operands[1],
- force_const_mem (SImode, const0_rtx)));
- DONE;
- }
-}")
-
-
-(define_insn "do_truncsihi2"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (truncate:HI (match_operand:SI 1 "register_operand" "0")))
- (use (match_operand:SI 2 "memory_operand" "m"))
- (clobber (reg:CC 33))]
- ""
- "icm\\t%0,12,%2"
- [(set_attr "op_type" "RX")])
+ operands[1] = gen_lowpart (HImode, operands[1]);
+ emit_insn (gen_andhi3 (operands[0], operands[1], GEN_INT (0xff)));
+ DONE;
+}
+")
-(define_insn "*truncsihi2_64"
+(define_insn "*zero_extendqihi2_64"
[(set (match_operand:HI 0 "register_operand" "=d")
- (truncate:HI (match_operand:SI 1 "register_operand" "0")))]
- "TARGET_64BIT"
- "iilh\\t%0,0"
- [(set_attr "op_type" "RI")])
-
-
-;
-; truncsiqi2 instruction pattern(s).
-;
-
-(define_insn "truncsiqi2"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (truncate:QI (match_operand:SI 1 "register_operand" "0")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "iilh\\t%0,0\;nill\\t%0,0x00FF"
- [(set_attr "op_type" "NN")
- (set_attr "type" "o2")
- (set_attr "length" "8")])
-
-
-;
-; trunchiqi2 instruction pattern(s).
-;
-
-(define_insn "trunchiqi2"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (truncate:QI (match_operand:HI 1 "register_operand" "0")))
+ (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))
(clobber (reg:CC 33))]
"TARGET_64BIT"
- "nill\\t%0,0x00FF"
- [(set_attr "op_type" "RI")])
-
+ "llgc\\t%0,%1"
+ [(set_attr "op_type" "RXE")
+ (set_attr "atype" "mem")])
;
; fixuns_truncdfdi2 and fix_truncdfsi2 instruction pattern(s).
rtx temp = gen_reg_rtx (DFmode);
operands[1] = force_reg (DFmode, operands[1]);
- emit_insn (gen_cmpdf (operands[1], force_const_mem (DFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x8000000000000000ULL, DFmode))));
+ emit_insn (gen_cmpdf (operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"9223372036854775808.0\", DFmode), DFmode)));
emit_jump_insn (gen_blt (label1));
-
- emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, DFmode))));
+ emit_insn (gen_subdf3 (temp, operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"18446744073709551616.0\", DFmode), DFmode)));
emit_insn (gen_fix_truncdfdi2_ieee (operands[0], temp, GEN_INT(7)));
emit_jump (label2);
"TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cgdbr\\t%0,%h2,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "other")])
+ (set_attr "type" "other")])
;
; fixuns_truncdfsi2 and fix_truncdfsi2 instruction pattern(s).
rtx temp = gen_reg_rtx (DFmode);
operands[1] = force_reg (DFmode,operands[1]);
- emit_insn (gen_cmpdf (operands[1], force_const_mem (DFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x80000000ULL, DFmode))));
+ emit_insn (gen_cmpdf (operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"2147483648.0\", DFmode), DFmode)));
emit_jump_insn (gen_blt (label1));
- emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, DFmode))));
+ emit_insn (gen_subdf3 (temp, operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"4294967296.0\", DFmode), DFmode)));
emit_insn (gen_fix_truncdfsi2_ieee (operands[0], temp, GEN_INT (7)));
emit_jump (label2);
/* This is the algorithm from POP chapter A.5.7.2. */
rtx temp = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
- rtx two31r = force_const_mem (DFmode,
- gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
- 0x08000000, 0x4F000000));
- rtx two32 = force_const_mem (DFmode,
- gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
- 0x0, 0x4E000001));
+ rtx two31r = s390_gen_rtx_const_DI (0x4f000000, 0x08000000);
+ rtx two32 = s390_gen_rtx_const_DI (0x4e000001, 0x00000000);
operands[1] = force_reg (DFmode, operands[1]);
emit_insn (gen_fix_truncdfsi2_ibm (operands[0], operands[1],
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cfdbr\\t%0,%h2,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "other" )])
+ (set_attr "type" "other" )])
(define_insn "fix_truncdfsi2_ibm"
[(set (match_operand:SI 0 "register_operand" "=d")
(fix:SI (match_operand:DF 1 "nonimmediate_operand" "+f")))
- (use (match_operand:DF 2 "memory_operand" "m"))
- (use (match_operand:DF 3 "memory_operand" "m"))
+ (use (match_operand:DI 2 "immediate_operand" "m"))
+ (use (match_operand:DI 3 "immediate_operand" "m"))
(use (match_operand:BLK 4 "memory_operand" "m"))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
return \"l\\t%0,%N4\";
}"
[(set_attr "op_type" "NN")
- (set_attr "type" "other")
+ (set_attr "type" "other")
(set_attr "length" "20")])
;
rtx temp = gen_reg_rtx (SFmode);
operands[1] = force_reg (SFmode, operands[1]);
- emit_insn (gen_cmpsf (operands[1], force_const_mem (SFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x8000000000000000ULL, SFmode))));
+ emit_insn (gen_cmpsf (operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"9223372036854775808.0\", SFmode), SFmode)));
emit_jump_insn (gen_blt (label1));
- emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, SFmode))));
+ emit_insn (gen_subsf3 (temp, operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"18446744073709551616.0\", SFmode), SFmode)));
emit_insn (gen_fix_truncsfdi2_ieee (operands[0], temp, GEN_INT(7)));
emit_jump (label2);
"TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cgebr\\t%0,%h2,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "other")])
+ (set_attr "type" "other")])
;
; fixuns_truncsfsi2 and fix_truncsfsi2 instruction pattern(s).
rtx temp = gen_reg_rtx (SFmode);
operands[1] = force_reg (SFmode, operands[1]);
- emit_insn (gen_cmpsf (operands[1], force_const_mem (SFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x80000000ULL, SFmode))));
+ emit_insn (gen_cmpsf (operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"2147483648.0\", SFmode), SFmode)));
emit_jump_insn (gen_blt (label1));
- emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
- CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, SFmode))));
+ emit_insn (gen_subsf3 (temp, operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF (\"4294967296.0\", SFmode), SFmode)));
emit_insn (gen_fix_truncsfsi2_ieee (operands[0], temp, GEN_INT (7)));
emit_jump (label2);
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cfebr\\t%0,%h2,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "other")])
+ (set_attr "type" "other")])
;
; floatdidf2 instruction pattern(s).
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (float:DF (match_operand:DI 1 "register_operand" "d")))]
+ (float:DF (match_operand:DI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
"TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cdgbr\\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "other" )])
+ (set_attr "type" "other" )])
;
; floatdisf2 instruction pattern(s).
(define_insn "floatdisf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (float:SF (match_operand:DI 1 "register_operand" "d")))]
+ (float:SF (match_operand:DI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
"TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cegbr\\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "other" )])
+ (set_attr "type" "other" )])
;
; floatsidf2 instruction pattern(s).
;
(define_expand "floatsidf2"
- [(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:SI 1 "register_operand" "")))]
+ [(parallel
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:SI 1 "register_operand" "")))
+ (clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"
{
/* This is the algorithm from POP chapter A.5.7.1. */
rtx temp = assign_stack_local (BLKmode, 2 * UNITS_PER_WORD, BITS_PER_WORD);
- rtx two31 = force_const_mem (DFmode,
- gen_rtx (CONST_DOUBLE, VOIDmode, cc0_rtx,
- 0x80000000U, 0x4E000000U));
+ rtx two31 = s390_gen_rtx_const_DI (0x4e000000, 0x80000000);
emit_insn (gen_floatsidf2_ibm (operands[0], operands[1], two31, temp));
DONE;
(define_insn "floatsidf2_ieee"
[(set (match_operand:DF 0 "register_operand" "=f")
- (float:DF (match_operand:SI 1 "register_operand" "d")))]
+ (float:DF (match_operand:SI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cdfbr\\t%0,%1"
[(set_attr "op_type" "RRE")
(define_insn "floatsidf2_ibm"
[(set (match_operand:DF 0 "register_operand" "=f")
(float:DF (match_operand:SI 1 "register_operand" "d")))
- (use (match_operand:DF 2 "memory_operand" "m"))
+ (use (match_operand:DI 2 "immediate_operand" "m"))
(use (match_operand:BLK 3 "memory_operand" "m"))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"*
{
- output_asm_insn (\"st\\t%0,%N3\", operands);
+ output_asm_insn (\"st\\t%1,%N3\", operands);
output_asm_insn (\"xi\\t%N3,128\", operands);
output_asm_insn (\"mvc\\t%O3(4,%R3),%2\", operands);
output_asm_insn (\"ld\\t%0,%3\", operands);
return \"sd\\t%0,%2\";
}"
[(set_attr "op_type" "NN")
- (set_attr "type" "other" )
+ (set_attr "type" "other" )
(set_attr "length" "20")])
;
;
(define_expand "floatsisf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:SI 1 "register_operand" "")))]
+ [(parallel
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:SI 1 "register_operand" "")))
+ (clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"
{
(define_insn "floatsisf2_ieee"
[(set (match_operand:SF 0 "register_operand" "=f")
- (float:SF (match_operand:SI 1 "register_operand" "d")))]
+ (float:SF (match_operand:SI 1 "register_operand" "d")))
+ (clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"cefbr\\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "other" )])
+ (set_attr "type" "other" )])
;
; truncdfsf2 instruction pattern(s).
[(set (match_operand:SF 0 "register_operand" "")
(float_truncate:SF (match_operand:DF 1 "general_operand" "")))]
"TARGET_HARD_FLOAT"
- "
-{
- if (CONSTANT_P(operands[1]))
- operands[1] = force_const_mem (DFmode, operands[1]);
-}")
+ "")
(define_insn "truncdfsf2_ieee"
[(set (match_operand:SF 0 "register_operand" "=f")
- (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "f")))]
+ (float_truncate:SF (match_operand:DF 1 "general_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"ledbr\\t%0,%1"
[(set_attr "op_type" "RR")])
(define_insn "truncdfsf2_ibm"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "f,m")))]
+ (float_truncate:SF (match_operand:DF 1 "general_operand" "f,m")))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
lrer\\t%0,%1
le\\t%0,%1"
- [(set_attr "op_type" "RR,RX")])
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
;
; extendsfdf2 instruction pattern(s).
"@
sdr\\t%0,%0\;ler\\t%0,%1
sdr\\t%0,%0\;le\\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")])
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")
+ (set_attr "type" "o2,o2")])
;;
"!TARGET_64BIT"
"*
{
- switch(which_alternative)
+ switch (which_alternative)
{
case 0: /* d <- d */
output_asm_insn (\"ar\\t%0,%2\", operands);
output_asm_insn (\"a\\t%0,%2\", operands);
output_asm_insn (\"al\\t%N0,%N2\", operands);
break;
+
+ default:
+ abort ();
}
output_asm_insn (\"brc\\t12,.+8\", operands);
}"
[(set_attr "op_type" "NN,NN")
(set_attr "atype" "reg,mem")
+ (set_attr "type" "o2,o2")
(set_attr "length" "12,16")])
(define_expand "adddi3"
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
- "")
+ "
+{
+ if (CONSTANT_P (operands[1])
+ && !legitimate_reload_constant_p (operands[1]))
+ operands[1] = force_const_mem (DImode, operands[1]);
+}")
+
(define_split
[(set (match_operand:DI 0 "register_operand" "")
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))]
- "")
+ "
+{
+ if (CONSTANT_P (operands[2])
+ && !legitimate_reload_constant_p (operands[2]))
+ operands[2] = force_const_mem (DImode, operands[2]);
+}")
;
; addsi3 instruction pattern(s).
;
-; The following insn is used when it is known that operand one is the stack pointer,
-; and operand two is small enough to fit in the displacement field
-; In this case, the result will be an address
-;
-(define_insn "addaddr"
+(define_insn "*la_ccclobber"
+ [(set (match_operand:SI 0 "register_operand" "=a")
+ (match_operand:QI 1 "address_operand" "p"))
+ (clobber (reg:CC 33))]
+ "legitimate_la_operand_p (operands[1])"
+ "la\\t%0,%a1"
+ [(set_attr "op_type" "RX")
+ (set_attr "atype" "mem")
+ (set_attr "type" "la")])
+
+(define_insn "*addaddr_ccclobber"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(plus:SI (match_operand:SI 1 "register_operand" "%a,a")
- (match_operand:SI 2 "nonmemory_operand" "J,a")))]
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
+ (clobber (reg:CC 33))]
"(((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
+ (REGNO (operands[1]) == FRAME_POINTER_REGNUM ) ||
(REGNO (operands[1]) == BASE_REGISTER)) &&
- (GET_CODE (operands[2]) == REG ||
+ (GET_CODE (operands[2]) == REG ||
CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
"@
la\\t%0,%c2(,%1)
[(set_attr "op_type" "RR,RI,RX")
(set_attr "atype" "reg,reg,mem")])
-(define_insn "*do_la"
+(define_insn "*la"
[(set (match_operand:SI 0 "register_operand" "=a")
(match_operand:QI 1 "address_operand" "p"))]
"reload_in_progress || reload_completed
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
- "")
+ "
+{
+ if (CONSTANT_P (operands[1])
+ && !legitimate_reload_constant_p (operands[1]))
+ operands[1] = force_const_mem (SImode, operands[1]);
+}")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
- "")
+ "
+{
+ if (CONSTANT_P (operands[2])
+ && !legitimate_reload_constant_p (operands[2]))
+ operands[2] = force_const_mem (SImode, operands[2]);
+}")
-(define_insn "addsi_64"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (plus:SI (match_operand:SI 1 "register_operand" "%a,a")
- (match_operand:SI 2 "nonmemory_operand" "J,a")))]
- "TARGET_64BIT"
- "@
- la\\t%0,%c2(,%1)
- la\\t%0,0(%1,%2)"
- [(set_attr "op_type" "RX")
- (set_attr "atype" "mem")
- (set_attr "type" "la")])
;
; addhi3 instruction pattern(s).
[(parallel
[(set (match_operand:DF 0 "register_operand" "=f,f")
(plus:DF (match_operand:DF 1 "register_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*adddf3"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(plus:DF (match_operand:DF 1 "register_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
(define_insn "*adddf3_ibm"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(plus:DF (match_operand:DF 1 "register_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
[(parallel
[(set (match_operand:SF 0 "register_operand" "=f,f")
(plus:SF (match_operand:SF 1 "register_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*addsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(plus:SF (match_operand:SF 1 "register_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
(define_insn "*addsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(plus:SF (match_operand:SF 1 "register_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
(define_insn "subdi3"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "nonimmediate_operand" "d,m")))
+ (match_operand:DI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
""
"*
output_asm_insn (\"s\\t%0,%2\", operands);
output_asm_insn (\"sl\\t%N0,%N2\", operands);
break;
+
+ default:
+ abort ();
}
output_asm_insn (\"brc\\t11,.+8\", operands);
}"
[(set_attr "op_type" "NN,NN")
(set_attr "atype" "reg,mem")
+ (set_attr "type" "other,other")
(set_attr "length" "12,16")])
;
;
(define_insn "subhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d,d")
- (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
- (match_operand:HI 2 "nonimmediate_operand" "d,K,m")))
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (minus:HI (match_operand:HI 1 "register_operand" "0,0")
+ (match_operand:HI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
""
"@
sr\\t%0,%2
- ahi\\t%0,-%h2
sh\\t%0,%2"
- [(set_attr "op_type" "RR,RI,RX")
- (set_attr "atype" "reg,reg,mem")])
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
;
; subqi3 instruction pattern(s).
[(parallel
[(set (match_operand:DF 0 "register_operand" "=f,f")
(minus:DF (match_operand:DF 1 "register_operand" "0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*subdf3"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(minus:DF (match_operand:DF 1 "register_operand" "0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
(define_insn "*subdf3_ibm"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(minus:DF (match_operand:DF 1 "register_operand" "0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
[(parallel
[(set (match_operand:SF 0 "register_operand" "=f,f")
(minus:SF (match_operand:SF 1 "register_operand" "0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*subsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(minus:SF (match_operand:SF 1 "register_operand" "0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
(define_insn "*subsf3_ibm"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(minus:SF (match_operand:SF 1 "register_operand" "0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
;;- Multiply instructions.
;;
-(define_expand "muldi3"
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (mult:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" "")))
- (clobber (reg:CC 33))])]
- ""
- "
-{
- if (!TARGET_64BIT)
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx op0_0 = operand_subword (operands[0], 0 ,1, DImode);
- rtx op0_1 = operand_subword (operands[0], 1 ,1, DImode);
- rtx temp1_0 = gen_reg_rtx (SImode);
- rtx temp1_1 = gen_reg_rtx (SImode);
- rtx temp2_0 = gen_reg_rtx (SImode);
- rtx temp2_1 = gen_reg_rtx (SImode);
-
- emit_move_insn (temp1_0, operand_subword (operands[1], 0 ,1, DImode));
- emit_move_insn (temp1_1, operand_subword (operands[1], 1 ,1, DImode));
- emit_move_insn (temp2_0, operand_subword (operands[2], 0 ,1, DImode));
- emit_move_insn (temp2_1, operand_subword (operands[2], 1 ,1, DImode));
- emit_move_insn (op0_1, temp1_1);
- emit_insn (gen_mulsi_6432 (operands[0], operands[0], temp2_1));
-
- emit_insn (gen_cmpsi (temp1_1, const0_rtx));
- emit_jump_insn (gen_bge (label1));
- emit_insn (gen_addsi3 (op0_0, op0_0, temp2_1));
- emit_label (label1);
- emit_insn (gen_cmpsi (temp2_1, const0_rtx));
- emit_jump_insn (gen_bge (label2));
- emit_insn (gen_addsi3 (op0_0, op0_0, temp1_1));
- emit_label (label2);
-
- emit_insn (gen_mulsi3 (temp2_1, temp2_1, temp1_0));
- emit_insn (gen_addsi3 (op0_0, op0_0, temp2_1));
-
- emit_insn (gen_mulsi3 (temp1_1, temp1_1, temp2_0));
- emit_insn (gen_addsi3 (op0_0, op0_0, temp1_1));
-
- DONE;
- }
-}")
+;
+; muldi3 instruction pattern(s).
+;
-(define_insn "*muldi3_64"
+(define_insn "muldi3"
[(set (match_operand:DI 0 "register_operand" "=d,d,d")
(mult:DI (match_operand:DI 1 "register_operand" "%0,0,0")
(match_operand:DI 2 "general_operand" "d,K,m")))
(set_attr "atype" "reg,reg,mem")
(set_attr "type" "imul")])
-;
-; mulsidi3 instruction pattern(s).
-;
-
-;(define_expand "mulsidi3"
-; [(set (match_operand:DI 0 "register_operand" "")
-; (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
-; (sign_extend:DI (match_operand:SI 2 "general_operand" ""))))]
-; ""
-; "
-;{
-; emit_insn (gen_extendsidi2 (operands[0], operands[1]));
-; emit_insn (gen_muldisidi3 (operands[0], operands[0], operands[2]));
-; DONE;
-;}")
-
-;(define_insn "muldisidi3"
-; [(set (match_operand:DI 0 "register_operand" "=d,d")
-; (mult:DI (match_operand:DI 1 "register_operand" "0,0")
-; (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
-; (clobber (reg:CC 33))]
-; "!TARGET_64BIT"
-; "@
-; mr\\t%0,%2
-; m\\t%0,%2"
-; [(set_attr "op_type" "RR,RX")
-; (set_attr "atype" "reg,mem")
-; (set_attr "type" "imul")])
-
;
; mulsi3 instruction pattern(s).
;
(set_attr "atype" "reg,reg,mem")
(set_attr "type" "imul")])
+;
+; mulsidi3 instruction pattern(s).
+;
+
+(define_expand "mulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" ""))))]
+ "!TARGET_64BIT"
+ "
+{
+ rtx insn;
+
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[0]));
+ emit_move_insn (gen_lowpart (SImode, operands[0]), operands[1]);
+ insn = emit_insn (gen_mulsi_6432 (operands[0], operands[0], operands[2]));
+
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL,
+ gen_rtx_MULT (DImode,
+ gen_rtx_SIGN_EXTEND (DImode, operands[1]),
+ gen_rtx_SIGN_EXTEND (DImode, operands[2])),
+ REG_NOTES (insn));
+ DONE;
+}")
+
(define_insn "mulsi_6432"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(mult:DI (sign_extend:DI
- (subreg:SI (match_operand:DI 1 "register_operand" "0,0") 4))
+ (truncate:SI (match_operand:DI 1 "register_operand" "0,0")))
(sign_extend:DI
- (match_operand:SI 2 "general_operand" "d,m"))))
+ (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
(clobber (reg:CC 33))]
"!TARGET_64BIT"
"@
(set_attr "atype" "reg,mem")
(set_attr "type" "imul")])
-
;
; muldf3 instruction pattern(s).
;
[(parallel
[(set (match_operand:DF 0 "register_operand" "=f,f")
(mult:DF (match_operand:DF 1 "register_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*muldf3"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(mult:DF (match_operand:DF 1 "register_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
mdbr\\t%0,%2
mdb\\t%0,%2"
[(set_attr "op_type" "RR,RX")
- (set_attr "type" "fmul")
+ (set_attr "type" "fmul")
(set_attr "atype" "reg,mem")])
(define_insn "*muldf3_ibm"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(mult:DF (match_operand:DF 1 "register_operand" "%0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
[(parallel
[(set (match_operand:SF 0 "register_operand" "=f,f")
(mult:SF (match_operand:SF 1 "register_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*mulsf3"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(mult:SF (match_operand:SF 1 "register_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
(define_insn "*mulsf3_ibm"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(mult:SF (match_operand:SF 1 "register_operand" "%0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
;;
;
-; divdi3 and moddi3 instruction pattern(s).
+; divmoddi4 instruction pattern(s).
;
-(define_expand "divdi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (div:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "general_operand" "")))]
- "TARGET_64BIT"
- "
-{
- rtx op3 = gen_reg_rtx (TImode);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (DImode, operands[2]);
-
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);
- emit_insn (gen_divmodtidi3 (op3, op3, operands[2]));
- emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 8));
- DONE;
-}")
-
-(define_expand "moddi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (mod:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "general_operand" "")))]
+(define_expand "divmoddi4"
+ [(parallel [(set (match_operand:DI 0 "general_operand" "")
+ (div:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))
+ (set (match_operand:DI 3 "general_operand" "")
+ (mod:DI (match_dup 1) (match_dup 2)))])
+ (clobber (match_dup 4))]
"TARGET_64BIT"
"
{
- rtx op3 = gen_reg_rtx (TImode);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (DImode, operands[2]);
+ rtx insn, div_equal, mod_equal, equal;
+
+ div_equal = gen_rtx_DIV (DImode, operands[1], operands[2]);
+ mod_equal = gen_rtx_MOD (DImode, operands[1], operands[2]);
+ equal = gen_rtx_IOR (TImode,
+ gen_rtx_ZERO_EXTEND (TImode, div_equal),
+ gen_rtx_ASHIFT (TImode,
+ gen_rtx_ZERO_EXTEND (TImode, mod_equal),
+ GEN_INT (64)));
+
+ operands[4] = gen_reg_rtx(TImode);
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[4]));
+ emit_move_insn (gen_lowpart (DImode, operands[4]), operands[1]);
+ insn = emit_insn (gen_divmodtidi3 (operands[4], operands[4], operands[2]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[0], gen_lowpart (DImode, operands[4]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, div_equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[3], gen_highpart (DImode, operands[4]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, mod_equal, REG_NOTES (insn));
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);
- emit_insn (gen_divmodtidi3 (op3, op3, operands[2]));
- emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 0));
DONE;
}")
(define_insn "divmodtidi3"
- [(set (subreg:DI (match_operand:TI 0 "register_operand" "=d,d") 0)
- (truncate:DI
- (mod:TI (match_operand:TI 1 "register_operand" "0,0")
- (sign_extend:TI
- (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
- (set (subreg:DI (match_dup 0) 8)
- (truncate:DI (div:TI (match_dup 1) (sign_extend:TI (match_dup 2)))))
- (clobber (reg:CC 33))]
+ [(set (match_operand:TI 0 "register_operand" "=d,d")
+ (ior:TI
+ (zero_extend:TI
+ (div:DI (truncate:DI (match_operand:TI 1 "register_operand" "0,0"))
+ (match_operand:DI 2 "general_operand" "d,m")))
+ (ashift:TI
+ (zero_extend:TI
+ (mod:DI (truncate:DI (match_dup 1))
+ (match_dup 2)))
+ (const_int 64))))]
"TARGET_64BIT"
"@
dsgr\\t%0,%2
(set_attr "type" "idiv")
(set_attr "atype" "reg,mem")])
-;
-; udivdi3 and umoddi3 instruction pattern(s).
-;
-
-(define_expand "udivdi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (udiv:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "general_operand" "")))]
+(define_insn "divmodtisi3"
+ [(set (match_operand:TI 0 "register_operand" "=d,d")
+ (ior:TI
+ (zero_extend:TI
+ (div:DI (truncate:DI (match_operand:TI 1 "register_operand" "0,0"))
+ (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
+ (ashift:TI
+ (zero_extend:TI
+ (mod:DI (truncate:DI (match_dup 1))
+ (sign_extend:DI (match_dup 2))))
+ (const_int 64))))]
"TARGET_64BIT"
- "
-{
- rtx op3 = gen_reg_rtx(TImode);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (DImode, operands[2]);
+ "@
+ dsgfr\\t%0,%2
+ dsgf\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "type" "idiv")
+ (set_attr "atype" "reg,mem")])
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);
- emit_insn (gen_udivmodtidi3 (op3, op3, operands[2]));
- emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 8));
- DONE;
-}")
+;
+; udivmoddi4 instruction pattern(s).
+;
-(define_expand "umoddi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (umod:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:DI 2 "general_operand" "")))]
+(define_expand "udivmoddi4"
+ [(parallel [(set (match_operand:DI 0 "general_operand" "")
+ (udiv:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "nonimmediate_operand" "")))
+ (set (match_operand:DI 3 "general_operand" "")
+ (umod:DI (match_dup 1) (match_dup 2)))])
+ (clobber (match_dup 4))]
"TARGET_64BIT"
"
{
- rtx op3 = gen_reg_rtx (TImode);
+ rtx insn, div_equal, mod_equal, equal;
+
+ div_equal = gen_rtx_UDIV (DImode, operands[1], operands[2]);
+ mod_equal = gen_rtx_UMOD (DImode, operands[1], operands[2]);
+ equal = gen_rtx_IOR (TImode,
+ gen_rtx_ZERO_EXTEND (TImode, div_equal),
+ gen_rtx_ASHIFT (TImode,
+ gen_rtx_ZERO_EXTEND (TImode, mod_equal),
+ GEN_INT (64)));
+
+ operands[4] = gen_reg_rtx(TImode);
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[4]));
+ emit_move_insn (gen_lowpart (DImode, operands[4]), operands[1]);
+ emit_move_insn (gen_highpart (DImode, operands[4]), const0_rtx);
+ insn = emit_insn (gen_udivmodtidi3 (operands[4], operands[4], operands[2]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[0], gen_lowpart (DImode, operands[4]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, div_equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[3], gen_highpart (DImode, operands[4]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, mod_equal, REG_NOTES (insn));
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (DImode, operands[2]);
-
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (DImode, op3, 8), operands[1]);
- emit_insn (gen_udivmodtidi3 (op3, op3, operands[2]));
- emit_move_insn (operands[0], gen_rtx_SUBREG (DImode, op3, 0));
DONE;
}")
(define_insn "udivmodtidi3"
- [(set (subreg:DI (match_operand:TI 0 "register_operand" "=d,d") 0)
- (truncate:DI
- (umod:TI (match_operand:TI 1 "register_operand" "0,0")
- (zero_extend:TI
- (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
- (set (subreg:DI (match_dup 0) 8)
- (truncate:DI (udiv:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))
- (clobber (reg:CC 33))]
+ [(set (match_operand:TI 0 "register_operand" "=d,d")
+ (ior:TI (zero_extend:TI
+ (truncate:DI
+ (udiv:TI (match_operand:TI 1 "register_operand" "0,0")
+ (zero_extend:TI
+ (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
+ (ashift:TI
+ (zero_extend:TI
+ (truncate:DI
+ (umod:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))
+ (const_int 64))))]
"TARGET_64BIT"
"@
dlgr\\t%0,%2
(set_attr "atype" "reg,mem")])
;
-; divsi3 and modsi3 instruction pattern(s).
+; divmodsi4 instruction pattern(s).
;
-(define_expand "divsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (div:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonimmediate_operand" "")))]
- "!TARGET_64BIT"
- "
-{
- rtx tmp = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (SImode, operands[2]);
- else
- operands[2] = force_reg (SImode, operands[2]);
-
- emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]);
- emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32)));
- emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
- emit_move_insn (operands[0], gen_rtx_SUBREG (SImode, tmp, 4));
- DONE;
-}")
-
-(define_expand "modsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (mod:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "nonimmediate_operand" "")))]
+(define_expand "divmodsi4"
+ [(parallel [(set (match_operand:SI 0 "general_operand" "")
+ (div:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "nonimmediate_operand" "")))
+ (set (match_operand:SI 3 "general_operand" "")
+ (mod:SI (match_dup 1) (match_dup 2)))])
+ (clobber (match_dup 4))]
"!TARGET_64BIT"
"
{
- rtx tmp = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (SImode, operands[2]);
- else
- operands[2] = force_reg (SImode, operands[2]);
+ rtx insn, div_equal, mod_equal, equal;
+
+ div_equal = gen_rtx_DIV (SImode, operands[1], operands[2]);
+ mod_equal = gen_rtx_MOD (SImode, operands[1], operands[2]);
+ equal = gen_rtx_IOR (DImode,
+ gen_rtx_ZERO_EXTEND (DImode, div_equal),
+ gen_rtx_ASHIFT (DImode,
+ gen_rtx_ZERO_EXTEND (DImode, mod_equal),
+ GEN_INT (32)));
+
+ operands[4] = gen_reg_rtx(DImode);
+ emit_insn (gen_extendsidi2 (operands[4], operands[1]));
+ insn = emit_insn (gen_divmoddisi3 (operands[4], operands[4], operands[2]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[0], gen_lowpart (SImode, operands[4]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, div_equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[3], gen_highpart (SImode, operands[4]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, mod_equal, REG_NOTES (insn));
- emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
- emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]));
- emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32)));
- emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
- emit_move_insn (operands[0], gen_rtx_SUBREG (SImode, tmp, 0));
DONE;
}")
(define_insn "divmoddisi3"
- [(set (subreg:SI (match_operand:DI 0 "register_operand" "=d,d") 0)
- (truncate:SI
- (mod:DI (match_operand:DI 1 "register_operand" "0,0")
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,m")))))
- (set (subreg:SI (match_dup 0) 4)
- (truncate:SI (div:DI (match_dup 1) (sign_extend:DI (match_dup 2)))))
- (clobber (reg:CC 33))]
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ior:DI (zero_extend:DI
+ (truncate:SI
+ (div:DI (match_operand:DI 1 "register_operand" "0,0")
+ (sign_extend:DI
+ (match_operand:SI 2 "nonimmediate_operand" "d,m")))))
+ (ashift:DI
+ (zero_extend:DI
+ (truncate:SI
+ (mod:DI (match_dup 1) (sign_extend:SI (match_dup 2)))))
+ (const_int 32))))]
"!TARGET_64BIT"
"@
dr\\t%0,%2
; udivsi3 and umodsi3 instruction pattern(s).
;
+
(define_expand "udivsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
+ (match_operand:SI 2 "general_operand" "")))
+ (clobber (match_dup 3))]
"!TARGET_64BIT"
"
{
- rtx dr_0, dr_1, tmp;
+ rtx insn, udiv_equal, umod_equal, equal;
- tmp = gen_reg_rtx (DImode);
- dr_0 = gen_rtx_SUBREG (SImode, tmp, 0);
- dr_1 = gen_rtx_SUBREG (SImode, tmp, 4);
+ udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
+ umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
+ equal = gen_rtx_IOR (DImode,
+ gen_rtx_ZERO_EXTEND (DImode, udiv_equal),
+ gen_rtx_ASHIFT (DImode,
+ gen_rtx_ZERO_EXTEND (DImode, umod_equal),
+ GEN_INT (32)));
+
+ operands[3] = gen_reg_rtx (DImode);
if (CONSTANT_P (operands[2]))
{
{
rtx label1 = gen_label_rtx ();
- emit_move_insn (dr_0, operands[1]);
- emit_move_insn (dr_1, const0_rtx);
- emit_insn (gen_cmpsi (dr_0, operands[2]));
+ operands[1] = make_safe_from (operands[1], operands[0]);
+ emit_move_insn (operands[0], const0_rtx);
+ emit_insn (gen_cmpsi (operands[1], operands[2]));
emit_jump_insn (gen_bltu (label1));
- emit_move_insn (dr_1, const1_rtx);
+ emit_move_insn (operands[0], const1_rtx);
emit_label (label1);
}
else
{
- operands[2] = force_const_mem (SImode, operands[2]);
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
- emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ operands[2] = force_reg (SImode, operands[2]);
+ operands[2] = make_safe_from (operands[2], operands[0]);
+
+ emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+ insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+ operands[2]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[0],
+ gen_lowpart (SImode, operands[3]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL,
+ udiv_equal, REG_NOTES (insn));
}
}
else
rtx label3 = gen_label_rtx ();
operands[1] = force_reg (SImode, operands[1]);
+ operands[1] = make_safe_from (operands[1], operands[0]);
operands[2] = force_reg (SImode, operands[2]);
-
- emit_move_insn (dr_1, const0_rtx);
+ operands[2] = make_safe_from (operands[2], operands[0]);
+
+ emit_move_insn (operands[0], const0_rtx);
emit_insn (gen_cmpsi (operands[2], operands[1]));
emit_jump_insn (gen_bgtu (label3));
emit_insn (gen_cmpsi (operands[2], const1_rtx));
emit_jump_insn (gen_blt (label2));
emit_insn (gen_cmpsi (operands[2], const1_rtx));
emit_jump_insn (gen_beq (label1));
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
- emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+ insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+ operands[2]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[0],
+ gen_lowpart (SImode, operands[3]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL,
+ udiv_equal, REG_NOTES (insn));
emit_jump (label3);
emit_label (label1);
- emit_move_insn (dr_1, operands[1]);
+ emit_move_insn (operands[0], operands[1]);
emit_jump (label3);
emit_label (label2);
- emit_move_insn (dr_1, const1_rtx);
+ emit_move_insn (operands[0], const1_rtx);
emit_label (label3);
}
-
- emit_move_insn (operands[0], dr_1);
+ emit_move_insn (operands[0], operands[0]);
DONE;
}")
(define_expand "umodsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(umod:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "nonimmediate_operand" "")))]
+ (match_operand:SI 2 "nonimmediate_operand" "")))
+ (clobber (match_dup 3))]
"!TARGET_64BIT"
"
{
- rtx dr_0, dr_1, tmp;
+ rtx insn, udiv_equal, umod_equal, equal;
+
+ udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
+ umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
+ equal = gen_rtx_IOR (DImode,
+ gen_rtx_ZERO_EXTEND (DImode, udiv_equal),
+ gen_rtx_ASHIFT (DImode,
+ gen_rtx_ZERO_EXTEND (DImode, umod_equal),
+ GEN_INT (32)));
- tmp = gen_reg_rtx (DImode);
- dr_0 = gen_rtx_SUBREG (SImode, tmp, 0);
- dr_1 = gen_rtx_SUBREG (SImode, tmp, 4);
+ operands[3] = gen_reg_rtx (DImode);
if (CONSTANT_P (operands[2]))
{
{
rtx label1 = gen_label_rtx ();
- emit_move_insn (dr_0, operands[1]);
- emit_insn (gen_cmpsi (dr_0, operands[2]));
+ operands[1] = make_safe_from (operands[1], operands[0]);
+ emit_move_insn (operands[0], operands[1]);
+ emit_insn (gen_cmpsi (operands[0], operands[2]));
emit_jump_insn (gen_bltu (label1));
- emit_insn (gen_abssi2 (dr_0, operands[2]));
- emit_insn (gen_addsi3 (dr_0,dr_0, operands[1]));
+ emit_insn (gen_abssi2 (operands[0], operands[2]));
+ emit_insn (gen_addsi3 (operands[0], operands[0], operands[1]));
emit_label (label1);
}
else
{
- operands[2] = force_const_mem (SImode, operands[2]);
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
- emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ operands[2] = force_reg (SImode, operands[2]);
+ operands[2] = make_safe_from (operands[2], operands[0]);
+
+ emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+ insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+ operands[2]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[0],
+ gen_highpart (SImode, operands[3]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL,
+ umod_equal, REG_NOTES (insn));
}
}
else
rtx label3 = gen_label_rtx ();
operands[1] = force_reg (SImode, operands[1]);
+ operands[1] = make_safe_from (operands[1], operands[0]);
operands[2] = force_reg (SImode, operands[2]);
+ operands[2] = make_safe_from (operands[2], operands[0]);
- emit_move_insn(dr_0, operands[1]);
- emit_insn (gen_cmpsi (operands[2], dr_0));
+ emit_move_insn(operands[0], operands[1]);
+ emit_insn (gen_cmpsi (operands[2], operands[1]));
emit_jump_insn (gen_bgtu (label3));
emit_insn (gen_cmpsi (operands[2], const1_rtx));
emit_jump_insn (gen_blt (label2));
emit_insn (gen_cmpsi (operands[2], const1_rtx));
emit_jump_insn (gen_beq (label1));
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
- emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
- emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
+ emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
+ insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
+ operands[2]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, equal, REG_NOTES (insn));
+
+ insn = emit_move_insn (operands[0],
+ gen_highpart (SImode, operands[3]));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL,
+ umod_equal, REG_NOTES (insn));
emit_jump (label3);
emit_label (label1);
- emit_move_insn (dr_0, const0_rtx);
+ emit_move_insn (operands[0], const0_rtx);
emit_jump (label3);
emit_label (label2);
- emit_insn (gen_subsi3 (dr_0, dr_0, operands[2]));
+ emit_insn (gen_subsi3 (operands[0], operands[0], operands[2]));
emit_label (label3);
}
-
- emit_move_insn (operands[0], dr_0);
DONE;
}")
(define_expand "divdf3"
[(parallel
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
- (div:DF (match_operand:DF 1 "general_operand" "0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (div:DF (match_operand:DF 1 "register_operand" "0,0")
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*divdf3"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
- (div:DF (match_operand:DF 1 "general_operand" "0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (div:DF (match_operand:DF 1 "register_operand" "0,0")
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
ddbr\\t%0,%2
ddb\\t%0,%2"
[(set_attr "op_type" "RR,RX")
- (set_attr "type" "fdiv")
+ (set_attr "type" "fdiv")
(set_attr "atype" "reg,mem")])
(define_insn "*divdf3_ibm"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f")
- (div:DF (match_operand:DF 1 "general_operand" "0,0")
- (match_operand:DF 2 "nonimmediate_operand" "f,m")))
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (div:DF (match_operand:DF 1 "register_operand" "0,0")
+ (match_operand:DF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
ddr\\t%0,%2
dd\\t%0,%2"
[(set_attr "op_type" "RR,RX")
- (set_attr "type" "fdiv")
+ (set_attr "type" "fdiv")
(set_attr "atype" "reg,mem")])
;
(define_expand "divsf3"
[(parallel
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
- (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (div:SF (match_operand:SF 1 "register_operand" "0,0")
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))])]
"TARGET_HARD_FLOAT"
"")
(define_insn "*divsf3"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
- (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (div:SF (match_operand:SF 1 "register_operand" "0,0")
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
(set_attr "atype" "reg,mem")])
(define_insn "*divsf3"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f")
- (div:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
- (match_operand:SF 2 "nonimmediate_operand" "f,m")))
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (div:SF (match_operand:SF 1 "register_operand" "0,0")
+ (match_operand:SF 2 "general_operand" "f,m")))
(clobber (reg:CC 33))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
(define_insn "*anddi3_cc"
[(set (reg 33)
- (compare (and:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:DI 2 "r_or_s_operand" "d,m,Q"))
+ (compare (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
- (set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
+ (set (match_operand:DI 0 "register_operand" "=d,d")
(and:DI (match_dup 1) (match_dup 2)))]
"s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
"@
ngr\\t%0,%2
- ng\\t%0,%2
- nc\\t%O0(8,%R0),%2"
- [(set_attr "op_type" "RR,RX,SS")
- (set_attr "atype" "reg,mem,mem")])
+ ng\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
(define_insn "*anddi3_cconly"
[(set (reg 33)
(compare (and:DI (match_operand:DI 1 "register_operand" "%0,0")
- (match_operand:DI 2 "r_or_s_operand" "d,m"))
+ (match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:DI 0 "=d,d"))]
"s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
"@
ngr\\t%0,%2
ng\\t%0,%2"
- [(set_attr "op_type" "RR,RX")
+ [(set_attr "op_type" "RRE,RXE")
(set_attr "atype" "reg,mem")])
+(define_insn "*anddi3_ni"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (and:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "immediate_operand" "n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT && s390_single_hi (operands[2], DImode, -1) >= 0"
+ "*
+{
+ int part = s390_single_hi (operands[2], DImode, -1);
+ operands[2] = GEN_INT (s390_extract_hi (operands[2], DImode, part));
+
+ switch (part)
+ {
+ case 0: return \"nihh\\t%0,%x2\";
+ case 1: return \"nihl\\t%0,%x2\";
+ case 2: return \"nilh\\t%0,%x2\";
+ case 3: return \"nill\\t%0,%x2\";
+ default: abort ();
+ }
+}"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
(define_insn "anddi3"
- [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
- (and:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:DI 2 "r_or_s_operand" "d,m,Q")))
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (and:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
"TARGET_64BIT"
"@
ngr\\t%0,%2
- ng\\t%0,%2
- nc\\t%O0(8,%R0),%2"
- [(set_attr "op_type" "RR,RX,SS")
- (set_attr "atype" "reg,mem,mem")])
+ ng\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*anddi3_ss"
+ [(set (match_operand:DI 0 "s_operand" "=Qo")
+ (and:DI (match_dup 0)
+ (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "nc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*anddi3_ss_inv"
+ [(set (match_operand:DI 0 "s_operand" "=Qo")
+ (and:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "nc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
; andsi3 instruction pattern(s).
(define_insn "*andsi3_cc"
[(set (reg 33)
- (compare (and:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:SI 2 "r_or_s_operand" "d,m,Q"))
+ (compare (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
- (set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
+ (set (match_operand:SI 0 "register_operand" "=d,d")
(and:SI (match_dup 1) (match_dup 2)))]
"s390_match_ccmode(insn, CCTmode)"
"@
nr\\t%0,%2
- n\\t%0,%2
- nc\\t%O0(4,%R0),%2"
- [(set_attr "op_type" "RR,RX,SS")
- (set_attr "atype" "reg,mem,mem")])
+ n\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
(define_insn "*andsi3_cconly"
[(set (reg 33)
(compare (and:SI (match_operand:SI 1 "register_operand" "%0,0")
- (match_operand:SI 2 "r_or_s_operand" "d,m"))
+ (match_operand:SI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=d,d"))]
"s390_match_ccmode(insn, CCTmode)"
[(set_attr "op_type" "RR,RX")
(set_attr "atype" "reg,mem")])
+(define_insn "*andsi3_ni"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (and:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "immediate_operand" "n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT && s390_single_hi (operands[2], SImode, -1) >= 0"
+ "*
+{
+ int part = s390_single_hi (operands[2], SImode, -1);
+ operands[2] = GEN_INT (s390_extract_hi (operands[2], SImode, part));
+
+ switch (part)
+ {
+ case 0: return \"nilh\\t%0,%x2\";
+ case 1: return \"nill\\t%0,%x2\";
+ default: abort ();
+ }
+}"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
(define_insn "andsi3"
- [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
- (and:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
""
"@
nr\\t%0,%2
- n\\t%0,%2
- nc\\t%O0(4,%R0),%2"
- [(set_attr "op_type" "RR,RX,SS")
- (set_attr "atype" "reg,mem,mem")])
+ n\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*andsi3_ss"
+ [(set (match_operand:SI 0 "s_operand" "=Qo")
+ (and:SI (match_dup 0)
+ (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "nc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*andsi3_ss_inv"
+ [(set (match_operand:SI 0 "s_operand" "=Qo")
+ (and:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "nc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
; andhi3 instruction pattern(s).
;
-(define_expand "andhi3"
- [(parallel
- [(set (match_operand:HI 0 "r_or_s_operand" "")
- (and:HI (match_operand:HI 1 "r_or_s_operand" "")
- (match_operand:HI 2 "r_or_s_operand" "")))
- (clobber (reg:CC 33))])]
+(define_insn "*andhi3_ni"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (and:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "d,n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ nr\\t%0,%2
+ nill\\t%0,%x2"
+ [(set_attr "op_type" "RR,RI")
+ (set_attr "atype" "reg")])
+
+(define_insn "andhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (and:HI (match_operand:HI 1 "register_operand" "%0")
+ (match_operand:HI 2 "nonmemory_operand" "d")))
+ (clobber (reg:CC 33))]
""
- "
-{
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (HImode, operands[2]);
-}")
+ "nr\\t%0,%2"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "reg")])
+
+(define_insn "*andhi3_ss"
+ [(set (match_operand:HI 0 "s_operand" "=Qo")
+ (and:HI (match_dup 0)
+ (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "nc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
-(define_insn "*andhi3"
- [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
- (and:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
- (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+(define_insn "*andhi3_ss_inv"
+ [(set (match_operand:HI 0 "s_operand" "=Qo")
+ (and:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
(clobber (reg:CC 33))]
""
- "@
- nr\\t%0,%2
- nc\\t%O0(2,%R0),%2"
- [(set_attr "op_type" "RR,SS")
- (set_attr "atype" "reg,mem")])
+ "nc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
; andqi3 instruction pattern(s).
;
+(define_insn "*andqi3_ni"
+ [(set (match_operand:QI 0 "register_operand" "=d,d")
+ (and:QI (match_operand:QI 1 "register_operand" "%0,0")
+ (match_operand:QI 2 "nonmemory_operand" "d,n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ nr\\t%0,%2
+ nill\\t%0,%b2"
+ [(set_attr "op_type" "RR,RI")
+ (set_attr "atype" "reg")])
+
(define_insn "andqi3"
- [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
- (and:QI (match_operand:QI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (and:QI (match_operand:QI 1 "register_operand" "%0")
+ (match_operand:QI 2 "nonmemory_operand" "d")))
+ (clobber (reg:CC 33))]
+ ""
+ "nr\\t%0,%2"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "reg")])
+
+(define_insn "*andqi3_ss"
+ [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ (and:QI (match_dup 0)
+ (match_operand:QI 1 "s_imm_operand" "n,Qo")))
(clobber (reg:CC 33))]
""
"@
- nr\\t%0,%2
- ni\\t%0,%b2
- nc\\t%O0(1,%R0),%2"
- [(set_attr "op_type" "RR,SI,SS")
- (set_attr "atype" "reg,mem,mem")])
+ ni\\t%0,%b1
+ nc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "SI,SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*andqi3_ss_inv"
+ [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ (and:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ ni\\t%0,%b1
+ nc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "SI,SS")
+ (set_attr "atype" "mem")])
;;
; iordi3 instruction pattern(s).
;
+(define_insn "*iordi3_cc"
+ [(set (reg 33)
+ (compare (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d,d")
+ (ior:DI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+ "@
+ ogr\\t%0,%2
+ og\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*iordi3_cconly"
+ [(set (reg 33)
+ (compare (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+ "@
+ ogr\\t%0,%2
+ og\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*iordi3_oi"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (ior:DI (match_operand:DI 1 "register_operand" "%0")
+ (match_operand:DI 2 "immediate_operand" "n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT && s390_single_hi (operands[2], DImode, 0) >= 0"
+ "*
+{
+ int part = s390_single_hi (operands[2], DImode, 0);
+ operands[2] = GEN_INT (s390_extract_hi (operands[2], DImode, part));
+
+ switch (part)
+ {
+ case 0: return \"oihh\\t%0,%x2\";
+ case 1: return \"oihl\\t%0,%x2\";
+ case 2: return \"oilh\\t%0,%x2\";
+ case 3: return \"oill\\t%0,%x2\";
+ default: abort ();
+ }
+}"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
(define_insn "iordi3"
- [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q,d")
- (ior:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0,0")
- (match_operand:DI 2 "r_or_s_operand" "d,m,Q,L")))
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ior:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
"TARGET_64BIT"
"@
ogr\\t%0,%2
- og\\t%0,%2
- oc\\t%O0(8,%R0),%2
- oill\\t%0,%2"
- [(set_attr "op_type" "RRE,RXE,SS,RI")
- (set_attr "atype" "reg,mem,mem,reg")])
+ og\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*iordi3_ss"
+ [(set (match_operand:DI 0 "s_operand" "=Qo")
+ (ior:DI (match_dup 0)
+ (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "oc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*iordi3_ss_inv"
+ [(set (match_operand:DI 0 "s_operand" "=Qo")
+ (ior:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "oc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
; iorsi3 instruction pattern(s).
;
-(define_expand "iorsi3"
- [(parallel
- [(set (match_operand:SI 0 "r_or_s_operand" "")
- (ior:SI (match_operand:SI 1 "r_or_s_operand" "")
- (match_operand:SI 2 "r_or_s_operand" "")))
- (clobber (reg:CC 33))])]
+(define_insn "*iorsi3_cc"
+ [(set (reg 33)
+ (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (ior:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ or\\t%0,%2
+ o\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*iorsi3_cconly"
+ [(set (reg 33)
+ (compare (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ or\\t%0,%2
+ o\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*iorsi3_oi"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "immediate_operand" "n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT && s390_single_hi (operands[2], SImode, 0) >= 0"
+ "*
+{
+ int part = s390_single_hi (operands[2], SImode, 0);
+ operands[2] = GEN_INT (s390_extract_hi (operands[2], SImode, part));
+
+ switch (part)
+ {
+ case 0: return \"oilh\\t%0,%x2\";
+ case 1: return \"oill\\t%0,%x2\";
+ default: abort ();
+ }
+}"
+ [(set_attr "op_type" "RI")
+ (set_attr "atype" "reg")])
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m")))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ or\\t%0,%2
+ o\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*iorsi3_ss"
+ [(set (match_operand:SI 0 "s_operand" "=Qo")
+ (ior:SI (match_dup 0)
+ (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "oc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*iorsi3_ss_inv"
+ [(set (match_operand:SI 0 "s_operand" "=Qo")
+ (ior:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "oc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+;
+; iorhi3 instruction pattern(s).
+;
+
+(define_insn "*iorhi3_oi"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "d,n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ or\\t%0,%2
+ oill\\t%0,%x2"
+ [(set_attr "op_type" "RR,RI")
+ (set_attr "atype" "reg")])
+
+(define_insn "iorhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (ior:HI (match_operand:HI 1 "register_operand" "%0")
+ (match_operand:HI 2 "nonmemory_operand" "d")))
+ (clobber (reg:CC 33))]
""
- "
-{
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (SImode, operands[2]);
-}")
+ "or\\t%0,%2"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "reg")])
+
+(define_insn "*iorhi3_ss"
+ [(set (match_operand:HI 0 "s_operand" "=Qo")
+ (ior:HI (match_dup 0)
+ (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "oc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
-(define_insn "*iorsi3"
- [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
- (ior:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+(define_insn "*iorhi3_ss_inv"
+ [(set (match_operand:HI 0 "s_operand" "=Qo")
+ (ior:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
(clobber (reg:CC 33))]
""
- "@
- or\\t%0,%2
- o\\t%0,%2
- oc\\t%O0(4,%R0),%2"
- [(set_attr "op_type" "RR,RX,SS")
- (set_attr "atype" "reg,mem,mem")])
+ "oc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
-; iorhi3 instruction pattern(s).
+; iorqi3 instruction pattern(s).
;
-(define_expand "iorhi3"
- [(parallel
- [(set (match_operand:HI 0 "r_or_s_operand" "")
- (ior:HI (match_operand:HI 1 "r_or_s_operand" "")
- (match_operand:HI 2 "r_or_s_operand" "")))
- (clobber (reg:CC 33))])]
- ""
- "
-{
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (HImode, operands[2]);
-}")
+(define_insn "*iorqi3_oi"
+ [(set (match_operand:QI 0 "register_operand" "=d,d")
+ (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
+ (match_operand:QI 2 "nonmemory_operand" "d,n")))
+ (clobber (reg:CC 33))]
+ "TARGET_64BIT"
+ "@
+ or\\t%0,%2
+ oill\\t%0,%b2"
+ [(set_attr "op_type" "RR,RI")
+ (set_attr "atype" "reg")])
-(define_insn "*iorhi3"
- [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
- (ior:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
- (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+(define_insn "iorqi3"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (ior:QI (match_operand:QI 1 "register_operand" "%0")
+ (match_operand:QI 2 "nonmemory_operand" "d")))
+ (clobber (reg:CC 33))]
+ ""
+ "or\\t%0,%2"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "reg")])
+
+(define_insn "*iorqi3_ss"
+ [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ (ior:QI (match_dup 0)
+ (match_operand:QI 1 "s_imm_operand" "n,Qo")))
(clobber (reg:CC 33))]
""
"@
- or\\t%0,%2
- oc\\t%O0(2,%R0),%2"
- [(set_attr "op_type" "RR,SS")
+ oi\\t%0,%b1
+ oc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "SI,SS")
(set_attr "atype" "reg,mem")])
-;
-; iorqi3 instruction pattern(s).
-;
-
-(define_insn "iorqi3"
- [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
- (ior:QI (match_operand:QI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+(define_insn "*iorqi3_ss_inv"
+ [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ (ior:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ (match_dup 0)))
(clobber (reg:CC 33))]
""
"@
- or\\t%0,%2
- oi\\t%0,%b2
- oc\\t%O0(1,%R0),%2"
- [(set_attr "op_type" "RR,SI,SS")
- (set_attr "atype" "reg,mem,mem")])
+ oi\\t%0,%b1
+ oc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "SI,SS")
+ (set_attr "atype" "reg,mem")])
;;
; xordi3 instruction pattern(s).
;
+(define_insn "*xordi3_cc"
+ [(set (reg 33)
+ (compare (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d,d")
+ (xor:DI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+ "@
+ xgr\\t%0,%2
+ xg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*xordi3_cconly"
+ [(set (reg 33)
+ (compare (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:DI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+ "@
+ xgr\\t%0,%2
+ xr\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
(define_insn "xordi3"
- [(set (match_operand:DI 0 "r_or_s_operand" "=d,d,Q")
- (xor:DI (match_operand:DI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:DI 2 "r_or_s_operand" "d,m,Q")))
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (xor:DI (match_operand:DI 1 "register_operand" "%0,0")
+ (match_operand:DI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
"TARGET_64BIT"
"@
xgr\\t%0,%2
- xg\\t%0,%2
- xc\\t%O0(8,%R0),%2"
- [(set_attr "op_type" "RRE,RXE,SS")
- (set_attr "atype" "reg,mem,mem")])
+ xg\\t%0,%2"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*xordi3_ss"
+ [(set (match_operand:DI 0 "s_operand" "=Qo")
+ (xor:DI (match_dup 0)
+ (match_operand:DI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "xc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*xordi3_ss_inv"
+ [(set (match_operand:DI 0 "s_operand" "=Qo")
+ (xor:DI (match_operand:DI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "xc\\t%O0(8,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
; xorsi3 instruction pattern(s).
;
-(define_expand "xorsi3"
- [(parallel
- [(set (match_operand:SI 0 "r_or_s_operand" "")
- (xor:SI (match_operand:SI 1 "r_or_s_operand" "")
- (match_operand:SI 2 "r_or_s_operand" "")))
- (clobber (reg:CC 33))])]
- ""
- "
-{
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (SImode, operands[2]);
-}")
+(define_insn "*xorsi3_cc"
+ [(set (reg 33)
+ (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d,d")
+ (xor:SI (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ xr\\t%0,%2
+ x\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*xorsi3_cconly"
+ [(set (reg 33)
+ (compare (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=d,d"))]
+ "s390_match_ccmode(insn, CCTmode)"
+ "@
+ xr\\t%0,%2
+ x\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
-(define_insn "*xorsi3"
- [(set (match_operand:SI 0 "r_or_s_operand" "=d,d,Q")
- (xor:SI (match_operand:SI 1 "r_or_s_operand" "%0,0,0")
- (match_operand:SI 2 "r_or_s_operand" "d,m,Q")))
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "general_operand" "d,m")))
(clobber (reg:CC 33))]
""
"@
xr\\t%0,%2
- x\\t%0,%2
- xc\\t%O0(4,%R0),%2"
- [(set_attr "op_type" "RR,RX,SS")
- (set_attr "atype" "reg,mem,mem")])
+ x\\t%0,%2"
+ [(set_attr "op_type" "RR,RX")
+ (set_attr "atype" "reg,mem")])
+
+(define_insn "*xorsi3_ss"
+ [(set (match_operand:SI 0 "s_operand" "=Qo")
+ (xor:SI (match_dup 0)
+ (match_operand:SI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "xc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*xorsi3_ss_inv"
+ [(set (match_operand:SI 0 "s_operand" "=Qo")
+ (xor:SI (match_operand:SI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "xc\\t%O0(4,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
; xorhi3 instruction pattern(s).
;
-(define_expand "xorhi3"
- [(parallel
- [(set (match_operand:HI 0 "r_or_s_operand" "")
- (xor:HI (match_operand:HI 1 "r_or_s_operand" "")
- (match_operand:HI 2 "r_or_s_operand" "")))
- (clobber (reg:CC 33))])]
+(define_insn "xorhi3"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (xor:HI (match_operand:HI 1 "register_operand" "%0")
+ (match_operand:HI 2 "nonmemory_operand" "d")))
+ (clobber (reg:CC 33))]
""
- "
-{
- if (CONSTANT_P (operands[2]))
- operands[2] = force_const_mem (HImode, operands[2]);
-}")
+ "xr\\t%0,%2"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "reg")])
+
+(define_insn "*xorhi3_ss"
+ [(set (match_operand:HI 0 "s_operand" "=Qo")
+ (xor:HI (match_dup 0)
+ (match_operand:HI 1 "s_imm_operand" "Qo")))
+ (clobber (reg:CC 33))]
+ ""
+ "xc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
-(define_insn "*xorhi3"
- [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
- (xor:HI (match_operand:HI 1 "r_or_s_operand" "%0,0")
- (match_operand:HI 2 "r_or_s_operand" "d,Q")))
+(define_insn "*xorhi3_ss_inv"
+ [(set (match_operand:HI 0 "s_operand" "=Qo")
+ (xor:HI (match_operand:HI 1 "s_imm_operand" "Qo")
+ (match_dup 0)))
(clobber (reg:CC 33))]
""
- "@
- xr\\t%0,%2
- xc\\t%O0(2,%R0),%2"
- [(set_attr "op_type" "RR,SS")
- (set_attr "atype" "reg,mem")])
+ "xc\\t%O0(2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "atype" "mem")])
;
; xorqi3 instruction pattern(s).
;
(define_insn "xorqi3"
- [(set (match_operand:QI 0 "r_or_s_operand" "=d,Q,Q")
- (xor:QI (match_operand:QI 1 "r_or_s_operand" "0,0,0")
- (match_operand:QI 2 "r_or_s_or_im8_operand" "d,n,Q")))
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (xor:QI (match_operand:QI 1 "register_operand" "%0")
+ (match_operand:QI 2 "nonmemory_operand" "d")))
+ (clobber (reg:CC 33))]
+ ""
+ "xr\\t%0,%2"
+ [(set_attr "op_type" "RR")
+ (set_attr "atype" "reg")])
+
+(define_insn "*xorqi3_ss"
+ [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ (xor:QI (match_dup 0)
+ (match_operand:QI 1 "s_imm_operand" "n,Qo")))
(clobber (reg:CC 33))]
""
"@
- xr\\t%0,%2
- xi\\t%0,%b2
- xc\\t%O0(1,%R0),%2"
- [(set_attr "op_type" "RR,SI,SS")
- (set_attr "atype" "reg,mem,mem")])
+ xi\\t%0,%b1
+ xc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "SI,SS")
+ (set_attr "atype" "mem")])
+
+(define_insn "*xorqi3_ss_inv"
+ [(set (match_operand:QI 0 "s_operand" "=Qo,Qo")
+ (xor:QI (match_operand:QI 1 "s_imm_operand" "n,Qo")
+ (match_dup 0)))
+ (clobber (reg:CC 33))]
+ ""
+ "@
+ xi\\t%0,%b1
+ xc\\t%O0(1,%R0),%1"
+ [(set_attr "op_type" "SI,SS")
+ (set_attr "atype" "mem")])
;;
return \"\";
}"
[(set_attr "op_type" "NN")
- (set_attr "length" "10")])
+ (set_attr "type" "other")
+ (set_attr "length" "10")])
;
; negsi2 instruction pattern(s).
"lpr\\t%0,%1"
[(set_attr "op_type" "RR")])
-;
-; abshi2 instruction pattern(s).
-;
-
-(define_insn "abshi2"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (abs:HI (match_operand:HI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "sll\\t%1,16\;sra\\t%1,16\;lpr\\t%0,%1"
- [(set_attr "op_type" "NN")
- (set_attr "type" "o3")
- (set_attr "length" "10")])
-
;
; absdf2 instruction pattern(s).
;
"lper\\t%0,%1"
[(set_attr "op_type" "RR")])
+;;
+;;- Square root instructions.
+;;
+
+;
+; sqrtdf2 instruction pattern(s).
+;
+
+(define_insn "sqrtdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (sqrt:DF (match_operand:DF 1 "general_operand" "f,m")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ sqdbr\\t%0,%1
+ sqdb\\t%0,%1"
+ [(set_attr "op_type" "RRE,RSE")])
+
+;
+; sqrtsf2 instruction pattern(s).
+;
+
+(define_insn "sqrtsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f,f")
+ (sqrt:SF (match_operand:SF 1 "general_operand" "f,m")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ sqebr\\t%0,%1
+ sqeb\\t%0,%1"
+ [(set_attr "op_type" "RRE,RSE")])
;;
;;- One complement instructions.
;
; one_cmpldi2 instruction pattern(s).
;
-
+
(define_expand "one_cmpldi2"
[(parallel
- [(set (match_operand:DI 0 "r_or_s_operand" "=d")
- (not:DI (match_operand:DI 1 "r_or_s_operand" "0")))
- (use (match_dup 2))
+ [(set (match_operand:DI 0 "register_operand" "")
+ (xor:DI (match_operand:DI 1 "register_operand" "")
+ (const_int -1)))
(clobber (reg:CC 33))])]
"TARGET_64BIT"
- "{ operands[2] = force_const_mem (DImode, constm1_rtx); }")
-
-(define_insn "*one_cmpldi2"
- [(set (match_operand:DI 0 "r_or_s_operand" "=d,Q")
- (not:DI (match_operand:DI 1 "r_or_s_operand" "0,0")))
- (use (match_operand:DI 2 "memory_operand" "m,m"))
- (clobber (reg:CC 33))]
- ""
- "@
- xg\\t%0,%2
- xc\\t%O0(8,%R0),%2"
- [(set_attr "op_type" "RR,SS")
- (set_attr "atype" "mem")])
-
+ "")
+
;
; one_cmplsi2 instruction pattern(s).
;
-
+
(define_expand "one_cmplsi2"
[(parallel
- [(set (match_operand:SI 0 "r_or_s_operand" "=d")
- (not:SI (match_operand:SI 1 "r_or_s_operand" "0")))
- (use (match_dup 2))
+ [(set (match_operand:SI 0 "register_operand" "")
+ (xor:SI (match_operand:SI 1 "register_operand" "")
+ (const_int -1)))
(clobber (reg:CC 33))])]
""
- "{ operands[2] = force_const_mem (SImode, constm1_rtx); }")
-
-(define_insn "*one_cmplsi2"
- [(set (match_operand:SI 0 "r_or_s_operand" "=d,Q")
- (not:SI (match_operand:SI 1 "r_or_s_operand" "0,0")))
- (use (match_operand:SI 2 "memory_operand" "m,m"))
- (clobber (reg:CC 33))]
- ""
- "@
- x\\t%0,%2
- xc\\t%O0(4,%R0),%2"
- [(set_attr "op_type" "RR,SS")
- (set_attr "atype" "mem")])
-
+ "")
+
;
; one_cmplhi2 instruction pattern(s).
;
-
+
(define_expand "one_cmplhi2"
[(parallel
- [(set (match_operand:HI 0 "r_or_s_operand" "=d")
- (not:HI (match_operand:HI 1 "r_or_s_operand" "0")))
- (use (match_dup 2))
+ [(set (match_operand:HI 0 "register_operand" "")
+ (xor:HI (match_operand:HI 1 "register_operand" "")
+ (const_int -1)))
(clobber (reg:CC 33))])]
""
- "{ operands[2] = force_const_mem (SImode, constm1_rtx); }")
-
-(define_insn "*one_cmplhi2"
- [(set (match_operand:HI 0 "r_or_s_operand" "=d,Q")
- (not:HI (match_operand:HI 1 "r_or_s_operand" "0,0")))
- (use (match_operand:SI 2 "memory_operand" "m,m"))
- (clobber (reg:CC 33))]
- ""
- "@
- x\\t%0,%2
- xc\\t%O0(2,%R0),%2"
- [(set_attr "op_type" "RX,SS")
- (set_attr "atype" "mem")])
-
+ "")
+
;
; one_cmplqi2 instruction pattern(s).
;
-
-(define_insn "one_cmpqi2"
- [(set (match_operand:QI 0 "memory_operand" "=Q")
- (not:QI (match_operand:QI 1 "memory_operand" "0")))
- (clobber (reg:CC 33))]
+
+(define_expand "one_cmplqi2"
+ [(parallel
+ [(set (match_operand:QI 0 "register_operand" "")
+ (xor:QI (match_operand:QI 1 "register_operand" "")
+ (const_int -1)))
+ (clobber (reg:CC 33))])]
""
- "xi\\t%0,255"
- [(set_attr "op_type" "SI")])
+ "")
;;
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
(clobber (reg:CC 33))]
""
"@
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
(clobber (reg:CC 33))]
""
"@
sra\\t%0,0(%2)"
[(set_attr "op_type" "RS")])
-;
-; ashlhi3 instruction pattern(s).
-;
-
-(define_insn "ashlhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (ashift:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:SI 2 "r_or_im8_operand" "J,a")))
- (clobber (reg:CC 33))]
- ""
- "@
- sll\\t%0,%c2
- sll\\t%0,0(%2)"
- [(set_attr "op_type" "RS,RS")])
-
-;
-; ashrhi3 instruction pattern(s).
-;
-
-(define_insn "ashrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:SI 2 "r_or_im8_operand" "J,a")))
- (clobber (reg:CC 33))]
- ""
- "@
- sll\\t%0,16\;sra\\t%0,16+%c2
- sll\\t%0,16\;sra\\t%0,16(%2)"
- [(set_attr "op_type" "NN,NN")
- (set_attr "length" "8,8")])
-
;;
;;- logical shift instructions.
(define_insn "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:SI 2 "r_or_im8_operand" "J,a")))
+ (match_operand:SI 2 "nonmemory_operand" "J,a")))
(clobber (reg:CC 33))]
""
"@
srl\\t%0,0(%2)"
[(set_attr "op_type" "RS")])
-;
-; lshrhi3 instruction pattern(s).
-;
-
-(define_insn "lshrhi3"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:SI 2 "r_or_im8_operand" "J,a")))
- (clobber (reg:CC 33))]
- ""
- "@
- sll\\t%0,16\;srl\\t%0,16+%c2
- sll\\t%0,16\;srl\\t%0,16(%2)"
- [(set_attr "op_type" "NN,NN")
- (set_attr "length" "8,8")])
-
;;
;; Branch instruction patterns.
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] 0)]
""
- "")
+ ""
+ [(set_attr "type" "none")])
+
;
"TARGET_64BIT"
"brasl\\t%2,%0"
[(set_attr "op_type" "RIL")
- (set_attr "type" "jsr")])
+ (set_attr "type" "jsr")])
(define_insn "bras"
[(call (mem:QI (match_operand:SI 0 "bras_sym_operand" "X"))
"TARGET_SMALL_EXEC"
"bras\\t%2,%0"
[(set_attr "op_type" "RI")
- (set_attr "type" "jsr")])
+ (set_attr "type" "jsr")])
(define_insn "basr_64"
[(call (mem:QI (match_operand:DI 0 "register_operand" "a"))
return \"basr\\t13,0\;ahi\\t13,%Y0\";
}"
[(set_attr "op_type" "NN")
- (set_attr "type" "o2")
+ (set_attr "type" "la")
(set_attr "length" "8")])
(define_insn "ltorg"
return \"0:\";
}"
[(set_attr "op_type" "NN")
- (set_attr "type" "branch")
+ (set_attr "type" "other")
(set_attr "length" "4096")])
+;;
+;; Insns related to generating the function prologue and epilogue.
+;;
+
+
+(define_expand "prologue"
+ [(use (const_int 0))]
+ ""
+ "
+{
+ s390_emit_prologue ();
+ DONE;
+}")
+
+(define_expand "epilogue"
+ [(use (const_int 1))]
+ ""
+ "
+{
+ s390_emit_epilogue ();
+ DONE;
+}")
+
+
+(define_insn "*return_si"
+ [(return)
+ (use (match_operand:SI 0 "register_operand" "a"))]
+ "!TARGET_64BIT"
+ "br\\t%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "jsr")
+ (set_attr "atype" "mem")])
+
+(define_insn "*return_di"
+ [(return)
+ (use (match_operand:DI 0 "register_operand" "a"))]
+ "TARGET_64BIT"
+ "br\\t%0"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "jsr")
+ (set_attr "atype" "mem")])
+
+
+(define_insn "lit"
+ [(set (reg 13) (pc))
+ (unspec_volatile [(const_int 0)] 200)]
+ ""
+ "*
+{
+ s390_output_constant_pool (asm_out_file);
+ return \"\";
+}"
+ [(set_attr "op_type" "NN")
+ (set_attr "type" "integer")])
+
;;
;; Peephole optimization patterns.