summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-05 14:06:25 +0000
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-05 14:06:25 +0000
commitd345b49344f084be829d9bc5877c14b39f0e95db (patch)
tree84f9b8f8b8c3088fe73f9fe8a8a2c9d737d54ca2 /gcc/config
parent4c29d398a1296efe38645675bd783f2aa0958eda (diff)
downloadgcc-d345b49344f084be829d9bc5877c14b39f0e95db.tar.gz
* config/s390/s390.c (s390_dump_pool): Remove return value.
Use gen_pool_align, gen_pool_section_start/end instead of gen_pool_start/end_31/64. * config/s390/s390.md (UNSPECV_POOL_START, UNSPECV_POOL_END): Remove. (UNSPECV_POOL_SECTION, UNSPECV_POOL_ALIGN): New constants. ("pool_start_31", "pool_end_31"): Remove. ("pool_start_64", "pool_end_64"): Likewise. ("pool_align", "pool_section_start", "pool_section_end": New insns. * config/s390/s390.c (s390_cannot_copy_insn_p): New function. (TARGET_CANNOT_COPY_INSN_P): Define. (s390_cannot_force_const_mem): Handle UNSPEC_INSN. (struct constant_pool): New member 'execute'. (s390_add_execute, s390_find_execute): New functions. (s390_execute_label, s390_execute_target): Likewise. (s390_dump_pool): Output in-pool execute target templates. (s390_dump_execute): New function. (s390_alloc_pool, s390_free_pool): Handle execute templates. (s390_mainpool_start, s390_mainpool_finish): Likewise. (s390_chunkify_start, s390_chunkify_finish): Likewise. * config/s390/s390.md (UNSPEC_INSN, UNSPEC_EXECUTE): New constants. ("*execute"): New insn pattern. ("movmem_short", "*movmem_short"): Use splitters to generate explicit execute pattern, remove embedded execute. ("clrmem_short", "*clrmem_short"): Likewise. ("cmpmem_short", "*cmpmem_short"): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@88555 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/s390/s390.c241
-rw-r--r--gcc/config/s390/s390.md308
2 files changed, 431 insertions, 118 deletions
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 21679c3ea81..c1414cf48f3 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -70,6 +70,7 @@ static enum attr_type s390_safe_attr_type (rtx);
static int s390_adjust_priority (rtx, int);
static int s390_issue_rate (void);
static int s390_first_cycle_multipass_dfa_lookahead (void);
+static bool s390_cannot_copy_insn_p (rtx);
static bool s390_rtx_costs (rtx, int, int, int *);
static int s390_address_cost (rtx);
static void s390_reorg (void);
@@ -127,6 +128,8 @@ static bool s390_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD s390_first_cycle_multipass_dfa_lookahead
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P s390_cannot_copy_insn_p
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS s390_rtx_costs
#undef TARGET_ADDRESS_COST
@@ -2123,6 +2126,11 @@ s390_cannot_force_const_mem (rtx x)
case UNSPEC_INDNTPOFF:
return false;
+ /* If the literal pool shares the code section, be put
+ execute template placeholders into the pool as well. */
+ case UNSPEC_INSN:
+ return TARGET_CPU_ZARCH;
+
default:
return true;
}
@@ -4720,6 +4728,7 @@ struct constant_pool
bitmap insns;
struct constant *constants[NR_C_MODES];
+ struct constant *execute;
rtx label;
int size;
};
@@ -4738,7 +4747,12 @@ static void s390_add_pool_insn (struct constant_pool *, rtx);
static struct constant_pool *s390_find_pool (struct constant_pool *, rtx);
static void s390_add_constant (struct constant_pool *, rtx, enum machine_mode);
static rtx s390_find_constant (struct constant_pool *, rtx, enum machine_mode);
-static rtx s390_dump_pool (struct constant_pool *, bool);
+static void s390_add_execute (struct constant_pool *, rtx);
+static rtx s390_find_execute (struct constant_pool *, rtx);
+static rtx s390_execute_label (rtx);
+static rtx s390_execute_target (rtx);
+static void s390_dump_pool (struct constant_pool *, bool);
+static void s390_dump_execute (struct constant_pool *);
static struct constant_pool *s390_alloc_pool (void);
static void s390_free_pool (struct constant_pool *);
@@ -4857,24 +4871,130 @@ s390_find_constant (struct constant_pool *pool, rtx val,
return offset;
}
+/* Add execute target for INSN to the constant pool POOL. */
+
+static void
+s390_add_execute (struct constant_pool *pool, rtx insn)
+{
+ struct constant *c;
+
+ for (c = pool->execute; c != NULL; c = c->next)
+ if (INSN_UID (insn) == INSN_UID (c->value))
+ break;
+
+ if (c == NULL)
+ {
+ rtx label = s390_execute_label (insn);
+ gcc_assert (label);
+
+ c = (struct constant *) xmalloc (sizeof *c);
+ c->value = insn;
+ c->label = label == const0_rtx ? gen_label_rtx () : XEXP (label, 0);
+ c->next = pool->execute;
+ pool->execute = c;
+ pool->size += label == const0_rtx ? 6 : 0;
+ }
+}
+
+/* Find execute target for INSN in the constant pool POOL.
+ Return an RTX describing the distance from the start of
+ the pool to the location of the execute target. */
+
+static rtx
+s390_find_execute (struct constant_pool *pool, rtx insn)
+{
+ struct constant *c;
+ rtx offset;
+
+ for (c = pool->execute; c != NULL; c = c->next)
+ if (INSN_UID (insn) == INSN_UID (c->value))
+ break;
+
+ if (c == NULL)
+ abort ();
+
+ offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
+ gen_rtx_LABEL_REF (Pmode, pool->label));
+ offset = gen_rtx_CONST (Pmode, offset);
+ return offset;
+}
+
+/* Check whether INSN is an execute. Return the label_ref to its
+ execute target template if so, NULL_RTX otherwise. */
+
+static rtx
+s390_execute_label (rtx insn)
+{
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == UNSPEC
+ && XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE)
+ return XVECEXP (XVECEXP (PATTERN (insn), 0, 0), 0, 2);
+
+ return NULL_RTX;
+}
+
+/* For an execute INSN, extract the execute target template. */
+
+static rtx
+s390_execute_target (rtx insn)
+{
+ rtx pattern = PATTERN (insn);
+ gcc_assert (s390_execute_label (insn));
+
+ if (XVECLEN (pattern, 0) == 2)
+ {
+ pattern = copy_rtx (XVECEXP (pattern, 0, 1));
+ }
+ else
+ {
+ rtvec vec = rtvec_alloc (XVECLEN (pattern, 0) - 1);
+ int i;
+
+ for (i = 0; i < XVECLEN (pattern, 0) - 1; i++)
+ RTVEC_ELT (vec, i) = copy_rtx (XVECEXP (pattern, 0, i + 1));
+
+ pattern = gen_rtx_PARALLEL (VOIDmode, vec);
+ }
+
+ return pattern;
+}
+
+/* Indicate that INSN cannot be duplicated. This is the case for
+ execute insns that carry a unique label. */
+
+static bool
+s390_cannot_copy_insn_p (rtx insn)
+{
+ rtx label = s390_execute_label (insn);
+ return label && label != const0_rtx;
+}
+
/* Dump out the constants in POOL. If REMOTE_LABEL is true,
do not emit the pool base label. */
-static rtx
+static void
s390_dump_pool (struct constant_pool *pool, bool remote_label)
{
struct constant *c;
- rtx insn;
+ rtx insn = pool->pool_insn;
int i;
- /* Pool start insn switches to proper section
- and guarantees necessary alignment. */
+ /* Switch to rodata section. */
if (TARGET_CPU_ZARCH)
- insn = emit_insn_after (gen_pool_start_64 (), pool->pool_insn);
+ {
+ insn = emit_insn_after (gen_pool_section_start (), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
+
+ /* Ensure minimum pool alignment. */
+ if (TARGET_CPU_ZARCH)
+ insn = emit_insn_after (gen_pool_align (GEN_INT (8)), insn);
else
- insn = emit_insn_after (gen_pool_start_31 (), pool->pool_insn);
+ insn = emit_insn_after (gen_pool_align (GEN_INT (4)), insn);
INSN_ADDRESSES_NEW (insn, -1);
+ /* Emit pool base label. */
if (!remote_label)
{
insn = emit_label_after (pool->label, insn);
@@ -4908,21 +5028,60 @@ s390_dump_pool (struct constant_pool *pool, bool remote_label)
INSN_ADDRESSES_NEW (insn, -1);
}
- /* Pool end insn switches back to previous section
- and guarantees necessary alignment. */
- if (TARGET_CPU_ZARCH)
- insn = emit_insn_after (gen_pool_end_64 (), insn);
- else
- insn = emit_insn_after (gen_pool_end_31 (), insn);
+ /* Ensure minimum alignment for instructions. */
+ insn = emit_insn_after (gen_pool_align (GEN_INT (2)), insn);
INSN_ADDRESSES_NEW (insn, -1);
+ /* Output in-pool execute template insns. */
+ for (c = pool->execute; c; c = c->next)
+ {
+ if (s390_execute_label (c->value) != const0_rtx)
+ continue;
+
+ insn = emit_label_after (c->label, insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+
+ insn = emit_insn_after (s390_execute_target (c->value), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
+
+ /* Switch back to previous section. */
+ if (TARGET_CPU_ZARCH)
+ {
+ insn = emit_insn_after (gen_pool_section_end (), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
+
insn = emit_barrier_after (insn);
INSN_ADDRESSES_NEW (insn, -1);
/* Remove placeholder insn. */
remove_insn (pool->pool_insn);
- return insn;
+ /* Output out-of-pool execute template isns. */
+ s390_dump_execute (pool);
+}
+
+/* Dump out the out-of-pool execute template insns in POOL
+ at the end of the instruction stream. */
+
+static void
+s390_dump_execute (struct constant_pool *pool)
+{
+ struct constant *c;
+ rtx insn;
+
+ for (c = pool->execute; c; c = c->next)
+ {
+ if (s390_execute_label (c->value) == const0_rtx)
+ continue;
+
+ insn = emit_label (c->label);
+ INSN_ADDRESSES_NEW (insn, -1);
+
+ insn = emit_insn (s390_execute_target (c->value));
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
}
/* Allocate new constant_pool structure. */
@@ -4938,6 +5097,7 @@ s390_alloc_pool (void)
for (i = 0; i < NR_C_MODES; i++)
pool->constants[i] = NULL;
+ pool->execute = NULL;
pool->label = gen_label_rtx ();
pool->first_insn = NULL_RTX;
pool->pool_insn = NULL_RTX;
@@ -4952,17 +5112,20 @@ s390_alloc_pool (void)
static void
s390_free_pool (struct constant_pool *pool)
{
+ struct constant *c, *next;
int i;
for (i = 0; i < NR_C_MODES; i++)
+ for (c = pool->constants[i]; c; c = next)
+ {
+ next = c->next;
+ free (c);
+ }
+
+ for (c = pool->execute; c; c = next)
{
- struct constant *c = pool->constants[i];
- while (c != NULL)
- {
- struct constant *next = c->next;
- free (c);
- c = next;
- }
+ next = c->next;
+ free (c);
}
BITMAP_XFREE (pool->insns);
@@ -4992,7 +5155,11 @@ s390_mainpool_start (void)
pool->pool_insn = insn;
}
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+ if (s390_execute_label (insn))
+ {
+ s390_add_execute (pool, insn);
+ }
+ else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{
rtx pool_ref = NULL_RTX;
find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -5034,6 +5201,9 @@ s390_mainpool_finish (struct constant_pool *pool)
/* If the pool is empty, we're done. */
if (pool->size == 0)
{
+ /* However, we may have out-of-pool execute templates. */
+ s390_dump_execute (pool);
+
/* We don't actually need a base register after all. */
cfun->machine->base_reg = NULL_RTX;
@@ -5120,8 +5290,12 @@ s390_mainpool_finish (struct constant_pool *pool)
find_constant_pool_ref (PATTERN (insn), &pool_ref);
if (pool_ref)
{
- addr = s390_find_constant (pool, get_pool_constant (pool_ref),
- get_pool_mode (pool_ref));
+ if (s390_execute_label (insn))
+ addr = s390_find_execute (pool, insn);
+ else
+ addr = s390_find_constant (pool, get_pool_constant (pool_ref),
+ get_pool_mode (pool_ref));
+
replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
INSN_CODE (insn) = -1;
}
@@ -5184,7 +5358,15 @@ s390_chunkify_start (void)
}
}
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+ if (s390_execute_label (insn))
+ {
+ if (!curr_pool)
+ curr_pool = s390_start_pool (&pool_list, insn);
+
+ s390_add_execute (curr_pool, insn);
+ s390_add_pool_insn (curr_pool, insn);
+ }
+ else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{
rtx pool_ref = NULL_RTX;
find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -5439,8 +5621,13 @@ s390_chunkify_finish (struct constant_pool *pool_list)
find_constant_pool_ref (PATTERN (insn), &pool_ref);
if (pool_ref)
{
- addr = s390_find_constant (curr_pool, get_pool_constant (pool_ref),
- get_pool_mode (pool_ref));
+ if (s390_execute_label (insn))
+ addr = s390_find_execute (curr_pool, insn);
+ else
+ addr = s390_find_constant (curr_pool,
+ get_pool_constant (pool_ref),
+ get_pool_mode (pool_ref));
+
replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
INSN_CODE (insn) = -1;
}
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index a2408d75196..5a649932329 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -94,6 +94,8 @@
(UNSPEC_RELOAD_BASE 210)
(UNSPEC_MAIN_BASE 211)
(UNSPEC_LTREF 212)
+ (UNSPEC_INSN 213)
+ (UNSPEC_EXECUTE 214)
; TLS relocation specifiers
(UNSPEC_TLSGD 500)
@@ -126,8 +128,8 @@
; Literal pool
(UNSPECV_POOL 200)
- (UNSPECV_POOL_START 201)
- (UNSPECV_POOL_END 202)
+ (UNSPECV_POOL_SECTION 201)
+ (UNSPECV_POOL_ALIGN 202)
(UNSPECV_POOL_ENTRY 203)
(UNSPECV_MAIN_POOL 300)
@@ -1594,6 +1596,17 @@
;; String instructions.
;;
+(define_insn "*execute"
+ [(match_parallel 0 ""
+ [(unspec [(match_operand 1 "register_operand" "a")
+ (match_operand:BLK 2 "memory_operand" "R")
+ (match_operand 3 "" "")] UNSPEC_EXECUTE)])]
+ "GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
+ && GET_MODE_SIZE (GET_MODE (operands[1])) <= UNITS_PER_WORD"
+ "ex\t%1,%2"
+ [(set_attr "op_type" "RX")])
+
+
;
; strlenM instruction pattern(s).
;
@@ -1698,36 +1711,72 @@
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "nonmemory_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_dup 3))])]
""
"operands[3] = gen_rtx_SCRATCH (Pmode);")
(define_insn "*movmem_short"
- [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q"))
- (use (match_operand 2 "nonmemory_operand" "n,a"))
- (clobber (match_scratch 3 "=X,&a"))]
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q,Q"))
+ (use (match_operand 2 "nonmemory_operand" "n,a,a"))
+ (use (match_operand 3 "immediate_operand" "X,R,X"))
+ (clobber (match_scratch 4 "=X,X,&a"))]
"(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
- && GET_MODE (operands[3]) == Pmode"
-{
- switch (which_alternative)
- {
- case 0:
- return "mvc\t%O0(%b2+1,%R0),%1";
+ && GET_MODE (operands[4]) == Pmode"
+ "#"
+ [(set_attr "op_type" "SS,RX,RX")
+ (set_attr "type" "cs")])
- case 1:
- output_asm_insn ("bras\t%3,.+10", operands);
- output_asm_insn ("mvc\t%O0(1,%R0),%1", operands);
- return "ex\t%2,0(%3)";
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "const_int_operand" ""))
+ (use (match_operand 3 "immediate_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (match_dup 1))
+ (use (match_dup 2))])]
+ "operands[2] = GEN_INT ((INTVAL (operands[2]) & 0xff) + 1);")
- default:
- abort ();
- }
-}
- [(set_attr "op_type" "SS,NN")
- (set_attr "type" "cs,cs")
- (set_attr "atype" "*,agen")
- (set_attr "length" "*,14")])
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "register_operand" ""))
+ (use (match_operand 3 "memory_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(unspec [(match_dup 2) (match_dup 3)
+ (const_int 0)] UNSPEC_EXECUTE)
+ (set (match_dup 0) (match_dup 1))
+ (use (const_int 1))])]
+ "")
+
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (match_operand 3 "register_operand" ""))]
+ "reload_completed && TARGET_CPU_ZARCH"
+ [(set (match_dup 3) (label_ref (match_dup 4)))
+ (parallel
+ [(unspec [(match_dup 2) (mem:BLK (match_dup 3))
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+ (set (match_dup 0) (match_dup 1))
+ (use (const_int 1))])]
+ "operands[4] = gen_label_rtx ();")
+
+(define_insn "*mvc"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q")
+ (match_operand:BLK 1 "memory_operand" "Q"))
+ (use (match_operand 2 "const_int_operand" "n"))]
+ ""
+ "mvc\t%O0(%2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "type" "cs")])
; Move a block of arbitrary length.
@@ -1820,38 +1869,81 @@
[(set (match_operand:BLK 0 "memory_operand" "")
(const_int 0))
(use (match_operand 1 "nonmemory_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_dup 2))
(clobber (reg:CC 33))])]
""
"operands[2] = gen_rtx_SCRATCH (Pmode);")
(define_insn "*clrmem_short"
- [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
(const_int 0))
- (use (match_operand 1 "nonmemory_operand" "n,a"))
- (clobber (match_scratch 2 "=X,&a"))
+ (use (match_operand 1 "nonmemory_operand" "n,a,a"))
+ (use (match_operand 2 "immediate_operand" "X,R,X"))
+ (clobber (match_scratch 3 "=X,X,&a"))
(clobber (reg:CC 33))]
"(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
- && GET_MODE (operands[2]) == Pmode"
-{
- switch (which_alternative)
- {
- case 0:
- return "xc\t%O0(%b1+1,%R0),%0";
+ && GET_MODE (operands[3]) == Pmode"
+ "#"
+ [(set_attr "op_type" "SS,RX,RX")
+ (set_attr "type" "cs")])
- case 1:
- output_asm_insn ("bras\t%2,.+10", operands);
- output_asm_insn ("xc\t%O0(1,%R0),%0", operands);
- return "ex\t%1,0(%2)";
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "const_int_operand" ""))
+ (use (match_operand 2 "immediate_operand" ""))
+ (clobber (scratch))
+ (clobber (reg:CC 33))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (const_int 0))
+ (use (match_dup 1))
+ (clobber (reg:CC 33))])]
+ "operands[1] = GEN_INT ((INTVAL (operands[1]) & 0xff) + 1);")
- default:
- abort ();
- }
-}
- [(set_attr "op_type" "SS,NN")
- (set_attr "type" "cs,cs")
- (set_attr "atype" "*,agen")
- (set_attr "length" "*,14")])
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "register_operand" ""))
+ (use (match_operand 2 "memory_operand" ""))
+ (clobber (scratch))
+ (clobber (reg:CC 33))]
+ "reload_completed"
+ [(parallel
+ [(unspec [(match_dup 1) (match_dup 2)
+ (const_int 0)] UNSPEC_EXECUTE)
+ (set (match_dup 0) (const_int 0))
+ (use (const_int 1))
+ (clobber (reg:CC 33))])]
+ "")
+
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (match_operand 2 "register_operand" ""))
+ (clobber (reg:CC 33))]
+ "reload_completed && TARGET_CPU_ZARCH"
+ [(set (match_dup 2) (label_ref (match_dup 3)))
+ (parallel
+ [(unspec [(match_dup 1) (mem:BLK (match_dup 2))
+ (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+ (set (match_dup 0) (const_int 0))
+ (use (const_int 1))
+ (clobber (reg:CC 33))])]
+ "operands[3] = gen_label_rtx ();")
+
+(define_insn "*xc_zero"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q")
+ (const_int 0))
+ (use (match_operand 1 "const_int_operand" "n"))
+ (clobber (reg:CC 33))]
+ ""
+ "xc\t%O0(%1,%R0),%0"
+ [(set_attr "op_type" "SS")
+ (set_attr "type" "cs")])
; Clear a block of arbitrary length.
@@ -1931,37 +2023,77 @@
(compare:CCU (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "nonmemory_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_dup 3))])]
""
"operands[3] = gen_rtx_SCRATCH (Pmode);")
(define_insn "*cmpmem_short"
[(set (reg:CCU 33)
- (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q")))
- (use (match_operand 2 "nonmemory_operand" "n,a"))
- (clobber (match_scratch 3 "=X,&a"))]
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q,Q")))
+ (use (match_operand 2 "nonmemory_operand" "n,a,a"))
+ (use (match_operand 3 "immediate_operand" "X,R,X"))
+ (clobber (match_scratch 4 "=X,X,&a"))]
"(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
- && GET_MODE (operands[3]) == Pmode"
-{
- switch (which_alternative)
- {
- case 0:
- return "clc\t%O0(%b2+1,%R0),%1";
+ && GET_MODE (operands[4]) == Pmode"
+ "#"
+ [(set_attr "op_type" "SS,RX,RX")
+ (set_attr "type" "cs")])
- case 1:
- output_asm_insn ("bras\t%3,.+10", operands);
- output_asm_insn ("clc\t%O0(1,%R0),%1", operands);
- return "ex\t%2,0(%3)";
+(define_split
+ [(set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "const_int_operand" ""))
+ (use (match_operand 3 "immediate_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(set (reg:CCU 33) (compare:CCU (match_dup 0) (match_dup 1)))
+ (use (match_dup 2))])]
+ "operands[2] = GEN_INT ((INTVAL (operands[2]) & 0xff) + 1);")
- default:
- abort ();
- }
-}
- [(set_attr "op_type" "SS,NN")
- (set_attr "type" "cs,cs")
- (set_attr "atype" "*,agen")
- (set_attr "length" "*,14")])
+(define_split
+ [(set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "register_operand" ""))
+ (use (match_operand 3 "memory_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(unspec [(match_dup 2) (match_dup 3)
+ (const_int 0)] UNSPEC_EXECUTE)
+ (set (reg:CCU 33) (compare:CCU (match_dup 0) (match_dup 1)))
+ (use (const_int 1))])]
+ "")
+
+(define_split
+ [(set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (match_operand 3 "register_operand" ""))]
+ "reload_completed && TARGET_CPU_ZARCH"
+ [(set (match_dup 3) (label_ref (match_dup 4)))
+ (parallel
+ [(unspec [(match_dup 2) (mem:BLK (match_dup 3))
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+ (set (reg:CCU 33) (compare:CCU (match_dup 0) (match_dup 1)))
+ (use (const_int 1))])]
+ "operands[4] = gen_label_rtx ();")
+
+(define_insn "*clc"
+ [(set (reg:CCU 33)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "=Q")
+ (match_operand:BLK 1 "memory_operand" "Q")))
+ (use (match_operand 2 "const_int_operand" "n"))]
+ ""
+ "clc\t%O0(%2,%R0),%1"
+ [(set_attr "op_type" "SS")
+ (set_attr "type" "cs")])
; Compare a block of arbitrary length.
@@ -7170,33 +7302,27 @@
(set (attr "length")
(symbol_ref "GET_MODE_SIZE (GET_MODE (PATTERN (insn)))"))])
-(define_insn "pool_start_31"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
- "!TARGET_CPU_ZARCH"
- ".align\t4"
- [(set_attr "op_type" "NN")
- (set_attr "length" "2")])
-
-(define_insn "pool_end_31"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)]
- "!TARGET_CPU_ZARCH"
- ".align\t2"
- [(set_attr "op_type" "NN")
- (set_attr "length" "2")])
+(define_insn "pool_align"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "n")]
+ UNSPECV_POOL_ALIGN)]
+ ""
+ ".align\t%0"
+ [(set_attr "op_type" "NN")
+ (set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
-(define_insn "pool_start_64"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
- "TARGET_CPU_ZARCH"
- ".section\t.rodata\;.align\t8"
- [(set_attr "op_type" "NN")
- (set_attr "length" "0")])
+(define_insn "pool_section_start"
+ [(unspec_volatile [(const_int 1)] UNSPECV_POOL_SECTION)]
+ ""
+ ".section\t.rodata"
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "0")])
-(define_insn "pool_end_64"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)]
- "TARGET_CPU_ZARCH"
+(define_insn "pool_section_end"
+ [(unspec_volatile [(const_int 0)] UNSPECV_POOL_SECTION)]
+ ""
".previous"
- [(set_attr "op_type" "NN")
- (set_attr "length" "0")])
+ [(set_attr "op_type" "NN")
+ (set_attr "length" "0")])
(define_insn "main_base_31_small"
[(set (match_operand 0 "register_operand" "=a")