aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.7/gcc/config/s390
diff options
context:
space:
mode:
authorDan Albert <danalbert@google.com>2015-06-17 11:09:54 -0700
committerDan Albert <danalbert@google.com>2015-06-17 14:15:22 -0700
commitf378ebf14df0952eae870c9865bab8326aa8f137 (patch)
tree31794503eb2a8c64ea5f313b93100f1163afcffb /gcc-4.7/gcc/config/s390
parent2c58169824949d3a597d9fa81931e001ef9b1bd0 (diff)
downloadtoolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.gz
toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.tar.bz2
toolchain_gcc-f378ebf14df0952eae870c9865bab8326aa8f137.zip
Delete old versions of GCC.
Change-Id: I710f125d905290e1024cbd67f48299861790c66c
Diffstat (limited to 'gcc-4.7/gcc/config/s390')
-rw-r--r--gcc-4.7/gcc/config/s390/2064.md135
-rw-r--r--gcc-4.7/gcc/config/s390/2084.md310
-rw-r--r--gcc-4.7/gcc/config/s390/2097.md764
-rw-r--r--gcc-4.7/gcc/config/s390/2817.md315
-rw-r--r--gcc-4.7/gcc/config/s390/constraints.md492
-rw-r--r--gcc-4.7/gcc/config/s390/linux.h91
-rw-r--r--gcc-4.7/gcc/config/s390/predicates.md406
-rw-r--r--gcc-4.7/gcc/config/s390/s390-modes.def174
-rw-r--r--gcc-4.7/gcc/config/s390/s390-opts.h41
-rw-r--r--gcc-4.7/gcc/config/s390/s390-protos.h113
-rw-r--r--gcc-4.7/gcc/config/s390/s390.c10793
-rw-r--r--gcc-4.7/gcc/config/s390/s390.h909
-rw-r--r--gcc-4.7/gcc/config/s390/s390.md9416
-rw-r--r--gcc-4.7/gcc/config/s390/s390.opt148
-rw-r--r--gcc-4.7/gcc/config/s390/s390x.h27
-rw-r--r--gcc-4.7/gcc/config/s390/t-linux6410
-rw-r--r--gcc-4.7/gcc/config/s390/tpf.h124
-rw-r--r--gcc-4.7/gcc/config/s390/tpf.md33
-rw-r--r--gcc-4.7/gcc/config/s390/tpf.opt27
19 files changed, 0 insertions, 24328 deletions
diff --git a/gcc-4.7/gcc/config/s390/2064.md b/gcc-4.7/gcc/config/s390/2064.md
deleted file mode 100644
index 143978334..000000000
--- a/gcc-4.7/gcc/config/s390/2064.md
+++ /dev/null
@@ -1,135 +0,0 @@
-;; Scheduling description for z900 (cpu 2064).
-;; Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
-;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-;; Ulrich Weigand (uweigand@de.ibm.com).
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 3, or (at your option) any later
-;; version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;;
-;; References:
-;; The microarchitecture of the IBM eServer z900 processor.
-;; E.M. Schwarz et al.
-;; IBM Journal of Research and Development Vol. 46 No 4/5, 2002.
-;;
-;; z900 (cpu 2064) pipeline
-;;
-;; dec
-;; --> | <---
-;; LA bypass | agen |
-;; | | |
-;; --- c1 | Load bypass
-;; | |
-;; c2----
-;; |
-;; e1
-;; |
-;; wr
-
-;; This scheduler description is also used for the g5 and g6.
-
-(define_automaton "z_ipu")
-(define_cpu_unit "z_e1" "z_ipu")
-(define_cpu_unit "z_wr" "z_ipu")
-
-
-(define_insn_reservation "z_la" 1
- (and (eq_attr "cpu" "z900,g5,g6")
- (eq_attr "type" "la"))
- "z_e1,z_wr")
-
-(define_insn_reservation "z_larl" 1
- (and (eq_attr "cpu" "z900,g5,g6")
- (eq_attr "type" "larl"))
- "z_e1,z_wr")
-
-(define_insn_reservation "z_load" 1
- (and (eq_attr "cpu" "z900,g5,g6")
- (eq_attr "type" "load"))
- "z_e1,z_wr")
-
-(define_insn_reservation "z_store" 1
- (and (eq_attr "cpu" "z900,g5,g6")
- (eq_attr "type" "store"))
- "z_e1,z_wr")
-
-(define_insn_reservation "z_sem" 2
- (and (eq_attr "cpu" "z900,g5,g6")
- (eq_attr "type" "sem"))
- "z_e1*2,z_wr")
-
-(define_insn_reservation "z_call" 5
- (and (eq_attr "cpu" "z900,g5,g6")
- (eq_attr "type" "jsr"))
- "z_e1*5,z_wr")
-
-(define_insn_reservation "z_mul" 5
- (and (eq_attr "cpu" "g5,g6,z900")
- (eq_attr "type" "imulsi,imulhi"))
- "z_e1*5,z_wr")
-
-(define_insn_reservation "z_inf" 10
- (and (eq_attr "cpu" "g5,g6,z900")
- (eq_attr "type" "idiv,imuldi"))
- "z_e1*10,z_wr")
-
-;; For everything else we check the atype flag.
-
-(define_insn_reservation "z_int" 1
- (and (eq_attr "cpu" "z900,g5,g6")
- (and (not (eq_attr "type" "la,larl,load,store,jsr"))
- (eq_attr "atype" "reg")))
- "z_e1,z_wr")
-
-(define_insn_reservation "z_agen" 1
- (and (eq_attr "cpu" "z900,g5,g6")
- (and (not (eq_attr "type" "la,larl,load,store,jsr"))
- (eq_attr "atype" "agen")))
- "z_e1,z_wr")
-
-;;
-;; s390_agen_dep_p returns 1, if a register is set in the
-;; first insn and used in the dependent insn to form a address.
-;;
-
-;;
-;; If an instruction uses a register to address memory, it needs
-;; to be set 5 cycles in advance.
-;;
-
-(define_bypass 5 "z_int,z_agen"
- "z_agen,z_la,z_call,z_load,z_store" "s390_agen_dep_p")
-
-;;
-;; A load type instruction uses a bypass to feed the result back
-;; to the address generation pipeline stage.
-;;
-
-(define_bypass 3 "z_load"
- "z_agen,z_la,z_call,z_load,z_store" "s390_agen_dep_p")
-
-;;
-;; A load address type instruction uses a bypass to feed the
-;; result back to the address generation pipeline stage.
-;;
-
-(define_bypass 2 "z_larl,z_la"
- "z_agen,z_la,z_call,z_load,z_store" "s390_agen_dep_p")
-
-
-
-
-
diff --git a/gcc-4.7/gcc/config/s390/2084.md b/gcc-4.7/gcc/config/s390/2084.md
deleted file mode 100644
index 2379f965e..000000000
--- a/gcc-4.7/gcc/config/s390/2084.md
+++ /dev/null
@@ -1,310 +0,0 @@
-;; Scheduling description for z990 (cpu 2084).
-;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2010
-;; Free Software Foundation, Inc.
-;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-;; Ulrich Weigand (uweigand@de.ibm.com).
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 3, or (at your option) any later
-;; version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-(define_automaton "x_ipu")
-
-(define_cpu_unit "x_e1_r,x_e1_s,x_e1_t" "x_ipu")
-(define_cpu_unit "x_wr_r,x_wr_s,x_wr_t,x_wr_fp" "x_ipu")
-(define_cpu_unit "x_s1,x_s2,x_s3,x_s4" "x_ipu")
-(define_cpu_unit "x_t1,x_t2,x_t3,x_t4" "x_ipu")
-(define_cpu_unit "x_f1,x_f2,x_f3,x_f4,x_f5,x_f6" "x_ipu")
-(define_cpu_unit "x_store_tok" "x_ipu")
-(define_cpu_unit "x_ms,x_mt" "x_ipu")
-
-(define_reservation "x-e1-st" "(x_e1_s | x_e1_t)")
-
-(define_reservation "x-e1-np" "(x_e1_r + x_e1_s + x_e1_t)")
-
-(absence_set "x_e1_r" "x_e1_s,x_e1_t")
-(absence_set "x_e1_s" "x_e1_t")
-
-;; Try to avoid int <-> fp transitions.
-
-(define_reservation "x-x" "x_s1|x_t1,x_s2|x_t2,x_s3|x_t3,x_s4|x_t4")
-(define_reservation "x-f" "x_f1,x_f2,x_f3,x_f4,x_f5,x_f6")
-(define_reservation "x-wr-st" "((x_wr_s | x_wr_t),x-x)")
-(define_reservation "x-wr-np" "((x_wr_r + x_wr_s + x_wr_t),x-x)")
-(define_reservation "x-wr-fp" "x_wr_fp,x-f")
-(define_reservation "x-mem" "x_ms|x_mt")
-
-(absence_set "x_wr_fp"
- "x_s1,x_s2,x_s3,x_s4,x_t1,x_t2,x_t3,x_t4,x_wr_s,x_wr_t")
-
-(absence_set "x_e1_r,x_wr_r,x_wr_s,x_wr_t"
- "x_f1,x_f2,x_f3,x_f4,x_f5,x_f6,x_wr_fp")
-
-;; Don't have any load type insn in same group as store
-
-(absence_set "x_ms,x_mt" "x_store_tok")
-
-
-;;
-;; Simple insns
-;;
-
-(define_insn_reservation "x_int" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (and (eq_attr "type" "integer")
- (eq_attr "atype" "reg")))
- "x-e1-st,x-wr-st")
-
-(define_insn_reservation "x_agen" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (and (eq_attr "type" "integer")
- (eq_attr "atype" "agen")))
- "x-e1-st,x-wr-st")
-
-(define_insn_reservation "x_lr" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "lr"))
- "x-e1-st,x-wr-st")
-
-(define_insn_reservation "x_la" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "la"))
- "x-e1-st,x-wr-st")
-
-(define_insn_reservation "x_larl" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "larl"))
- "x-e1-st,x-wr-st")
-
-(define_insn_reservation "x_load" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "load"))
- "x-e1-st+x-mem,x-wr-st")
-
-(define_insn_reservation "x_store" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "store"))
- "x-e1-st+x_store_tok,x-wr-st")
-
-(define_insn_reservation "x_branch" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "branch"))
- "x_e1_r,x_wr_r")
-
-(define_insn_reservation "x_call" 5
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "jsr"))
- "x-e1-np*5,x-wr-np")
-
-(define_insn_reservation "x_mul_hi" 2
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "imulhi"))
- "x-e1-np*2,x-wr-np")
-
-(define_insn_reservation "x_mul_sidi" 4
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "imulsi,imuldi"))
- "x-e1-np*4,x-wr-np")
-
-(define_insn_reservation "x_div" 10
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "idiv"))
- "x-e1-np*10,x-wr-np")
-
-(define_insn_reservation "x_sem" 17
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "sem"))
- "x-e1-np+x-mem,x-e1-np*16,x-wr-st")
-
-;;
-;; Multicycle insns
-;;
-
-(define_insn_reservation "x_cs" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "cs"))
- "x-e1-np,x-wr-np")
-
-(define_insn_reservation "x_vs" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "vs"))
- "x-e1-np*10,x-wr-np")
-
-(define_insn_reservation "x_stm" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "stm"))
- "(x-e1-np+x_store_tok)*10,x-wr-np")
-
-(define_insn_reservation "x_lm" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "lm"))
- "x-e1-np*10,x-wr-np")
-
-(define_insn_reservation "x_other" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "other"))
- "x-e1-np,x-wr-np")
-
-;;
-;; Floating point insns
-;;
-
-(define_insn_reservation "x_fsimptf" 7
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fsimptf,fhex"))
- "x_e1_t*2,x-wr-fp")
-
-(define_insn_reservation "x_fsimpdf" 6
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fsimpdf,fmuldf,fmadddf,fhex"))
- "x_e1_t,x-wr-fp")
-
-(define_insn_reservation "x_fsimpsf" 6
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fsimpsf,fmulsf,fmaddsf,fhex"))
- "x_e1_t,x-wr-fp")
-
-
-(define_insn_reservation "x_fmultf" 33
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fmultf"))
- "x_e1_t*27,x-wr-fp")
-
-
-(define_insn_reservation "x_fdivtf" 82
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fdivtf,fsqrttf"))
- "x_e1_t*76,x-wr-fp")
-
-(define_insn_reservation "x_fdivdf" 36
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fdivdf,fsqrtdf"))
- "x_e1_t*30,x-wr-fp")
-
-(define_insn_reservation "x_fdivsf" 36
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fdivsf,fsqrtsf"))
- "x_e1_t*30,x-wr-fp")
-
-
-(define_insn_reservation "x_floadtf" 6
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "floadtf"))
- "x_e1_t,x-wr-fp")
-
-(define_insn_reservation "x_floaddf" 6
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "floaddf"))
- "x_e1_t,x-wr-fp")
-
-(define_insn_reservation "x_floadsf" 6
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "floadsf"))
- "x_e1_t,x-wr-fp")
-
-
-(define_insn_reservation "x_fstoredf" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fstoredf"))
- "x_e1_t,x-wr-fp")
-
-(define_insn_reservation "x_fstoresf" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "fstoresf"))
- "x_e1_t,x-wr-fp")
-
-
-(define_insn_reservation "x_ftrunctf" 16
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "ftrunctf"))
- "x_e1_t*10,x-wr-fp")
-
-(define_insn_reservation "x_ftruncdf" 11
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "ftruncdf"))
- "x_e1_t*5,x-wr-fp")
-
-
-(define_insn_reservation "x_ftoi" 1
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "ftoi"))
- "x_e1_t*3,x-wr-fp")
-
-(define_insn_reservation "x_itof" 7
- (and (eq_attr "cpu" "z990,z9_109,z9_ec")
- (eq_attr "type" "itoftf,itofdf,itofsf"))
- "x_e1_t*3,x-wr-fp")
-
-(define_bypass 1 "x_fsimpdf" "x_fstoredf")
-
-(define_bypass 1 "x_fsimpsf" "x_fstoresf")
-
-(define_bypass 1 "x_floaddf" "x_fsimpdf,x_fstoredf,x_floaddf")
-
-(define_bypass 1 "x_floadsf" "x_fsimpsf,x_fstoresf,x_floadsf")
-
-;;
-;; s390_agen_dep_p returns 1, if a register is set in the
-;; first insn and used in the dependent insn to form a address.
-;;
-
-;;
-;; If an instruction uses a register to address memory, it needs
-;; to be set 5 cycles in advance.
-;;
-
-(define_bypass 5 "x_int,x_agen,x_lr"
- "x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
- "s390_agen_dep_p")
-
-(define_bypass 9 "x_int,x_agen,x_lr"
- "x_floadtf, x_floaddf, x_floadsf, x_fstoredf, x_fstoresf,\
- x_fsimpdf, x_fsimpsf, x_fdivdf, x_fdivsf"
- "s390_agen_dep_p")
-;;
-;; A load type instruction uses a bypass to feed the result back
-;; to the address generation pipeline stage.
-;;
-
-(define_bypass 4 "x_load"
- "x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
- "s390_agen_dep_p")
-
-(define_bypass 5 "x_load"
- "x_floadtf, x_floaddf, x_floadsf, x_fstoredf, x_fstoresf,\
- x_fsimpdf, x_fsimpsf, x_fdivdf, x_fdivsf"
- "s390_agen_dep_p")
-
-;;
-;; A load address type instruction uses a bypass to feed the
-;; result back to the address generation pipeline stage.
-;;
-
-(define_bypass 3 "x_larl,x_la"
- "x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
- "s390_agen_dep_p")
-
-(define_bypass 5 "x_larl, x_la"
- "x_floadtf, x_floaddf, x_floadsf, x_fstoredf, x_fstoresf,\
- x_fsimpdf, x_fsimpsf, x_fdivdf, x_fdivsf"
- "s390_agen_dep_p")
-
-;;
-;; Operand forwarding
-;;
-
-(define_bypass 0 "x_lr,x_la,x_load" "x_int,x_lr")
-
-
diff --git a/gcc-4.7/gcc/config/s390/2097.md b/gcc-4.7/gcc/config/s390/2097.md
deleted file mode 100644
index 77c206ecd..000000000
--- a/gcc-4.7/gcc/config/s390/2097.md
+++ /dev/null
@@ -1,764 +0,0 @@
-;; Scheduling description for z10 (cpu 2097).
-;; Copyright (C) 2008, 2010 Free Software Foundation, Inc.
-;; Contributed by Wolfgang Gellerich (gellerich@de.ibm.com).
-
-
-; General naming conventions used in this file:
-; - The two pipelines are called S and T, respectively.
-; - A name ending "_S" or "_T" indicates that something happens in
-; (or belongs to) this pipeline.
-; - A name ending "_ANY" indicates that something happens in (or belongs
-; to) either of the two pipelines.
-; - A name ending "_BOTH" indicates that something happens in (or belongs
-; to) both pipelines.
-
-
-;; Automaton and components.
-
-(define_automaton "z10_cpu")
-
-(define_cpu_unit "z10_e1_S, z10_e1_T" "z10_cpu")
-(define_reservation "z10_e1_ANY" "(z10_e1_S | z10_e1_T)")
-(define_reservation "z10_e1_BOTH" "(z10_e1_S + z10_e1_T)")
-
-
-; Both pipelines can execute a branch instruction, and branch
-; instructions can be grouped with all other groupable instructions
-; but not with a second branch instruction.
-
-(define_cpu_unit "z10_branch_ANY" "z10_cpu")
-
-(define_insn_reservation "z10_branch" 4
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "branch"))
- "z10_branch_ANY + z10_e1_ANY, z10_Gate_ANY")
-
-
-; Z10 operand and result forwarding.
-
-; Instructions marked with the attributes as z10_fwd or z10_fr can
-; forward a value they load from one of their operants into a register
-; if the instruction in the second pipeline reads the same register.
-; The second operation must be superscalar. Instructions marked as
-; z10_rec or z10_fr can receive a value they read from a register is
-; this register gets updated by an instruction in the first pipeline.
-; The first instruction must be superscalar.
-
-
-; Forwarding from z10_fwd and z10_fr to z10_super.
-
-(define_bypass 0 "z10_la_fwd, z10_la_fwd_A1, z10_larl_fwd, z10_larl_fwd_A3, \
- z10_load_fwd, z10_load_fwd_A3, \
- z10_other_fwd, z10_other_fwd_A1, z10_other_fwd_A3, \
- z10_other_fr, z10_other_fr_A3, z10_other_fr_E1, \
- z10_other_fwd_E1, z10_lr_fr, z10_lr_fr_E1, \
- z10_int_fwd, z10_int_fwd_A1, z10_int_fwd_A3, \
- z10_int_fwd_E1, z10_int_fr, z10_int_fr_E1, \
- z10_int_fr_A3"
- "z10_other_super, z10_other_super_c_E1, z10_other_super_E1, \
- z10_int_super, z10_int_super_E1, \
- z10_lr, z10_store_super"
- " ! s390_agen_dep_p")
-
-
-; Forwarding from z10_super to frz10_ and z10_rec.
-
-(define_bypass 0 "z10_other_super, z10_other_super_E1, z10_other_super_c_E1, \
- z10_int_super, z10_int_super_E1, \
- z10_larl_super_E1, z10_larl_super, \
- z10_store_super"
- "z10_int_fr, z10_int_fr_E1, z10_int_fr_A3, \
- z10_other_fr, z10_other_fr_A3, z10_lr_fr, z10_lr_fr_E1, \
- z10_other_fr_E1, z10_store_rec"
- " ! s390_agen_dep_p")
-
-
-; Forwarding from z10_fwd and z10_fr to z10_rec and z10_fr.
-
-(define_bypass 0 "z10_la_fwd, z10_la_fwd_A1, z10_larl_fwd, z10_larl_fwd_A3, \
- z10_load_fwd, z10_load_fwd_A3, \
- z10_other_fwd, z10_other_fwd_A1, z10_other_fwd_A3, \
- z10_other_fr, z10_other_fr_A3, z10_other_fr_E1, \
- z10_other_fwd_E1, \
- z10_lr_fr, z10_lr_fr_E1, \
- z10_int_fwd, z10_int_fwd_A1, z10_int_fwd_A3, \
- z10_int_fwd_E1, z10_int_fr, z10_int_fr_E1, \
- z10_int_fr_A3"
- "z10_int_fr, z10_int_fr_E1, z10_int_fr_A3, \
- z10_other_fr, z10_other_fr_A3, z10_lr_fr, z10_lr_fr_E1, \
- z10_other_fr_E1, z10_store_rec"
- " ! s390_agen_dep_p")
-
-
-;
-; Simple insns
-;
-
-; Here is the cycle diagram for FXU-executed instructions:
-; ... A1 A2 A3 E1 P1 P2 P3 R0 ...
-; ^ ^ ^
-; | | updated GPR is available
-; | write to GPR
-; instruction reads GPR during this cycle
-
-
-; Variants of z10_int follow.
-
-(define_insn_reservation "z10_int" 6
- (and (and (eq_attr "cpu" "z10")
- (eq_attr "type" "integer"))
- (and (eq_attr "atype" "reg")
- (and (and (eq_attr "z10prop" "!z10_super")
- (eq_attr "z10prop" "!z10_super_c"))
- (and (and (and (and (eq_attr "z10prop" "!z10_super_E1")
- (eq_attr "z10prop" "!z10_super_c_E1"))
- (eq_attr "z10prop" "!z10_fwd"))
- (and (eq_attr "z10prop" "!z10_fwd_A1")
- (eq_attr "z10prop" "!z10_fwd_A3")))
- (and (and (eq_attr "z10prop" "!z10_fwd_E1")
- (eq_attr "z10prop" "!z10_fr"))
- (and (eq_attr "z10prop" "!z10_fr_E1")
- (eq_attr "z10prop" "!z10_fr_A3")))))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_super" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (ior (eq_attr "z10prop" "z10_super")
- (eq_attr "z10prop" "z10_super_c")))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_super_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (ior (eq_attr "z10prop" "z10_super_E1")
- (eq_attr "z10prop" "z10_super_c_E1")))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_fwd" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (eq_attr "z10prop" "z10_fwd"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_fwd_A1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (eq_attr "z10prop" "z10_fwd_A1"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_fwd_A3" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (eq_attr "z10prop" "z10_fwd_A3"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_fwd_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (eq_attr "z10prop" "z10_fwd_E1"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_fr" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (eq_attr "z10prop" "z10_fr"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_fr_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (eq_attr "z10prop" "z10_fr_E1"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_int_fr_A3" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (and (eq_attr "atype" "reg")
- (eq_attr "z10prop" "z10_fr_A3"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-; END of z10_int variants
-
-
-(define_insn_reservation "z10_agen" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "integer")
- (eq_attr "atype" "agen")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-
-(define_insn_reservation "z10_lr" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "lr")
- (and (eq_attr "z10prop" "!z10_fr")
- (eq_attr "z10prop" "!z10_fr_E1"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_lr_fr" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "lr")
- (eq_attr "z10prop" "z10_fr")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_lr_fr_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "lr")
- (eq_attr "z10prop" "z10_fr_E1")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_la" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "la")
- (and (eq_attr "z10prop" "!z10_fwd")
- (eq_attr "z10prop" "!z10_fwd_A1"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_la_fwd" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "la")
- (eq_attr "z10prop" "z10_fwd")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_la_fwd_A1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "la")
- (eq_attr "z10prop" "z10_fwd_A1")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-
-; larl-type instructions
-
-(define_insn_reservation "z10_larl" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "larl")
- (and (eq_attr "z10prop" "!z10_super_A1")
- (and (eq_attr "z10prop" "!z10_fwd")
- (and (eq_attr "z10prop" "!z10_fwd_A3")
- (and (eq_attr "z10prop" "!z10_super")
- (eq_attr "z10prop" "!z10_super_c"))
- (and (eq_attr "z10prop" "!z10_super_E1")
- (eq_attr "z10prop" "!z10_super_c_E1")))))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_larl_super" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "larl")
- (and (eq_attr "z10prop" "z10_super")
- (eq_attr "z10prop" "z10_super_c"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_larl_fwd" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "larl")
- (eq_attr "z10prop" "z10_fwd")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_larl_fwd_A3" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "larl")
- (eq_attr "z10prop" "z10_fwd_A3")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-
-(define_insn_reservation "z10_larl_A1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "larl")
- (eq_attr "z10prop" "z10_super_A1")))
- "z10_e1_ANY, z10_Gate_ANY")
-; "z10_e1_ANY")
-
-(define_insn_reservation "z10_larl_super_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "larl")
- (ior (eq_attr "z10prop" "z10_super_E1")
- (eq_attr "z10prop" "z10_super_c_E1"))))
- "z10_e1_ANY, z10_Gate_ANY")
-; "z10_e1_ANY")
-
-
-(define_insn_reservation "z10_load" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "load")
- (and (eq_attr "z10prop" "!z10_fwd")
- (eq_attr "z10prop" "!z10_fwd_A3"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_load_fwd" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "load")
- (eq_attr "z10prop" "z10_fwd")))
- "z10_e1_ANY, z10_Gate_ANY")
-; "z10_e1_ANY")
-
-(define_insn_reservation "z10_load_fwd_A3" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "load")
- (eq_attr "z10prop" "z10_fwd_A3")))
- "z10_e1_ANY, z10_Gate_ANY")
-; "z10_e1_ANY")
-
-(define_insn_reservation "z10_store" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "store")
- (and (eq_attr "z10prop" "!z10_rec")
- (and (eq_attr "z10prop" "!z10_super")
- (eq_attr "z10prop" "!z10_super_c")))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_store_super" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "store")
- (ior (eq_attr "z10prop" "z10_super")
- (eq_attr "z10prop" "z10_super_c"))))
- "z10_e1_ANY, z10_Gate_ANY")
-
-(define_insn_reservation "z10_store_rec" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "store")
- (eq_attr "z10prop" "z10_rec")))
- "z10_e1_ANY, z10_Gate_ANY")
-
-; The default_latency is chosen to drain off the pipeline.
-(define_insn_reservation "z10_call" 14
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "jsr"))
- "z10_e1_BOTH*4, z10_Gate_BOTH")
-
-; The default latency is for worst case. CS and CSG take one
-; cycle only (i.e. latency would be 6).
-(define_insn_reservation "z10_sem" 9
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "sem"))
- "z10_e1_BOTH*5, z10_Gate_ANY")
-
-(define_insn_reservation "z10_cs" 6
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "cs"))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_vs" 6
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "vs"))
- "z10_e1_BOTH*4, z10_Gate_BOTH")
-
-; Load and store multiple. Actual number of cycles
-; in unknown at compile.time.
-(define_insn_reservation "z10_stm" 10
- (and (eq_attr "cpu" "z10")
- (ior (eq_attr "type" "stm")
- (eq_attr "type" "lm")))
- "z10_e1_BOTH*4, z10_Gate_BOTH")
-
-
-; Subsets of z10_other follow.
-
-(define_insn_reservation "z10_other" 6
- (and (and (eq_attr "cpu" "z10")
- (eq_attr "type" "other"))
- (and (and (eq_attr "z10prop" "!z10_fwd")
- (eq_attr "z10prop" "!z10_fwd_A1"))
- (and (and (and (eq_attr "z10prop" "!z10_fr_A3")
- (eq_attr "z10prop" "!z10_fwd_A3"))
- (and (eq_attr "z10prop" "!z10_fr")
- (eq_attr "z10prop" "!z10_fr_E1")))
- (and (and (and (eq_attr "z10prop" "!z10_super")
- (eq_attr "z10prop" "!z10_super_c"))
- (eq_attr "z10prop" "!z10_super_c_E1"))
- (and (eq_attr "z10prop" "!z10_super_E1")
- (eq_attr "z10prop" "!z10_fwd_E1"))))))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_fr_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_fr_E1")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_super_c_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_super_c_E1")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_super_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_super_E1")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_fwd_E1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_fwd_E1")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_fwd" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_fwd")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_fwd_A3" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_fwd_A3")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_fwd_A1" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_fwd_A1")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_fr" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_fr")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_fr_A3" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (eq_attr "z10prop" "z10_fr_A3")))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-(define_insn_reservation "z10_other_super" 6
- (and (eq_attr "cpu" "z10")
- (and (eq_attr "type" "other")
- (ior (eq_attr "z10prop" "z10_super")
- (eq_attr "z10prop" "z10_super_c"))))
- "z10_e1_BOTH, z10_Gate_BOTH")
-
-; END of z10_other subsets.
-
-
-;
-; Floating point insns
-;
-
-; Z10 executes the following integer operations in the BFU pipeline.
-
-(define_insn_reservation "z10_mul_sidi" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "imulsi,imuldi,imulhi"))
- "z10_e1_BOTH, z10_Gate_FP")
-
-; Some variants take fewer cycles, but that is not relevant here.
-(define_insn_reservation "z10_div" 162
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "idiv"))
- "z10_e1_BOTH*4, z10_Gate_FP")
-
-
-; BFP multiplication and general instructions
-
-(define_insn_reservation "z10_fsimpdf" 6
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsimpdf,fmuldf,fmadddf"))
- "z10_e1_BOTH, z10_Gate_FP")
-
-(define_insn_reservation "z10_fsimpsf" 6
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsimpsf,fmulsf,fmaddsf"))
- "z10_e1_BOTH, z10_Gate_FP")
-
-(define_insn_reservation "z10_fmultf" 52
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fmultf"))
- "z10_e1_BOTH*4, z10_Gate_FP")
-
-(define_insn_reservation "z10_fsimptf" 14
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsimptf"))
- "z10_e1_BOTH*2, z10_Gate_FP")
-
-
-; BFP division
-
-(define_insn_reservation "z10_fdivtf" 113
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fdivtf"))
- "z10_e1_T*4, z10_Gate_FP")
-
-(define_insn_reservation "z10_fdivdf" 41
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fdivdf"))
- "z10_e1_T*4, z10_Gate_FP")
-
-(define_insn_reservation "z10_fdivsf" 34
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fdivsf"))
- "z10_e1_T*4, z10_Gate_FP")
-
-
-; BFP sqrt
-
-(define_insn_reservation "z10_fsqrtsf" 41
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsqrtsf"))
- "z10_e1_T*4, z10_Gate_FP")
-
-(define_insn_reservation "z10_fsqrtdf" 54
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsqrtdf"))
- "z10_e1_T*4, z10_Gate_FP")
-
-(define_insn_reservation "z10_fsqrtf" 122
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsqrttf"))
- "z10_e1_T*4, z10_Gate_FP")
-
-
-; BFP load and store
-
-(define_insn_reservation "z10_floadtf" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "floadtf"))
- "z10_e1_T, z10_Gate_FP")
-
-(define_insn_reservation "z10_floaddf" 1
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "floaddf"))
- "z10_e1_T, z10_Gate_FP")
-
-(define_insn_reservation "z10_floadsf" 1
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "floadsf"))
- "z10_e1_T, z10_Gate_FP")
-
-(define_insn_reservation "z10_fstoredf" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fstoredf,fstoredd"))
- "z10_e1_T, z10_Gate_FP")
-
-(define_insn_reservation "z10_fstoresf" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fstoresf,fstoresd"))
- "z10_e1_T, z10_Gate_FP")
-
-
-; BFP truncate
-(define_insn_reservation "z10_ftrunctf" 16
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "ftrunctf"))
- "z10_e1_T, z10_Gate_FP")
-
-(define_insn_reservation "z10_ftruncdf" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "ftruncdf"))
- "z10_e1_T, z10_Gate_FP")
-
-
-; Conversion between BFP and int.
-(define_insn_reservation "z10_ftoi" 13
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "ftoi"))
- "z10_e1_T, z10_Gate_FP")
-
-(define_insn_reservation "z10_itoftf" 14
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "itoftf"))
- "z10_e1_T*2, z10_Gate_FP")
-
-(define_insn_reservation "z10_itofsfdf" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "itofdf,itofsf"))
- "z10_e1_T, z10_Gate_FP")
-
-
-
-; BFP-related bypasses. There is no bypass for extended mode.
-(define_bypass 1 "z10_fsimpdf" "z10_fstoredf")
-(define_bypass 1 "z10_fsimpsf" "z10_fstoresf")
-(define_bypass 1 "z10_floaddf" "z10_fsimpdf, z10_fstoredf")
-(define_bypass 1 "z10_floadsf" "z10_fsimpsf, z10_fstoresf")
-
-
-;
-; insn_reservations for DFP instructions.
-;
-
-; Exact number of cycles is not known at compile-time.
-(define_insn_reservation "z10_fdivddtd" 40
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fdivdd,fdivtd"))
- "z10_e1_BOTH,z10_Gate_DFU")
-
-(define_insn_reservation "z10_ftruncsd" 38
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "ftruncsd"))
- "z10_e1_BOTH*4,z10_Gate_DFU")
-
-(define_insn_reservation "z10_ftruncdd" 340
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "ftruncsd"))
- "z10_e1_BOTH*4,z10_Gate_DFU")
-
-(define_insn_reservation "z10_floaddd" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "floaddd"))
- "z10_e1_BOTH,z10_Gate_DFU")
-
-(define_insn_reservation "z10_floadsd" 12
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "floadsd"))
- "z10_e1_BOTH,z10_Gate_DFU")
-
-; Exact number of cycles is not known at compile-time.
-(define_insn_reservation "z10_fmulddtd" 35
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fmuldd,fmultd"))
- "z10_e1_BOTH,z10_Gate_DFU")
-
-(define_insn_reservation "z10_fsimpdd" 17
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsimpdd"))
- "z10_e1_BOTH,z10_Gate_DFU")
-
-(define_insn_reservation "z10_fsimpsd" 17
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsimpsd"))
- "z10_e1_BOTH,z10_Gate_DFU")
-
-(define_insn_reservation "z10_fsimptd" 18
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "fsimptd"))
- "z10_e1_BOTH,z10_Gate_DFU")
-
-(define_insn_reservation "z10_itofdd" 36
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "itofdd"))
- "z10_e1_BOTH*3,z10_Gate_DFU")
-
-(define_insn_reservation "z10_itoftd" 49
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "itoftd"))
- "z10_e1_BOTH*3,z10_Gate_DFU")
-
-; Exact number of cycles is not known at compile-time.
-(define_insn_reservation "z10_ftoidfp" 30
- (and (eq_attr "cpu" "z10")
- (eq_attr "type" "ftoidfp"))
- "z10_e1_BOTH*3,z10_Gate_DFU")
-
-
-;
-; Address-related bypasses
-;
-
-; Here is the cycle diagram for address-related bypasses:
-; ... G1 G2 G3 A0 A1 A2 A3 E1 P1 P2 P3 R0 ...
-; ^ ^ ^ ^ ^ ^
-; | | | | | without bypass, its available AFTER this cycle
-; | | | | E1-type bypasses provide the new value AFTER this cycle
-; | | | A3-type bypasses provide the new value AFTER this cycle
-; | | A1-type bypasses provide the new value AFTER this cycle
-; | AGI resolution, actual USE of new value is DURING this cycle
-; AGI detection
-
-(define_bypass 3 "z10_larl_A1, z10_la_fwd_A1, z10_other_fwd_A1, \
- z10_int_fwd_A1"
- "z10_agen, z10_la, z10_branch, z10_call, z10_load, \
- z10_store, \
- z10_cs, z10_stm, z10_other"
- "s390_agen_dep_p")
-
-(define_bypass 5 "z10_larl_fwd_A3, z10_load_fwd_A3, z10_other_fwd_A3, \
- z10_other_fr_A3, z10_int_fwd_A3, z10_int_fr_A3"
- "z10_agen, z10_la, z10_branch, z10_call, z10_load, \
- z10_store, \
- z10_cs, z10_stm, z10_other"
- "s390_agen_dep_p")
-
-(define_bypass 6 "z10_other_fr_E1, z10_other_super_c_E1, z10_other_super_E1, \
- z10_other_fwd_E1, \
- z10_lr_fr_E1, z10_larl_super_E1, \
- z10_int_super_E1, z10_int_fwd_E1, z10_int_fr_E1"
- "z10_agen, z10_la, z10_branch, z10_call, z10_load, \
- z10_store, \
- z10_cs, z10_stm, z10_other"
- "s390_agen_dep_p")
-
-(define_bypass 9 "z10_int_super, z10_int_fwd, z10_int_fr"
- "z10_agen, z10_la, z10_branch, z10_call, z10_load, \
- z10_store, \
- z10_cs, z10_stm, z10_other"
- "s390_agen_dep_p")
-
-
-
-;
-; Try to avoid transitions between DFU-, BFU- and FXU-executed instructions as there is a
-; dispatch delay required.
-;
-
-
-; Declaration for some pseudo-pipeline stages that reflect the
-; dispatch gap when issueing an INT/FXU/BFU-executed instruction after
-; an instruction executed by a different unit has been executed. The
-; approach is that we pretend a pipelined execution of BFU operations
-; with as many stages as the gap is long and request that none of
-; these stages is busy when issueing a FXU- or DFU-executed
-; instruction. Similar for FXU- and DFU-executed instructions.
-
-; Declaration for FPU stages.
-(define_cpu_unit "z10_f0, z10_f1, z10_f2, z10_f3, z10_f4, z10_f5, z10_f6, \
- z10_f7, z10_f8, z10_f9, z10_f10, z10_f11, z10_f12" "z10_cpu")
-(define_reservation "z10_FP_PP" "z10_f0, z10_f1, z10_f2, z10_f3, z10_f4, \
- z10_f5, z10_f6, z10_f7, z10_f8, z10_f9, z10_f10, z10_f11, \
- z10_f12")
-
-; Declaration for FXU stages.
-(define_cpu_unit "z10_S1, z10_S2, z10_S3, z10_S4, z10_S5, z10_S6" "z10_cpu")
-(define_cpu_unit "z10_T1, z10_T2, z10_T3, z10_T4, z10_T5, z10_T6" "z10_cpu")
-(define_reservation "z10_INT_PP" "z10_S1 | z10_T1, z10_S2 | z10_T2, z10_S3 \
- | z10_T3, z10_S4 | z10_T4, z10_S5 | \
- z10_T5, z10_S6 | z10_T6")
-
-; Declaration for DFU stages.
-(define_cpu_unit "z10_d0, z10_d1, z10_d2, z10_d3, z10_d4, z10_d5, z10_d6"
- "z10_cpu")
-(define_reservation "z10_DFU_PP" "z10_d0, z10_d1, z10_d2, z10_d3, z10_d4, \
- z10_d5, z10_d6")
-
-
-; Pseudo-units representing whether the respective unit is available
-; in the sense that using it does not cause a dispatch delay.
-
-(define_cpu_unit "z10_S_avail, z10_T_avail, z10_FP_avail, z10_DFU_avail"
- "z10_cpu")
-
-(absence_set "z10_FP_avail"
- "z10_S1, z10_S2, z10_S3, z10_S4, z10_S5, z10_S6, z10_T1, z10_T2, z10_T3, z10_T4, \
- z10_T5, z10_T6, \
- z10_d0, z10_d1, z10_d2, z10_d3, z10_d4, z10_d5, z10_d6")
-
-(absence_set "z10_S_avail,z10_T_avail"
- "z10_f0, z10_f1, z10_f2, z10_f3, z10_f4, z10_f5, z10_f6, z10_f7, \
- z10_f8, z10_f9, z10_f10, z10_f11, z10_f12, \
- z10_d0, z10_d1, z10_d2, z10_d3, z10_d4, z10_d5, z10_d6")
-
-(absence_set "z10_DFU_avail"
- "z10_S1, z10_S2, z10_S3, z10_S4, z10_S5, z10_S6, z10_T1, z10_T2, z10_T3, z10_T4, \
- z10_T5, z10_T6, \
- z10_f0, z10_f1, z10_f2, z10_f3, z10_f4, z10_f5, z10_f6, z10_f7, \
- z10_f8, z10_f9, z10_f10, z10_f11, z10_f12")
-
-
-; Pseudo-units to be used in insn_reservations.
-
-(define_reservation "z10_Gate_ANY" "((z10_S_avail | z10_T_avail), z10_INT_PP)")
-(define_reservation "z10_Gate_BOTH" "((z10_S_avail + z10_T_avail), z10_INT_PP)")
-
-(define_reservation "z10_Gate_FP" "z10_FP_avail, z10_FP_PP")
-
-(define_reservation "z10_Gate_DFU" "z10_DFU_avail, z10_DFU_PP")
diff --git a/gcc-4.7/gcc/config/s390/2817.md b/gcc-4.7/gcc/config/s390/2817.md
deleted file mode 100644
index ea181b01f..000000000
--- a/gcc-4.7/gcc/config/s390/2817.md
+++ /dev/null
@@ -1,315 +0,0 @@
-;; Scheduling description for z196 (cpu 2817).
-;; Copyright (C) 2010
-;; Free Software Foundation, Inc.
-;; Contributed by Christian Borntraeger (Christian.Borntraeger@de.ibm.com)
-;; Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 3, or (at your option) any later
-;; version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-(define_automaton "z196_ipu")
-
-;; Fetch + Decoder
-(define_cpu_unit "z196_g1" "z196_ipu")
-(define_cpu_unit "z196_g2" "z196_ipu")
-(define_cpu_unit "z196_g3" "z196_ipu")
-(define_cpu_unit "z196_cr1" "z196_ipu")
-(define_cpu_unit "z196_cr2" "z196_ipu")
-(define_cpu_unit "z196_cr3" "z196_ipu")
-
-(final_presence_set "z196_g2" "z196_g1")
-(final_presence_set "z196_g3" "z196_g2")
-(final_presence_set "z196_cr2" "z196_cr1")
-(final_presence_set "z196_cr3" "z196_cr2")
-(exclusion_set "z196_g1" "z196_cr1")
-
-;; Instructions can be groupable, end a group, or be alone in a group.
-(define_reservation "z196_simple" "( z196_g1 | z196_g2 | z196_g3 )")
-(define_reservation "z196_ends" "( z196_g3 | ( z196_g2 + z196_g3 ) | ( z196_g1 + z196_g2 + z196_g3 ) )")
-
-;; Try to keep cracked and alone insns together in a clump. This will also
-;; improve the clumping of "normal" insns. We also allow crackes insns
-;; to go as a last instruction together with normal ones.
-(define_reservation "z196_crack" "( z196_cr1 | z196_cr2 | z196_cr3 | z196_g3)")
-(define_reservation "z196_alone" "( z196_cr1 | z196_cr2 | z196_cr3 )")
-
-;; Most simple instruction a fast enough to be handled by OOO even with
-;; latency == 0. This reduces life ranges and spilling. We want to increase
-;; life range for longer running ops, though, thats why we do not use
-;; -fno-schedule-insns.
-(define_insn_reservation "z196_simple_LSU" 0
- (and (eq_attr "cpu" "z196")
- (and (eq_attr "type" "load,store,lr")
- (eq_attr "z196prop" "none")))
- "z196_simple")
-
-(define_insn_reservation "z196_simple_FXU" 0
- (and (eq_attr "cpu" "z196")
- (and (eq_attr "type" "integer,la,larl,other")
- (and (eq_attr "z196prop" "none")
- (eq_attr "op_type" "RR"))))
- "z196_simple")
-
-(define_insn_reservation "z196_simple_DUAL" 0
- (and (eq_attr "cpu" "z196")
- (and (eq_attr "type" "integer,la,larl,other")
- (and (eq_attr "z196prop" "none")
- (eq_attr "op_type" "!RR"))))
- "z196_simple")
-
-(define_insn_reservation "z196_cracked" 0
- (and (eq_attr "cpu" "z196")
- (and (eq_attr "type" "integer,la,larl,load,lr,store,other")
- (eq_attr "z196prop" "z196_cracked")))
- "z196_crack")
-
-(define_insn_reservation "z196_alone" 0
- (and (eq_attr "cpu" "z196")
- (and (eq_attr "type" "integer,la,larl,load,lr,store,other")
- (eq_attr "z196prop" "z196_alone")))
- "z196_alone")
-
-(define_insn_reservation "z196_ends" 0
- (and (eq_attr "cpu" "z196")
- (and (eq_attr "type" "integer,la,larl,load,lr,store,other")
- (eq_attr "z196prop" "z196_ends")))
- "z196_ends")
-
-(define_insn_reservation "z196_branch" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "branch"))
- "z196_ends")
-
-(define_insn_reservation "z196_call" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "jsr"))
- "z196_ends")
-
-(define_insn_reservation "z196_mul_hi" 10
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "imulhi"))
- "z196_simple")
-
-(define_insn_reservation "z196_mul_si" 12
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "imulsi"))
- "z196_simple")
-
-(define_insn_reservation "z196_mul_di" 14
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "imuldi"))
- "z196_simple")
-
-(define_insn_reservation "z196_div" 73
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "idiv"))
- "z196_alone")
-
-(define_insn_reservation "z196_sem" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "sem"))
- "z196_crack")
-
-(define_insn_reservation "z196_cs" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "cs"))
- "z196_crack")
-
-(define_insn_reservation "z196_vs" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "vs"))
- "z196_alone")
-
-(define_insn_reservation "z196_lm_stm" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "stm,lm"))
- "z196_crack")
-
-
-;;
-;; Binary Floating Point
-;;
-
-(define_insn_reservation "z196_fsimptf" 18
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fsimptf,fhex"))
- "z196_alone")
-
-(define_insn_reservation "z196_fmultf" 47
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fmultf"))
- "z196_alone")
-
-(define_insn_reservation "z196_fsimpdf" 7
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fsimpdf,fmuldf,fhex"))
- "z196_simple")
-
-(define_insn_reservation "z196_fmadddf" 7
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fmadddf"))
- "z196_alone")
-
-(define_insn_reservation "z196_fsimpsf" 7
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fsimpsf,fmulsf,fhex"))
- "z196_simple")
-
-(define_insn_reservation "z196_fmaddsf" 7
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fmaddsf"))
- "z196_alone")
-
-(define_insn_reservation "z196_fdivtf" 108
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fdivtf,fsqrttf"))
- "z196_alone")
-
-(define_insn_reservation "z196_fdivdf" 36
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fdivdf,fsqrtdf"))
- "z196_simple")
-
-(define_insn_reservation "z196_fdivsf" 29
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fdivsf,fsqrtsf"))
- "z196_simple")
-
-
-;; Loads and stores are cheap as well.
-(define_insn_reservation "z196_floaddf" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "floaddf"))
- "z196_simple")
-
-(define_insn_reservation "z196_floadsf" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "floadsf"))
- "z196_simple")
-
-(define_insn_reservation "z196_fstoredf" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fstoredf"))
- "z196_simple")
-
-(define_insn_reservation "z196_fstoresf" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fstoresf"))
- "z196_simple")
-
-
-(define_insn_reservation "z196_ftrunctf" 9
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "ftrunctf"))
- "z196_simple")
-
-(define_insn_reservation "z196_ftruncdf" 7
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "ftruncdf"))
- "z196_simple")
-
-
-(define_insn_reservation "z196_ftoi" 7
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "ftoi"))
- "z196_crack")
-
-(define_insn_reservation "z196_itof" 7
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "itoftf,itofdf,itofsf"))
- "z196_crack")
-
-;;
-;; Decimal Floating Point
-;;
-
-;; DDTR
-(define_insn_reservation "z196_fdivdd" 33
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fdivdd"))
- "z196_simple")
-
-;; DXTR
-(define_insn_reservation "z196_fdivtd" 35
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fdivtd"))
- "z196_alone")
-
-;; LEDTR
-(define_insn_reservation "z196_ftruncsd" 34
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "ftruncsd"))
- "z196_simple")
-
-;; LDXTR
-(define_insn_reservation "z196_ftruncdd" 36
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "ftruncdd"))
- "z196_simple")
-
-;; These are normal fp loads/stores - which are cheap.
-(define_insn_reservation "z196_floadsddd" 0
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "floadsd,floaddd,fstoredd,fstoresd"))
- "z196_simple")
-
-;; MDTR
-(define_insn_reservation "z196_fmuldd" 23
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fmuldd"))
- "z196_simple")
-
-;; MXTR
-(define_insn_reservation "z196_fmultd" 25
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fmultd"))
- "z196_alone")
-
-;; multiple different isns like add, sub etc.
-;; Just use the same defaults as z10.
-(define_insn_reservation "z196_fsimpsd" 17
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fsimpsd"))
- "z196_simple")
-(define_insn_reservation "z196_fsimpdd" 17
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fsimpdd"))
- "z196_simple")
-(define_insn_reservation "z196_fsimptd" 18
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "fsimptd"))
- "z196_alone")
-
-;; CDGTR
-(define_insn_reservation "z196_itofdd" 45
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "itofdd"))
- "z196_crack")
-
-;; CXGTR
-(define_insn_reservation "z196_itoftd" 33
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "itoftd"))
- "z196_crack")
-
-;; CGXTR, CGDTR
-(define_insn_reservation "z196_ftoidfp" 33
- (and (eq_attr "cpu" "z196")
- (eq_attr "type" "ftoidfp"))
- "z196_crack")
-
-
-
diff --git a/gcc-4.7/gcc/config/s390/constraints.md b/gcc-4.7/gcc/config/s390/constraints.md
deleted file mode 100644
index 8564b6619..000000000
--- a/gcc-4.7/gcc/config/s390/constraints.md
+++ /dev/null
@@ -1,492 +0,0 @@
-;; Constraints definitions belonging to the gcc backend for IBM S/390.
-;; Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
-;; Written by Wolfgang Gellerich, using code and information found in
-;; files s390.md, s390.h, and s390.c.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 3, or (at your option) any later
-;; version.
-;;
-;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-
-;;
-;; Special constraints for s/390 machine description:
-;;
-;; a -- Any address register from 1 to 15.
-;; b -- Memory operand whose address is a symbol reference or a symbol
-;; reference + constant which can be proven to be naturally aligned.
-;; c -- Condition code register 33.
-;; d -- Any register from 0 to 15.
-;; f -- Floating point registers.
-;; t -- Access registers 36 and 37.
-;; C -- A signed 8-bit constant (-128..127)
-;; D -- An unsigned 16-bit constant (0..65535)
-;; G -- Const double zero operand
-;; I -- An 8-bit constant (0..255).
-;; J -- A 12-bit constant (0..4095).
-;; K -- A 16-bit constant (-32768..32767).
-;; L -- Value appropriate as displacement.
-;; (0..4095) for short displacement
-;; (-524288..524287) for long displacement
-;; M -- Constant integer with a value of 0x7fffffff.
-;; N -- Multiple letter constraint followed by 4 parameter letters.
-;; 0..9,x: number of the part counting from most to least significant
-;; H,Q: mode of the part
-;; D,S,H: mode of the containing operand
-;; 0,F: value of the other parts (F - all bits set)
-;;
-;; The constraint matches if the specified part of a constant
-;; has a value different from its other parts. If the letter x
-;; is specified instead of a part number, the constraint matches
-;; if there is any single part with non-default value.
-;; O -- Multiple letter constraint followed by 1 parameter.
-;; s: Signed extended immediate value (-2G .. 2G-1).
-;; p: Positive extended immediate value (0 .. 4G-1).
-;; n: Negative extended immediate value (-4G+1 .. -1).
-;; These constraints do not accept any operand if the machine does
-;; not provide the extended-immediate facility.
-;; P -- Any integer constant that can be loaded without literal pool.
-;; Q -- Memory reference without index register and with short displacement.
-;; R -- Memory reference with index register and short displacement.
-;; S -- Memory reference without index register but with long displacement.
-;; T -- Memory reference with index register and long displacement.
-;; A -- Multiple letter constraint followed by Q, R, S, or T:
-;; Offsettable memory reference of type specified by second letter.
-;; B -- Multiple letter constraint followed by Q, R, S, or T:
-;; Memory reference of the type specified by second letter that
-;; does *not* refer to a literal pool entry.
-;; U -- Pointer with short displacement. (deprecated - use ZQZR)
-;; W -- Pointer with long displacement. (deprecated - use ZSZT)
-;; Y -- Shift count operand.
-;; ZQ -- Pointer without index register and with short displacement.
-;; ZR -- Pointer with index register and short displacement.
-;; ZS -- Pointer without index register but with long displacement.
-;; ZT -- Pointer with index register and long displacement.
-;;
-;;
-
-
-;;
-;; Register constraints.
-;;
-
-(define_register_constraint "a"
- "ADDR_REGS"
- "Any address register from 1 to 15.")
-
-
-(define_register_constraint "c"
- "CC_REGS"
- "Condition code register 33")
-
-
-(define_register_constraint "d"
- "GENERAL_REGS"
- "Any register from 0 to 15")
-
-
-(define_register_constraint "f"
- "FP_REGS"
- "Floating point registers")
-
-
-(define_register_constraint "t"
- "ACCESS_REGS"
- "@internal
- Access registers 36 and 37")
-
-
-;;
-;; General constraints for constants.
-;;
-
-(define_constraint "C"
- "@internal
- An 8-bit signed immediate constant (-128..127)"
- (and (match_code "const_int")
- (match_test "ival >= -128 && ival <= 127")))
-
-
-(define_constraint "D"
- "An unsigned 16-bit constant (0..65535)"
- (and (match_code "const_int")
- (match_test "ival >= 0 && ival <= 65535")))
-
-
-(define_constraint "G"
- "@internal
- Const double zero operand"
- (and (match_code "const_double")
- (match_test "s390_float_const_zero_p (op)")))
-
-
-(define_constraint "I"
- "An 8-bit constant (0..255)"
- (and (match_code "const_int")
- (match_test "(unsigned HOST_WIDE_INT) ival <= 255")))
-
-
-(define_constraint "J"
- "A 12-bit constant (0..4095)"
- (and (match_code "const_int")
- (match_test "(unsigned HOST_WIDE_INT) ival <= 4095")))
-
-
-(define_constraint "K"
- "A 16-bit constant (-32768..32767)"
- (and (match_code "const_int")
- (match_test "ival >= -32768 && ival <= 32767")))
-
-
-(define_constraint "L"
- "Value appropriate as displacement.
- (0..4095) for short displacement
- (-524288..524287) for long displacement"
- (and (match_code "const_int")
- (match_test "TARGET_LONG_DISPLACEMENT ?
- (ival >= -524288 && ival <= 524287)
- : (ival >= 0 && ival <= 4095)")))
-
-
-(define_constraint "M"
- "Constant integer with a value of 0x7fffffff"
- (and (match_code "const_int")
- (match_test "ival == 2147483647")))
-
-
-(define_constraint "P"
- "@internal
- Any integer constant that can be loaded without literal pool"
- (and (match_code "const_int")
- (match_test "legitimate_reload_constant_p (GEN_INT (ival))")))
-
-
-(define_address_constraint "Y"
- "Shift count operand"
-
-;; Simply check for the basic form of a shift count. Reload will
-;; take care of making sure we have a proper base register.
-
- (match_test "s390_decompose_shift_count (op, NULL, NULL)" ))
-
-
-;; N -- Multiple letter constraint followed by 4 parameter letters.
-;; 0..9,x: number of the part counting from most to least significant
-;; H,Q: mode of the part
-;; D,S,H: mode of the containing operand
-;; 0,F: value of the other parts (F = all bits set)
-;;
-;; The constraint matches if the specified part of a constant
-;; has a value different from its other parts. If the letter x
-;; is specified instead of a part number, the constraint matches
-;; if there is any single part with non-default value.
-;;
-;; The following patterns define only those constraints that are actually
-;; used in s390.md. If you need an additional one, simply add it in the
-;; obvious way. Function s390_N_constraint_str is ready to handle all
-;; combinations.
-;;
-
-
-(define_constraint "NxQS0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"xQS0\", ival)")))
-
-
-(define_constraint "NxQD0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"xQD0\", ival)")))
-
-
-(define_constraint "N3HD0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"3HD0\", ival)")))
-
-
-(define_constraint "N2HD0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"2HD0\", ival)")))
-
-
-(define_constraint "N1SD0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"1SD0\", ival)")))
-
-
-(define_constraint "N1HS0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"1HS0\", ival)")))
-
-
-(define_constraint "N1HD0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"1HD0\", ival)")))
-
-
-(define_constraint "N0SD0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"0SD0\", ival)")))
-
-
-(define_constraint "N0HS0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"0HS0\", ival)")))
-
-
-(define_constraint "N0HD0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"0HD0\", ival)")))
-
-
-(define_constraint "NxQDF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"xQDF\", ival)")))
-
-
-(define_constraint "N1SDF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"1SDF\", ival)")))
-
-
-(define_constraint "N0SDF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"0SDF\", ival)")))
-
-
-(define_constraint "N3HDF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"3HDF\", ival)")))
-
-
-(define_constraint "N2HDF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"2HDF\", ival)")))
-
-
-(define_constraint "N1HDF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"1HDF\", ival)")))
-
-
-(define_constraint "N0HDF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"0HDF\", ival)")))
-
-
-(define_constraint "N0HSF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"0HSF\", ival)")))
-
-
-(define_constraint "N1HSF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"1HSF\", ival)")))
-
-
-(define_constraint "NxQSF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"xQSF\", ival)")))
-
-
-(define_constraint "NxQHF"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"xQHF\", ival)")))
-
-
-(define_constraint "NxQH0"
- "@internal"
- (and (match_code "const_int")
- (match_test "s390_N_constraint_str (\"xQH0\", ival)")))
-
-
-
-
-;;
-;; Double-letter constraints starting with O follow.
-;;
-
-
-(define_constraint "Os"
- "@internal
- Signed extended immediate value (-2G .. 2G-1).
- This constraint will only match if the machine provides
- the extended-immediate facility."
- (and (match_code "const_int")
- (match_test "s390_O_constraint_str ('s', ival)")))
-
-
-(define_constraint "Op"
- "@internal
- Positive extended immediate value (0 .. 4G-1).
- This constraint will only match if the machine provides
- the extended-immediate facility."
- (and (match_code "const_int")
- (match_test "s390_O_constraint_str ('p', ival)")))
-
-
-(define_constraint "On"
- "@internal
- Negative extended immediate value (-4G+1 .. -1).
- This constraint will only match if the machine provides
- the extended-immediate facility."
- (and (match_code "const_int")
- (match_test "s390_O_constraint_str ('n', ival)")))
-
-
-
-
-;;
-;; Memory constraints follow.
-;;
-
-(define_memory_constraint "Q"
- "Memory reference without index register and with short displacement"
- (match_test "s390_mem_constraint (\"Q\", op)"))
-
-
-(define_memory_constraint "R"
- "Memory reference with index register and short displacement"
- (match_test "s390_mem_constraint (\"R\", op)"))
-
-
-(define_memory_constraint "S"
- "Memory reference without index register but with long displacement"
- (match_test "s390_mem_constraint (\"S\", op)"))
-
-
-(define_memory_constraint "T"
- "Memory reference with index register and long displacement"
- (match_test "s390_mem_constraint (\"T\", op)"))
-
-
-(define_memory_constraint "b"
- "Memory reference whose address is a naturally aligned symbol reference."
- (match_test "MEM_P (op)
- && s390_check_symref_alignment (XEXP (op, 0),
- GET_MODE_SIZE (GET_MODE (op)))"))
-
-(define_memory_constraint "e"
- "Matches all memory references available on the current architecture
-level. This constraint will never be used and using it in an inline
-assembly is *always* a bug since there is no instruction accepting all
-those addresses. It just serves as a placeholder for a generic memory
-constraint."
- (match_test "strict_memory_address_p (GET_MODE (op), op)"))
-
-; This defines 'm' as normal memory constraint. This is only possible
-; since the standard memory constraint is re-defined in s390.h using
-; the TARGET_MEM_CONSTRAINT macro.
-(define_memory_constraint "m"
- "Matches the most general memory address for pre-z10 machines."
- (match_test "s390_mem_constraint (\"R\", op)
- || s390_mem_constraint (\"T\", op)"))
-
-(define_memory_constraint "AQ"
- "@internal
- Offsettable memory reference without index register and with short displacement"
- (match_test "s390_mem_constraint (\"AQ\", op)"))
-
-
-(define_memory_constraint "AR"
- "@internal
- Offsettable memory reference with index register and short displacement"
- (match_test "s390_mem_constraint (\"AR\", op)"))
-
-
-(define_memory_constraint "AS"
- "@internal
- Offsettable memory reference without index register but with long displacement"
- (match_test "s390_mem_constraint (\"AS\", op)"))
-
-
-(define_memory_constraint "AT"
- "@internal
- Offsettable memory reference with index register and long displacement"
- (match_test "s390_mem_constraint (\"AT\", op)"))
-
-
-
-(define_constraint "BQ"
- "@internal
- Memory reference without index register and with short
- displacement that does *not* refer to a literal pool entry."
- (match_test "s390_mem_constraint (\"BQ\", op)"))
-
-
-(define_constraint "BR"
- "@internal
- Memory reference with index register and short displacement that
- does *not* refer to a literal pool entry. "
- (match_test "s390_mem_constraint (\"BR\", op)"))
-
-
-(define_constraint "BS"
- "@internal
- Memory reference without index register but with long displacement
- that does *not* refer to a literal pool entry. "
- (match_test "s390_mem_constraint (\"BS\", op)"))
-
-
-(define_constraint "BT"
- "@internal
- Memory reference with index register and long displacement that
- does *not* refer to a literal pool entry. "
- (match_test "s390_mem_constraint (\"BT\", op)"))
-
-
-(define_address_constraint "U"
- "Pointer with short displacement. (deprecated - use ZQZR)"
- (match_test "s390_mem_constraint (\"U\", op)"))
-
-(define_address_constraint "W"
- "Pointer with long displacement. (deprecated - use ZSZT)"
- (match_test "s390_mem_constraint (\"W\", op)"))
-
-
-(define_address_constraint "ZQ"
- "Pointer without index register and with short displacement."
- (match_test "s390_mem_constraint (\"ZQ\", op)"))
-
-(define_address_constraint "ZR"
- "Pointer with index register and short displacement."
- (match_test "s390_mem_constraint (\"ZR\", op)"))
-
-(define_address_constraint "ZS"
- "Pointer without index register but with long displacement."
- (match_test "s390_mem_constraint (\"ZS\", op)"))
-
-(define_address_constraint "ZT"
- "Pointer with index register and long displacement."
- (match_test "s390_mem_constraint (\"ZT\", op)"))
diff --git a/gcc-4.7/gcc/config/s390/linux.h b/gcc-4.7/gcc/config/s390/linux.h
deleted file mode 100644
index e5385eca3..000000000
--- a/gcc-4.7/gcc/config/s390/linux.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* Definitions for Linux for S/390.
- Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2010, 2011
- Free Software Foundation, Inc.
- Contributed by Hartmut Penner (hpenner@de.ibm.com) and
- Ulrich Weigand (uweigand@de.ibm.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef _LINUX_H
-#define _LINUX_H
-
-/* Target specific type definitions. */
-
-/* ??? Do we really want long as size_t on 31-bit? */
-#undef SIZE_TYPE
-#define SIZE_TYPE (TARGET_64BIT ? "long unsigned int" : "long unsigned int")
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-
-/* Target specific preprocessor settings. */
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- GNU_USER_TARGET_OS_CPP_BUILTINS(); \
- } \
- while (0)
-
-
-/* Target specific assembler settings. */
-
-#undef ASM_SPEC
-#define ASM_SPEC "%{m31&m64}%{mesa&mzarch}%{march=*}"
-
-
-/* Target specific linker settings. */
-
-#ifdef DEFAULT_TARGET_64BIT
-#define MULTILIB_DEFAULTS { "m64" }
-#else
-#define MULTILIB_DEFAULTS { "m31" }
-#endif
-
-#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
-#define GLIBC_DYNAMIC_LINKER64 "/lib/ld64.so.1"
-
-#undef LINK_SPEC
-#define LINK_SPEC \
- "%{m31:-m elf_s390}%{m64:-m elf64_s390} \
- %{shared:-shared} \
- %{!shared: \
- %{static:-static} \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{m31:-dynamic-linker " GNU_USER_DYNAMIC_LINKER32 "} \
- %{m64:-dynamic-linker " GNU_USER_DYNAMIC_LINKER64 "}}}"
-
-#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
-
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-
-#ifdef TARGET_LIBC_PROVIDES_SSP
-/* s390 glibc provides __stack_chk_guard in 0x14(tp),
- s390x glibc provides it at 0x28(tp). */
-#define TARGET_THREAD_SSP_OFFSET (TARGET_64BIT ? 0x28 : 0x14)
-#endif
-
-/* Define if long doubles should be mangled as 'g'. */
-#define TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-
-#endif
diff --git a/gcc-4.7/gcc/config/s390/predicates.md b/gcc-4.7/gcc/config/s390/predicates.md
deleted file mode 100644
index 9d619fbc0..000000000
--- a/gcc-4.7/gcc/config/s390/predicates.md
+++ /dev/null
@@ -1,406 +0,0 @@
-;; Predicate definitions for S/390 and zSeries.
-;; Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
-;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-;; Ulrich Weigand (uweigand@de.ibm.com).
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;; OP is the current operation.
-;; MODE is the current operation mode.
-
-;; operands --------------------------------------------------------------
-
-;; Return true if OP a (const_int 0) operand.
-
-(define_predicate "const0_operand"
- (and (match_code "const_int, const_double")
- (match_test "op == CONST0_RTX (mode)")))
-
-;; Return true if OP is constant.
-
-(define_special_predicate "consttable_operand"
- (and (match_code "symbol_ref, label_ref, const, const_int, const_double")
- (match_test "CONSTANT_P (op)")))
-
-;; Return true if OP is a valid S-type operand.
-
-(define_predicate "s_operand"
- (and (match_code "subreg, mem")
- (match_operand 0 "general_operand"))
-{
- /* 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);
-
- if (GET_CODE (op) != MEM)
- return false;
- if (!s390_legitimate_address_without_index_p (op))
- return false;
-
- return true;
-})
-
-;; Return true if OP is a valid operand for the BRAS instruction.
-;; Allow SYMBOL_REFs and @PLT stubs.
-
-(define_special_predicate "bras_sym_operand"
- (ior (and (match_code "symbol_ref")
- (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)"))
- (and (match_code "const")
- (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
- (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT")))))
-
-;; Return true if OP is a PLUS that is not a legitimate
-;; operand for the LA instruction.
-
-(define_predicate "s390_plus_operand"
- (and (match_code "plus")
- (and (match_test "mode == Pmode")
- (match_test "!legitimate_la_operand_p (op)"))))
-
-;; Return true if OP is a valid operand as shift count or setmem.
-
-(define_predicate "shift_count_or_setmem_operand"
- (match_code "reg, subreg, plus, const_int")
-{
- HOST_WIDE_INT offset;
- rtx base;
-
- /* Extract base register and offset. */
- if (!s390_decompose_shift_count (op, &base, &offset))
- return false;
-
- /* Don't allow any non-base hard registers. Doing so without
- confusing reload and/or regrename would be tricky, and doesn't
- buy us much anyway. */
- if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base))
- return false;
-
- /* Unfortunately we have to reject constants that are invalid
- for an address, or else reload will get confused. */
- if (!DISP_IN_RANGE (offset))
- return false;
-
- return true;
-})
-
-;; Return true if OP a valid operand for the LARL instruction.
-
-(define_predicate "larl_operand"
- (match_code "label_ref, symbol_ref, const, const_int, const_double")
-{
- /* Allow labels and local symbols. */
- if (GET_CODE (op) == LABEL_REF)
- return true;
- if (GET_CODE (op) == SYMBOL_REF)
- return (!SYMBOL_REF_ALIGN1_P (op)
- && SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
-
- /* Everything else must have a CONST, so strip it. */
- if (GET_CODE (op) != CONST)
- return false;
- op = XEXP (op, 0);
-
- /* Allow adding *even* in-range constants. */
- if (GET_CODE (op) == PLUS)
- {
- if (GET_CODE (XEXP (op, 1)) != CONST_INT
- || (INTVAL (XEXP (op, 1)) & 1) != 0)
- return false;
- if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
- || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
- return false;
- op = XEXP (op, 0);
- }
-
- /* Labels and local symbols allowed here as well. */
- if (GET_CODE (op) == LABEL_REF)
- return true;
- if (GET_CODE (op) == SYMBOL_REF)
- return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
- && SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
-
- /* Now we must have a @GOTENT offset or @PLT stub
- or an @INDNTPOFF TLS offset. */
- if (GET_CODE (op) == UNSPEC
- && XINT (op, 1) == UNSPEC_GOTENT)
- return true;
- if (GET_CODE (op) == UNSPEC
- && XINT (op, 1) == UNSPEC_PLT)
- return true;
- if (GET_CODE (op) == UNSPEC
- && XINT (op, 1) == UNSPEC_INDNTPOFF)
- return true;
-
- return false;
-})
-
-;; operators --------------------------------------------------------------
-
-;; Return nonzero if OP is a valid comparison operator
-;; for a branch condition.
-
-(define_predicate "s390_comparison"
- (match_code "eq, ne, lt, gt, le, ge, ltu, gtu, leu, geu,
- uneq, unlt, ungt, unle, unge, ltgt,
- unordered, ordered")
-{
- if (GET_CODE (XEXP (op, 0)) != REG
- || REGNO (XEXP (op, 0)) != CC_REGNUM
- || XEXP (op, 1) != const0_rtx)
- return false;
-
- return (s390_branch_condition_mask (op) >= 0);
-})
-
-;; Return true if op is the cc register.
-(define_predicate "cc_reg_operand"
- (and (match_code "reg")
- (match_test "REGNO (op) == CC_REGNUM")))
-
-(define_predicate "s390_signed_integer_comparison"
- (match_code "eq, ne, lt, gt, le, ge")
-{
- return (s390_compare_and_branch_condition_mask (op) >= 0);
-})
-
-(define_predicate "s390_unsigned_integer_comparison"
- (match_code "eq, ne, ltu, gtu, leu, geu")
-{
- return (s390_compare_and_branch_condition_mask (op) >= 0);
-})
-
-;; Return nonzero if OP is a valid comparison operator for the
-;; cstore expanders -- respectively cstorecc4 and integer cstore.
-(define_predicate "s390_eqne_operator"
- (match_code "eq, ne"))
-
-(define_predicate "s390_scond_operator"
- (match_code "ltu, gtu, leu, geu"))
-
-(define_predicate "s390_brx_operator"
- (match_code "le, gt"))
-
-;; Return nonzero if OP is a valid comparison operator
-;; for an ALC condition.
-
-(define_predicate "s390_alc_comparison"
- (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
-{
- while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
- op = XEXP (op, 0);
-
- if (!COMPARISON_P (op))
- return false;
-
- if (GET_CODE (XEXP (op, 0)) != REG
- || REGNO (XEXP (op, 0)) != CC_REGNUM
- || XEXP (op, 1) != const0_rtx)
- return false;
-
- switch (GET_MODE (XEXP (op, 0)))
- {
- case CCL1mode:
- return GET_CODE (op) == LTU;
-
- case CCL2mode:
- return GET_CODE (op) == LEU;
-
- case CCL3mode:
- return GET_CODE (op) == GEU;
-
- case CCUmode:
- return GET_CODE (op) == GTU;
-
- case CCURmode:
- return GET_CODE (op) == LTU;
-
- case CCSmode:
- return GET_CODE (op) == UNGT;
-
- case CCSRmode:
- return GET_CODE (op) == UNLT;
-
- default:
- return false;
- }
-})
-
-;; Return nonzero if OP is a valid comparison operator
-;; for an SLB condition.
-
-(define_predicate "s390_slb_comparison"
- (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
-{
- while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
- op = XEXP (op, 0);
-
- if (!COMPARISON_P (op))
- return false;
-
- if (GET_CODE (XEXP (op, 0)) != REG
- || REGNO (XEXP (op, 0)) != CC_REGNUM
- || XEXP (op, 1) != const0_rtx)
- return false;
-
- switch (GET_MODE (XEXP (op, 0)))
- {
- case CCL1mode:
- return GET_CODE (op) == GEU;
-
- case CCL2mode:
- return GET_CODE (op) == GTU;
-
- case CCL3mode:
- return GET_CODE (op) == LTU;
-
- case CCUmode:
- return GET_CODE (op) == LEU;
-
- case CCURmode:
- return GET_CODE (op) == GEU;
-
- case CCSmode:
- return GET_CODE (op) == LE;
-
- case CCSRmode:
- return GET_CODE (op) == GE;
-
- default:
- return false;
- }
-})
-
-;; Return true if OP is a load multiple operation. It is known to be a
-;; PARALLEL and the first section will be tested.
-
-(define_special_predicate "load_multiple_operation"
- (match_code "parallel")
-{
- enum machine_mode elt_mode;
- int count = XVECLEN (op, 0);
- unsigned int dest_regno;
- rtx src_addr;
- int i, off;
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != REG
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != MEM)
- return false;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
- src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
- elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 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 false;
-
- for (i = 1; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != elt_mode
- || REGNO (SET_DEST (elt)) != dest_regno + i
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != elt_mode
- || 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))
- != off + i * GET_MODE_SIZE (elt_mode))
- return false;
- }
-
- return true;
-})
-
-;; Return true if OP is a store multiple operation. It is known to be a
-;; PARALLEL and the first section will be tested.
-
-(define_special_predicate "store_multiple_operation"
- (match_code "parallel")
-{
- enum machine_mode elt_mode;
- int count = XVECLEN (op, 0);
- unsigned int src_regno;
- rtx dest_addr;
- int i, off;
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, 0))) != MEM
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != REG)
- return false;
-
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
- dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
- elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 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 false;
-
- for (i = 1; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != elt_mode
- || REGNO (SET_SRC (elt)) != src_regno + i
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != elt_mode
- || 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))
- != off + i * GET_MODE_SIZE (elt_mode))
- return false;
- }
- return true;
-})
diff --git a/gcc-4.7/gcc/config/s390/s390-modes.def b/gcc-4.7/gcc/config/s390/s390-modes.def
deleted file mode 100644
index be2bf6ea7..000000000
--- a/gcc-4.7/gcc/config/s390/s390-modes.def
+++ /dev/null
@@ -1,174 +0,0 @@
-/* Definitions of target machine for GNU compiler, for IBM S/390
- Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
- Contributed by Hartmut Penner (hpenner@de.ibm.com) and
- Ulrich Weigand (uweigand@de.ibm.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
-INT_MODE (OI, 32);
-
-/* Define TFmode to work around reload problem PR 20927. */
-FLOAT_MODE (TF, 16, ieee_quad_format);
-
-/* Add any extra modes needed to represent the condition code. */
-
-/*
-
-Condition Codes
-
-Check for zero
-
-CCZ: EQ NE NE NE
-CCZ1: EQ NE (CS)
-
-Unsigned compares
-
-CCU: EQ LTU GTU NE (CLG/R, CL/R/Y, CLM/Y, CLI/Y)
-CCUR: EQ GTU LTU NE (CLGF/R)
-
-Signed compares
-
-CCS: EQ LT GT UNORDERED (LTGFR, LTGR, LTR, ICM/Y,
- LTDBR, LTDR, LTEBR, LTER,
- CG/R, C/R/Y, CGHI, CHI,
- CDB/R, CD/R, CEB/R, CE/R,
- ADB/R, AEB/R, SDB/R, SEB/R,
- SRAG, SRA, SRDA)
-CCSR: EQ GT LT UNORDERED (CGF/R, CH/Y)
-
-Condition codes resulting from add with overflow
-
-CCA: EQ LT GT Overflow
-CCAP: EQ LT GT LT (AGHI, AHI)
-CCAN: EQ LT GT GT (AGHI, AHI)
-
-Condition codes of unsigned adds and subs
-
-CCL: EQ NE EQ NE (ALGF/R, ALG/R, AL/R/Y,
- ALCG/R, ALC/R,
- SLGF/R, SLG/R, SL/R/Y,
- SLBG/R, SLB/R)
-CCL1: GEU GEU LTU LTU (ALG/R, AL/R/Y)
-CCL2: GTU GTU LEU LEU (SLG/R, SL/R/Y)
-CCL3: EQ LTU EQ GTU (SLG/R, SL/R/Y)
-
-Test under mask checks
-
-CCT: EQ NE NE NE (ICM/Y, TML, CG/R, CGHI,
- C/R/Y, CHI, NG/R, N/R/Y,
- OG/R, O/R/Y, XG/R, X/R/Y)
-CCT1: NE EQ NE NE (TMH, TML)
-CCT2: NE NE EQ NE (TMH, TML)
-CCT3: NE NE NE EQ (TMH, TML)
-
-CCA and CCT modes are request only modes. These modes are never returned by
-s390_select_cc_mode. They are only intended to match other modes.
-
-Requested mode -> Destination CC register mode
-
-CCS, CCU, CCT, CCSR, CCUR -> CCZ
-CCA -> CCAP, CCAN
-
-
-*** Comments ***
-
-CCAP, CCAN
-
-The CC obtained from add instruction usually can't be used for comparisons
-because its coupling with overflow flag. In case of an overflow the
-less than/greater than data are lost. Nevertheless a comparison can be done
-whenever immediate values are involved because they are known at compile time.
-If you know whether the used constant is positive or negative you can predict
-the sign of the result even in case of an overflow.
-
-
-CCT, CCT1, CCT2, CCT3
-
-If bits of an integer masked with an AND instruction are checked, the test under
-mask instructions turn out to be very handy for a set of special cases.
-The simple cases are checks whether all masked bits are zero or ones:
-
- int a;
- if ((a & (16 + 128)) == 0) -> CCT/CCZ
- if ((a & (16 + 128)) == 16 + 128) -> CCT3
-
-Using two extra modes makes it possible to do complete checks on two bits of an
-integer (This is possible on register operands only. TM does not provide the
-information necessary for CCT1 and CCT2 modes.):
-
- int a;
- if ((a & (16 + 128)) == 16) -> CCT1
- if ((a & (16 + 128)) == 128) -> CCT2
-
-
-CCSR, CCUR
-
-There are several instructions comparing 32 bit with 64-bit unsigned/signed
-values. Such instructions can be considered to have a builtin zero/sign_extend.
-The problem is that in the RTL (to be canonical) the zero/sign extended operand
-has to be the first one but the machine instructions like it the other way
-around. The following both modes can be considered as CCS and CCU modes with
-exchanged operands.
-
-
-CCL1, CCL2
-
-These modes represent the result of overflow checks.
-
-if (a + b < a) -> CCL1 state of the carry bit (CC2 | CC3)
-if (a - b > a) -> CCL2 state of the borrow bit (CC0 | CC1)
-
-They are used when multi word numbers are computed dealing one SImode part after
-another or whenever manual overflow checks like the examples above are
-compiled.
-
-
-CCL3
-
-A logical subtract instruction sets the borrow bit in case of an overflow.
-The resulting condition code of those instructions is represented by the
-CCL3 mode. Together with the CCU mode this mode is used for jumpless
-implementations of several if-constructs - see s390_expand_addcc for more
-details.
-
-CCZ1
-
-The compare and swap instructions sets the condition code to 0/1 if the
-operands were equal/unequal. The CCZ1 mode ensures the result can be
-effectively placed into a register.
-
-*/
-
-
-CC_MODE (CCZ);
-CC_MODE (CCZ1);
-CC_MODE (CCA);
-CC_MODE (CCAP);
-CC_MODE (CCAN);
-CC_MODE (CCL);
-CC_MODE (CCL1);
-CC_MODE (CCL2);
-CC_MODE (CCL3);
-CC_MODE (CCU);
-CC_MODE (CCUR);
-CC_MODE (CCS);
-CC_MODE (CCSR);
-CC_MODE (CCT);
-CC_MODE (CCT1);
-CC_MODE (CCT2);
-CC_MODE (CCT3);
diff --git a/gcc-4.7/gcc/config/s390/s390-opts.h b/gcc-4.7/gcc/config/s390/s390-opts.h
deleted file mode 100644
index 668aaaa84..000000000
--- a/gcc-4.7/gcc/config/s390/s390-opts.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Definitions for option handling for IBM S/390.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef S390_OPTS_H
-#define S390_OPTS_H
-
-/* Which processor to generate code or schedule for. The cpu attribute
- defines a list that mirrors this list, so changes to s390.md must be
- made at the same time. */
-
-enum processor_type
-{
- PROCESSOR_9672_G5,
- PROCESSOR_9672_G6,
- PROCESSOR_2064_Z900,
- PROCESSOR_2084_Z990,
- PROCESSOR_2094_Z9_109,
- PROCESSOR_2094_Z9_EC,
- PROCESSOR_2097_Z10,
- PROCESSOR_2817_Z196,
- PROCESSOR_max
-};
-
-#endif
diff --git a/gcc-4.7/gcc/config/s390/s390-protos.h b/gcc-4.7/gcc/config/s390/s390-protos.h
deleted file mode 100644
index 01a3584fe..000000000
--- a/gcc-4.7/gcc/config/s390/s390-protos.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Definitions of target machine for GNU compiler, for IBM S/390.
- Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
-
- Contributed by Hartmut Penner (hpenner@de.ibm.com)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-
-/* Prototypes of functions used for constraint evaluation in
- constraints.c. */
-
-extern int s390_mem_constraint (const char *str, rtx op);
-extern int s390_O_constraint_str (const char c, HOST_WIDE_INT value);
-extern int s390_N_constraint_str (const char *str, HOST_WIDE_INT value);
-extern int s390_float_const_zero_p (rtx value);
-extern bool s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment);
-
-
-/* Declare functions in s390.c. */
-
-extern HOST_WIDE_INT s390_initial_elimination_offset (int, int);
-extern void s390_emit_prologue (void);
-extern void s390_emit_epilogue (bool);
-extern void s390_function_profiler (FILE *, int);
-extern void s390_set_has_landing_pad_p (bool);
-extern bool s390_hard_regno_mode_ok (unsigned int, enum machine_mode);
-extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
-extern int s390_class_max_nregs (enum reg_class, enum machine_mode);
-
-#ifdef RTX_CODE
-extern int s390_extra_constraint_str (rtx, int, const char *);
-extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
-extern int s390_const_double_ok_for_constraint_p (rtx, int, const char *);
-extern int s390_single_part (rtx, enum machine_mode, enum machine_mode, int);
-extern unsigned HOST_WIDE_INT s390_extract_part (rtx, enum machine_mode, int);
-extern bool s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT, int, int *, int *);
-extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int);
-extern bool s390_overlap_p (rtx, rtx, HOST_WIDE_INT);
-extern bool s390_offset_p (rtx, rtx, rtx);
-extern int tls_symbolic_operand (rtx);
-
-extern bool s390_match_ccmode (rtx, enum machine_mode);
-extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
-extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
-extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
-extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
-extern void s390_emit_jump (rtx, rtx);
-extern bool symbolic_reference_mentioned_p (rtx);
-extern bool tls_symbolic_reference_mentioned_p (rtx);
-extern bool legitimate_la_operand_p (rtx);
-extern bool preferred_la_operand_p (rtx, rtx);
-extern int legitimate_pic_operand_p (rtx);
-extern bool legitimate_reload_constant_p (rtx);
-extern rtx legitimize_pic_address (rtx, rtx);
-extern rtx legitimize_reload_address (rtx, enum machine_mode, int, int);
-extern enum reg_class s390_secondary_input_reload_class (enum reg_class,
- enum machine_mode,
- rtx);
-extern enum reg_class s390_secondary_output_reload_class (enum reg_class,
- enum machine_mode,
- rtx);
-extern void s390_reload_larl_operand (rtx , rtx , rtx);
-extern void s390_reload_symref_address (rtx , rtx , rtx , bool);
-extern void s390_expand_plus_operand (rtx, rtx, rtx);
-extern void emit_symbolic_move (rtx *);
-extern void s390_load_address (rtx, rtx);
-extern void s390_expand_movmem (rtx, rtx, rtx);
-extern void s390_expand_setmem (rtx, rtx, rtx);
-extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
-extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
-extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
-extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx, rtx);
-extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
- rtx, rtx, rtx, bool);
-extern rtx s390_return_addr_rtx (int, rtx);
-extern rtx s390_back_chain_rtx (void);
-extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
-extern void s390_expand_logical_operator (enum rtx_code,
- enum machine_mode, rtx *);
-extern bool s390_logical_operator_ok_p (rtx *);
-extern void s390_narrow_logical_operator (enum rtx_code, rtx *, rtx *);
-extern void s390_split_access_reg (rtx, rtx *, rtx *);
-
-extern void print_operand_address (FILE *, rtx);
-extern void print_operand (FILE *, rtx, int);
-extern void s390_output_pool_entry (rtx, enum machine_mode, unsigned int);
-extern int s390_label_align (rtx);
-extern int s390_agen_dep_p (rtx, rtx);
-extern rtx s390_load_got (void);
-extern rtx s390_get_thread_pointer (void);
-extern void s390_emit_tpf_eh_return (rtx);
-extern bool s390_legitimate_address_without_index_p (rtx);
-extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
-extern int s390_branch_condition_mask (rtx);
-extern int s390_compare_and_branch_condition_mask (rtx);
-
-#endif /* RTX_CODE */
diff --git a/gcc-4.7/gcc/config/s390/s390.c b/gcc-4.7/gcc/config/s390/s390.c
deleted file mode 100644
index d6e250fd5..000000000
--- a/gcc-4.7/gcc/config/s390/s390.c
+++ /dev/null
@@ -1,10793 +0,0 @@
-/* Subroutines used for code generation on IBM S/390 and zSeries
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
- Contributed by Hartmut Penner (hpenner@de.ibm.com) and
- Ulrich Weigand (uweigand@de.ibm.com) and
- Andreas Krebbel (Andreas.Krebbel@de.ibm.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "rtl.h"
-#include "tree.h"
-#include "tm_p.h"
-#include "regs.h"
-#include "hard-reg-set.h"
-#include "insn-config.h"
-#include "conditions.h"
-#include "output.h"
-#include "insn-attr.h"
-#include "flags.h"
-#include "except.h"
-#include "function.h"
-#include "recog.h"
-#include "expr.h"
-#include "reload.h"
-#include "diagnostic-core.h"
-#include "basic-block.h"
-#include "integrate.h"
-#include "ggc.h"
-#include "target.h"
-#include "target-def.h"
-#include "debug.h"
-#include "langhooks.h"
-#include "optabs.h"
-#include "gimple.h"
-#include "df.h"
-#include "params.h"
-#include "cfgloop.h"
-#include "opts.h"
-
-/* Define the specific costs for a given cpu. */
-
-struct processor_costs
-{
- /* multiplication */
- const int m; /* cost of an M instruction. */
- const int mghi; /* cost of an MGHI instruction. */
- const int mh; /* cost of an MH instruction. */
- const int mhi; /* cost of an MHI instruction. */
- const int ml; /* cost of an ML instruction. */
- const int mr; /* cost of an MR instruction. */
- const int ms; /* cost of an MS instruction. */
- const int msg; /* cost of an MSG instruction. */
- const int msgf; /* cost of an MSGF instruction. */
- const int msgfr; /* cost of an MSGFR instruction. */
- const int msgr; /* cost of an MSGR instruction. */
- const int msr; /* cost of an MSR instruction. */
- const int mult_df; /* cost of multiplication in DFmode. */
- const int mxbr;
- /* square root */
- const int sqxbr; /* cost of square root in TFmode. */
- const int sqdbr; /* cost of square root in DFmode. */
- const int sqebr; /* cost of square root in SFmode. */
- /* multiply and add */
- const int madbr; /* cost of multiply and add in DFmode. */
- const int maebr; /* cost of multiply and add in SFmode. */
- /* division */
- const int dxbr;
- const int ddbr;
- const int debr;
- const int dlgr;
- const int dlr;
- const int dr;
- const int dsgfr;
- const int dsgr;
-};
-
-const struct processor_costs *s390_cost;
-
-static const
-struct processor_costs z900_cost =
-{
- COSTS_N_INSNS (5), /* M */
- COSTS_N_INSNS (10), /* MGHI */
- COSTS_N_INSNS (5), /* MH */
- COSTS_N_INSNS (4), /* MHI */
- COSTS_N_INSNS (5), /* ML */
- COSTS_N_INSNS (5), /* MR */
- COSTS_N_INSNS (4), /* MS */
- COSTS_N_INSNS (15), /* MSG */
- COSTS_N_INSNS (7), /* MSGF */
- COSTS_N_INSNS (7), /* MSGFR */
- COSTS_N_INSNS (10), /* MSGR */
- COSTS_N_INSNS (4), /* MSR */
- COSTS_N_INSNS (7), /* multiplication in DFmode */
- COSTS_N_INSNS (13), /* MXBR */
- COSTS_N_INSNS (136), /* SQXBR */
- COSTS_N_INSNS (44), /* SQDBR */
- COSTS_N_INSNS (35), /* SQEBR */
- COSTS_N_INSNS (18), /* MADBR */
- COSTS_N_INSNS (13), /* MAEBR */
- COSTS_N_INSNS (134), /* DXBR */
- COSTS_N_INSNS (30), /* DDBR */
- COSTS_N_INSNS (27), /* DEBR */
- COSTS_N_INSNS (220), /* DLGR */
- COSTS_N_INSNS (34), /* DLR */
- COSTS_N_INSNS (34), /* DR */
- COSTS_N_INSNS (32), /* DSGFR */
- COSTS_N_INSNS (32), /* DSGR */
-};
-
-static const
-struct processor_costs z990_cost =
-{
- COSTS_N_INSNS (4), /* M */
- COSTS_N_INSNS (2), /* MGHI */
- COSTS_N_INSNS (2), /* MH */
- COSTS_N_INSNS (2), /* MHI */
- COSTS_N_INSNS (4), /* ML */
- COSTS_N_INSNS (4), /* MR */
- COSTS_N_INSNS (5), /* MS */
- COSTS_N_INSNS (6), /* MSG */
- COSTS_N_INSNS (4), /* MSGF */
- COSTS_N_INSNS (4), /* MSGFR */
- COSTS_N_INSNS (4), /* MSGR */
- COSTS_N_INSNS (4), /* MSR */
- COSTS_N_INSNS (1), /* multiplication in DFmode */
- COSTS_N_INSNS (28), /* MXBR */
- COSTS_N_INSNS (130), /* SQXBR */
- COSTS_N_INSNS (66), /* SQDBR */
- COSTS_N_INSNS (38), /* SQEBR */
- COSTS_N_INSNS (1), /* MADBR */
- COSTS_N_INSNS (1), /* MAEBR */
- COSTS_N_INSNS (60), /* DXBR */
- COSTS_N_INSNS (40), /* DDBR */
- COSTS_N_INSNS (26), /* DEBR */
- COSTS_N_INSNS (176), /* DLGR */
- COSTS_N_INSNS (31), /* DLR */
- COSTS_N_INSNS (31), /* DR */
- COSTS_N_INSNS (31), /* DSGFR */
- COSTS_N_INSNS (31), /* DSGR */
-};
-
-static const
-struct processor_costs z9_109_cost =
-{
- COSTS_N_INSNS (4), /* M */
- COSTS_N_INSNS (2), /* MGHI */
- COSTS_N_INSNS (2), /* MH */
- COSTS_N_INSNS (2), /* MHI */
- COSTS_N_INSNS (4), /* ML */
- COSTS_N_INSNS (4), /* MR */
- COSTS_N_INSNS (5), /* MS */
- COSTS_N_INSNS (6), /* MSG */
- COSTS_N_INSNS (4), /* MSGF */
- COSTS_N_INSNS (4), /* MSGFR */
- COSTS_N_INSNS (4), /* MSGR */
- COSTS_N_INSNS (4), /* MSR */
- COSTS_N_INSNS (1), /* multiplication in DFmode */
- COSTS_N_INSNS (28), /* MXBR */
- COSTS_N_INSNS (130), /* SQXBR */
- COSTS_N_INSNS (66), /* SQDBR */
- COSTS_N_INSNS (38), /* SQEBR */
- COSTS_N_INSNS (1), /* MADBR */
- COSTS_N_INSNS (1), /* MAEBR */
- COSTS_N_INSNS (60), /* DXBR */
- COSTS_N_INSNS (40), /* DDBR */
- COSTS_N_INSNS (26), /* DEBR */
- COSTS_N_INSNS (30), /* DLGR */
- COSTS_N_INSNS (23), /* DLR */
- COSTS_N_INSNS (23), /* DR */
- COSTS_N_INSNS (24), /* DSGFR */
- COSTS_N_INSNS (24), /* DSGR */
-};
-
-static const
-struct processor_costs z10_cost =
-{
- COSTS_N_INSNS (10), /* M */
- COSTS_N_INSNS (10), /* MGHI */
- COSTS_N_INSNS (10), /* MH */
- COSTS_N_INSNS (10), /* MHI */
- COSTS_N_INSNS (10), /* ML */
- COSTS_N_INSNS (10), /* MR */
- COSTS_N_INSNS (10), /* MS */
- COSTS_N_INSNS (10), /* MSG */
- COSTS_N_INSNS (10), /* MSGF */
- COSTS_N_INSNS (10), /* MSGFR */
- COSTS_N_INSNS (10), /* MSGR */
- COSTS_N_INSNS (10), /* MSR */
- COSTS_N_INSNS (1) , /* multiplication in DFmode */
- COSTS_N_INSNS (50), /* MXBR */
- COSTS_N_INSNS (120), /* SQXBR */
- COSTS_N_INSNS (52), /* SQDBR */
- COSTS_N_INSNS (38), /* SQEBR */
- COSTS_N_INSNS (1), /* MADBR */
- COSTS_N_INSNS (1), /* MAEBR */
- COSTS_N_INSNS (111), /* DXBR */
- COSTS_N_INSNS (39), /* DDBR */
- COSTS_N_INSNS (32), /* DEBR */
- COSTS_N_INSNS (160), /* DLGR */
- COSTS_N_INSNS (71), /* DLR */
- COSTS_N_INSNS (71), /* DR */
- COSTS_N_INSNS (71), /* DSGFR */
- COSTS_N_INSNS (71), /* DSGR */
-};
-
-static const
-struct processor_costs z196_cost =
-{
- COSTS_N_INSNS (7), /* M */
- COSTS_N_INSNS (5), /* MGHI */
- COSTS_N_INSNS (5), /* MH */
- COSTS_N_INSNS (5), /* MHI */
- COSTS_N_INSNS (7), /* ML */
- COSTS_N_INSNS (7), /* MR */
- COSTS_N_INSNS (6), /* MS */
- COSTS_N_INSNS (8), /* MSG */
- COSTS_N_INSNS (6), /* MSGF */
- COSTS_N_INSNS (6), /* MSGFR */
- COSTS_N_INSNS (8), /* MSGR */
- COSTS_N_INSNS (6), /* MSR */
- COSTS_N_INSNS (1) , /* multiplication in DFmode */
- COSTS_N_INSNS (40), /* MXBR B+40 */
- COSTS_N_INSNS (100), /* SQXBR B+100 */
- COSTS_N_INSNS (42), /* SQDBR B+42 */
- COSTS_N_INSNS (28), /* SQEBR B+28 */
- COSTS_N_INSNS (1), /* MADBR B */
- COSTS_N_INSNS (1), /* MAEBR B */
- COSTS_N_INSNS (101), /* DXBR B+101 */
- COSTS_N_INSNS (29), /* DDBR */
- COSTS_N_INSNS (22), /* DEBR */
- COSTS_N_INSNS (160), /* DLGR cracked */
- COSTS_N_INSNS (160), /* DLR cracked */
- COSTS_N_INSNS (160), /* DR expanded */
- COSTS_N_INSNS (160), /* DSGFR cracked */
- COSTS_N_INSNS (160), /* DSGR cracked */
-};
-
-extern int reload_completed;
-
-/* Kept up to date using the SCHED_VARIABLE_ISSUE hook. */
-static rtx last_scheduled_insn;
-
-/* Structure used to hold the components of a S/390 memory
- address. A legitimate address on S/390 is of the general
- form
- base + index + displacement
- where any of the components is optional.
-
- base and index are registers of the class ADDR_REGS,
- displacement is an unsigned 12-bit immediate constant. */
-
-struct s390_address
-{
- rtx base;
- rtx indx;
- rtx disp;
- bool pointer;
- bool literal_pool;
-};
-
-/* The following structure is embedded in the machine
- specific part of struct function. */
-
-struct GTY (()) s390_frame_layout
-{
- /* Offset within stack frame. */
- HOST_WIDE_INT gprs_offset;
- HOST_WIDE_INT f0_offset;
- HOST_WIDE_INT f4_offset;
- HOST_WIDE_INT f8_offset;
- HOST_WIDE_INT backchain_offset;
-
- /* Number of first and last gpr where slots in the register
- save area are reserved for. */
- int first_save_gpr_slot;
- int last_save_gpr_slot;
-
- /* Number of first and last gpr to be saved, restored. */
- int first_save_gpr;
- int first_restore_gpr;
- int last_save_gpr;
- int last_restore_gpr;
-
- /* Bits standing for floating point registers. Set, if the
- respective register has to be saved. Starting with reg 16 (f0)
- at the rightmost bit.
- Bit 15 - 8 7 6 5 4 3 2 1 0
- fpr 15 - 8 7 5 3 1 6 4 2 0
- reg 31 - 24 23 22 21 20 19 18 17 16 */
- unsigned int fpr_bitmap;
-
- /* Number of floating point registers f8-f15 which must be saved. */
- int high_fprs;
-
- /* Set if return address needs to be saved.
- This flag is set by s390_return_addr_rtx if it could not use
- the initial value of r14 and therefore depends on r14 saved
- to the stack. */
- bool save_return_addr_p;
-
- /* Size of stack frame. */
- HOST_WIDE_INT frame_size;
-};
-
-/* Define the structure for the machine field in struct function. */
-
-struct GTY(()) machine_function
-{
- struct s390_frame_layout frame_layout;
-
- /* Literal pool base register. */
- rtx base_reg;
-
- /* True if we may need to perform branch splitting. */
- bool split_branches_pending_p;
-
- /* Some local-dynamic TLS symbol name. */
- const char *some_ld_name;
-
- bool has_landing_pad_p;
-};
-
-/* Few accessor macros for struct cfun->machine->s390_frame_layout. */
-
-#define cfun_frame_layout (cfun->machine->frame_layout)
-#define cfun_save_high_fprs_p (!!cfun_frame_layout.high_fprs)
-#define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr_slot - \
- cfun_frame_layout.first_save_gpr_slot + 1) * UNITS_PER_LONG)
-#define cfun_set_fpr_bit(BITNUM) (cfun->machine->frame_layout.fpr_bitmap |= \
- (1 << (BITNUM)))
-#define cfun_fpr_bit_p(BITNUM) (!!(cfun->machine->frame_layout.fpr_bitmap & \
- (1 << (BITNUM))))
-
-/* Number of GPRs and FPRs used for argument passing. */
-#define GP_ARG_NUM_REG 5
-#define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2)
-
-/* A couple of shortcuts. */
-#define CONST_OK_FOR_J(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'J', "J")
-#define CONST_OK_FOR_K(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'K', "K")
-#define CONST_OK_FOR_Os(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Os")
-#define CONST_OK_FOR_Op(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Op")
-#define CONST_OK_FOR_On(x) \
- CONST_OK_FOR_CONSTRAINT_P((x), 'O', "On")
-
-#define REGNO_PAIR_OK(REGNO, MODE) \
- (HARD_REGNO_NREGS ((REGNO), (MODE)) == 1 || !((REGNO) & 1))
-
-/* That's the read ahead of the dynamic branch prediction unit in
- bytes on a z10 (or higher) CPU. */
-#define PREDICT_DISTANCE (TARGET_Z10 ? 384 : 2048)
-
-/* Return the alignment for LABEL. We default to the -falign-labels
- value except for the literal pool base label. */
-int
-s390_label_align (rtx label)
-{
- rtx prev_insn = prev_active_insn (label);
-
- if (prev_insn == NULL_RTX)
- goto old;
-
- prev_insn = single_set (prev_insn);
-
- if (prev_insn == NULL_RTX)
- goto old;
-
- prev_insn = SET_SRC (prev_insn);
-
- /* Don't align literal pool base labels. */
- if (GET_CODE (prev_insn) == UNSPEC
- && XINT (prev_insn, 1) == UNSPEC_MAIN_BASE)
- return 0;
-
- old:
- return align_labels_log;
-}
-
-static enum machine_mode
-s390_libgcc_cmp_return_mode (void)
-{
- return TARGET_64BIT ? DImode : SImode;
-}
-
-static enum machine_mode
-s390_libgcc_shift_count_mode (void)
-{
- return TARGET_64BIT ? DImode : SImode;
-}
-
-static enum machine_mode
-s390_unwind_word_mode (void)
-{
- return TARGET_64BIT ? DImode : SImode;
-}
-
-/* Return true if the back end supports mode MODE. */
-static bool
-s390_scalar_mode_supported_p (enum machine_mode mode)
-{
- /* In contrast to the default implementation reject TImode constants on 31bit
- TARGET_ZARCH for ABI compliance. */
- if (!TARGET_64BIT && TARGET_ZARCH && mode == TImode)
- return false;
-
- if (DECIMAL_FLOAT_MODE_P (mode))
- return default_decimal_float_supported_p ();
-
- return default_scalar_mode_supported_p (mode);
-}
-
-/* Set the has_landing_pad_p flag in struct machine_function to VALUE. */
-
-void
-s390_set_has_landing_pad_p (bool value)
-{
- cfun->machine->has_landing_pad_p = value;
-}
-
-/* If two condition code modes are compatible, return a condition code
- mode which is compatible with both. Otherwise, return
- VOIDmode. */
-
-static enum machine_mode
-s390_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
-{
- if (m1 == m2)
- return m1;
-
- switch (m1)
- {
- case CCZmode:
- if (m2 == CCUmode || m2 == CCTmode || m2 == CCZ1mode
- || m2 == CCSmode || m2 == CCSRmode || m2 == CCURmode)
- return m2;
- return VOIDmode;
-
- case CCSmode:
- case CCUmode:
- case CCTmode:
- case CCSRmode:
- case CCURmode:
- case CCZ1mode:
- if (m2 == CCZmode)
- return m1;
-
- return VOIDmode;
-
- default:
- return VOIDmode;
- }
- return VOIDmode;
-}
-
-/* Return true if SET either doesn't set the CC register, or else
- the source and destination have matching CC modes and that
- CC mode is at least as constrained as REQ_MODE. */
-
-static bool
-s390_match_ccmode_set (rtx set, enum machine_mode req_mode)
-{
- enum machine_mode set_mode;
-
- gcc_assert (GET_CODE (set) == SET);
-
- if (GET_CODE (SET_DEST (set)) != REG || !CC_REGNO_P (REGNO (SET_DEST (set))))
- return 1;
-
- set_mode = GET_MODE (SET_DEST (set));
- switch (set_mode)
- {
- case CCSmode:
- case CCSRmode:
- case CCUmode:
- case CCURmode:
- case CCLmode:
- case CCL1mode:
- case CCL2mode:
- case CCL3mode:
- case CCT1mode:
- case CCT2mode:
- case CCT3mode:
- if (req_mode != set_mode)
- return 0;
- break;
-
- case CCZmode:
- if (req_mode != CCSmode && req_mode != CCUmode && req_mode != CCTmode
- && req_mode != CCSRmode && req_mode != CCURmode)
- return 0;
- break;
-
- case CCAPmode:
- case CCANmode:
- if (req_mode != CCAmode)
- return 0;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return (GET_MODE (SET_SRC (set)) == set_mode);
-}
-
-/* Return true if every SET in INSN that sets the CC register
- has source and destination with matching CC modes and that
- CC mode is at least as constrained as REQ_MODE.
- If REQ_MODE is VOIDmode, always return false. */
-
-bool
-s390_match_ccmode (rtx insn, enum machine_mode req_mode)
-{
- int i;
-
- /* s390_tm_ccmode returns VOIDmode to indicate failure. */
- if (req_mode == VOIDmode)
- return false;
-
- if (GET_CODE (PATTERN (insn)) == SET)
- return s390_match_ccmode_set (PATTERN (insn), req_mode);
-
- if (GET_CODE (PATTERN (insn)) == PARALLEL)
- for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- {
- rtx set = XVECEXP (PATTERN (insn), 0, i);
- if (GET_CODE (set) == SET)
- if (!s390_match_ccmode_set (set, req_mode))
- return false;
- }
-
- return true;
-}
-
-/* If a test-under-mask instruction can be used to implement
- (compare (and ... OP1) OP2), return the CC mode required
- to do that. Otherwise, return VOIDmode.
- MIXED is true if the instruction can distinguish between
- CC1 and CC2 for mixed selected bits (TMxx), it is false
- if the instruction cannot (TM). */
-
-enum machine_mode
-s390_tm_ccmode (rtx op1, rtx op2, bool mixed)
-{
- int bit0, bit1;
-
- /* ??? Fixme: should work on CONST_DOUBLE as well. */
- if (GET_CODE (op1) != CONST_INT || GET_CODE (op2) != CONST_INT)
- return VOIDmode;
-
- /* Selected bits all zero: CC0.
- e.g.: int a; if ((a & (16 + 128)) == 0) */
- if (INTVAL (op2) == 0)
- return CCTmode;
-
- /* Selected bits all one: CC3.
- e.g.: int a; if ((a & (16 + 128)) == 16 + 128) */
- if (INTVAL (op2) == INTVAL (op1))
- return CCT3mode;
-
- /* Exactly two bits selected, mixed zeroes and ones: CC1 or CC2. e.g.:
- int a;
- if ((a & (16 + 128)) == 16) -> CCT1
- if ((a & (16 + 128)) == 128) -> CCT2 */
- if (mixed)
- {
- bit1 = exact_log2 (INTVAL (op2));
- bit0 = exact_log2 (INTVAL (op1) ^ INTVAL (op2));
- if (bit0 != -1 && bit1 != -1)
- return bit0 > bit1 ? CCT1mode : CCT2mode;
- }
-
- return VOIDmode;
-}
-
-/* Given a comparison code OP (EQ, NE, etc.) and the operands
- OP0 and OP1 of a COMPARE, return the mode to be used for the
- comparison. */
-
-enum machine_mode
-s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
-{
- switch (code)
- {
- case EQ:
- case NE:
- if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
- return CCAPmode;
- if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
- && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))
- return CCAPmode;
- if ((GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
- || GET_CODE (op1) == NEG)
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
- return CCLmode;
-
- if (GET_CODE (op0) == AND)
- {
- /* Check whether we can potentially do it via TM. */
- enum machine_mode ccmode;
- ccmode = s390_tm_ccmode (XEXP (op0, 1), op1, 1);
- if (ccmode != VOIDmode)
- {
- /* Relax CCTmode to CCZmode to allow fall-back to AND
- if that turns out to be beneficial. */
- return ccmode == CCTmode ? CCZmode : ccmode;
- }
- }
-
- if (register_operand (op0, HImode)
- && GET_CODE (op1) == CONST_INT
- && (INTVAL (op1) == -1 || INTVAL (op1) == 65535))
- return CCT3mode;
- if (register_operand (op0, QImode)
- && GET_CODE (op1) == CONST_INT
- && (INTVAL (op1) == -1 || INTVAL (op1) == 255))
- return CCT3mode;
-
- return CCZmode;
-
- case LE:
- case LT:
- case GE:
- case GT:
- /* The only overflow condition of NEG and ABS happens when
- -INT_MAX is used as parameter, which stays negative. So
- we have an overflow from a positive value to a negative.
- Using CCAP mode the resulting cc can be used for comparisons. */
- if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
- return CCAPmode;
-
- /* If constants are involved in an add instruction it is possible to use
- the resulting cc for comparisons with zero. Knowing the sign of the
- constant the overflow behavior gets predictable. e.g.:
- int a, b; if ((b = a + c) > 0)
- with c as a constant value: c < 0 -> CCAN and c >= 0 -> CCAP */
- if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
- && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))
- {
- if (INTVAL (XEXP((op0), 1)) < 0)
- return CCANmode;
- else
- return CCAPmode;
- }
- /* Fall through. */
- case UNORDERED:
- case ORDERED:
- case UNEQ:
- case UNLE:
- case UNLT:
- case UNGE:
- case UNGT:
- case LTGT:
- if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
- && GET_CODE (op1) != CONST_INT)
- return CCSRmode;
- return CCSmode;
-
- case LTU:
- case GEU:
- if (GET_CODE (op0) == PLUS
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
- return CCL1mode;
-
- if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
- && GET_CODE (op1) != CONST_INT)
- return CCURmode;
- return CCUmode;
-
- case LEU:
- case GTU:
- if (GET_CODE (op0) == MINUS
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
- return CCL2mode;
-
- if ((GET_CODE (op0) == SIGN_EXTEND || GET_CODE (op0) == ZERO_EXTEND)
- && GET_CODE (op1) != CONST_INT)
- return CCURmode;
- return CCUmode;
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
- that we can implement more efficiently. */
-
-void
-s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
-{
- /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
- if ((*code == EQ || *code == NE)
- && *op1 == const0_rtx
- && GET_CODE (*op0) == ZERO_EXTRACT
- && GET_CODE (XEXP (*op0, 1)) == CONST_INT
- && GET_CODE (XEXP (*op0, 2)) == CONST_INT
- && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
- {
- rtx inner = XEXP (*op0, 0);
- HOST_WIDE_INT modesize = GET_MODE_BITSIZE (GET_MODE (inner));
- HOST_WIDE_INT len = INTVAL (XEXP (*op0, 1));
- HOST_WIDE_INT pos = INTVAL (XEXP (*op0, 2));
-
- if (len > 0 && len < modesize
- && pos >= 0 && pos + len <= modesize
- && modesize <= HOST_BITS_PER_WIDE_INT)
- {
- unsigned HOST_WIDE_INT block;
- block = ((unsigned HOST_WIDE_INT) 1 << len) - 1;
- block <<= modesize - pos - len;
-
- *op0 = gen_rtx_AND (GET_MODE (inner), inner,
- gen_int_mode (block, GET_MODE (inner)));
- }
- }
-
- /* Narrow AND of memory against immediate to enable TM. */
- if ((*code == EQ || *code == NE)
- && *op1 == const0_rtx
- && GET_CODE (*op0) == AND
- && GET_CODE (XEXP (*op0, 1)) == CONST_INT
- && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
- {
- rtx inner = XEXP (*op0, 0);
- rtx mask = XEXP (*op0, 1);
-
- /* Ignore paradoxical SUBREGs if all extra bits are masked out. */
- if (GET_CODE (inner) == SUBREG
- && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (inner)))
- && (GET_MODE_SIZE (GET_MODE (inner))
- >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner))))
- && ((INTVAL (mask)
- & GET_MODE_MASK (GET_MODE (inner))
- & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner))))
- == 0))
- inner = SUBREG_REG (inner);
-
- /* Do not change volatile MEMs. */
- if (MEM_P (inner) && !MEM_VOLATILE_P (inner))
- {
- int part = s390_single_part (XEXP (*op0, 1),
- GET_MODE (inner), QImode, 0);
- if (part >= 0)
- {
- mask = gen_int_mode (s390_extract_part (mask, QImode, 0), QImode);
- inner = adjust_address_nv (inner, QImode, part);
- *op0 = gen_rtx_AND (QImode, inner, mask);
- }
- }
- }
-
- /* Narrow comparisons against 0xffff to HImode if possible. */
- if ((*code == EQ || *code == NE)
- && GET_CODE (*op1) == CONST_INT
- && INTVAL (*op1) == 0xffff
- && SCALAR_INT_MODE_P (GET_MODE (*op0))
- && (nonzero_bits (*op0, GET_MODE (*op0))
- & ~(unsigned HOST_WIDE_INT) 0xffff) == 0)
- {
- *op0 = gen_lowpart (HImode, *op0);
- *op1 = constm1_rtx;
- }
-
- /* Remove redundant UNSPEC_CCU_TO_INT conversions if possible. */
- if (GET_CODE (*op0) == UNSPEC
- && XINT (*op0, 1) == UNSPEC_CCU_TO_INT
- && XVECLEN (*op0, 0) == 1
- && GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode
- && GET_CODE (XVECEXP (*op0, 0, 0)) == REG
- && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
- && *op1 == const0_rtx)
- {
- enum rtx_code new_code = UNKNOWN;
- switch (*code)
- {
- case EQ: new_code = EQ; break;
- case NE: new_code = NE; break;
- case LT: new_code = GTU; break;
- case GT: new_code = LTU; break;
- case LE: new_code = GEU; break;
- case GE: new_code = LEU; break;
- default: break;
- }
-
- if (new_code != UNKNOWN)
- {
- *op0 = XVECEXP (*op0, 0, 0);
- *code = new_code;
- }
- }
-
- /* Remove redundant UNSPEC_CCZ_TO_INT conversions if possible. */
- if (GET_CODE (*op0) == UNSPEC
- && XINT (*op0, 1) == UNSPEC_CCZ_TO_INT
- && XVECLEN (*op0, 0) == 1
- && GET_MODE (XVECEXP (*op0, 0, 0)) == CCZmode
- && GET_CODE (XVECEXP (*op0, 0, 0)) == REG
- && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
- && *op1 == const0_rtx)
- {
- enum rtx_code new_code = UNKNOWN;
- switch (*code)
- {
- case EQ: new_code = EQ; break;
- case NE: new_code = NE; break;
- default: break;
- }
-
- if (new_code != UNKNOWN)
- {
- *op0 = XVECEXP (*op0, 0, 0);
- *code = new_code;
- }
- }
-
- /* Simplify cascaded EQ, NE with const0_rtx. */
- if ((*code == NE || *code == EQ)
- && (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)
- && GET_MODE (*op0) == SImode
- && GET_MODE (XEXP (*op0, 0)) == CCZ1mode
- && REG_P (XEXP (*op0, 0))
- && XEXP (*op0, 1) == const0_rtx
- && *op1 == const0_rtx)
- {
- if ((*code == EQ && GET_CODE (*op0) == NE)
- || (*code == NE && GET_CODE (*op0) == EQ))
- *code = EQ;
- else
- *code = NE;
- *op0 = XEXP (*op0, 0);
- }
-
- /* Prefer register over memory as first operand. */
- if (MEM_P (*op0) && REG_P (*op1))
- {
- rtx tem = *op0; *op0 = *op1; *op1 = tem;
- *code = swap_condition (*code);
- }
-}
-
-/* Emit a compare instruction suitable to implement the comparison
- OP0 CODE OP1. Return the correct condition RTL to be placed in
- the IF_THEN_ELSE of the conditional branch testing the result. */
-
-rtx
-s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
-{
- enum machine_mode mode = s390_select_ccmode (code, op0, op1);
- rtx cc;
-
- /* Do not output a redundant compare instruction if a compare_and_swap
- pattern already computed the result and the machine modes are compatible. */
- if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC)
- {
- gcc_assert (s390_cc_modes_compatible (GET_MODE (op0), mode)
- == GET_MODE (op0));
- cc = op0;
- }
- else
- {
- cc = gen_rtx_REG (mode, CC_REGNUM);
- emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1)));
- }
-
- return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
-}
-
-/* Emit a SImode compare and swap instruction setting MEM to NEW_RTX if OLD
- matches CMP.
- Return the correct condition RTL to be placed in the IF_THEN_ELSE of the
- conditional branch testing the result. */
-
-static rtx
-s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem, rtx cmp, rtx new_rtx)
-{
- emit_insn (gen_sync_compare_and_swapsi (old, mem, cmp, new_rtx));
- return s390_emit_compare (code, gen_rtx_REG (CCZ1mode, CC_REGNUM), const0_rtx);
-}
-
-/* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an
- unconditional jump, else a conditional jump under condition COND. */
-
-void
-s390_emit_jump (rtx target, rtx cond)
-{
- rtx insn;
-
- target = gen_rtx_LABEL_REF (VOIDmode, target);
- if (cond)
- target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, target, pc_rtx);
-
- insn = gen_rtx_SET (VOIDmode, pc_rtx, target);
- emit_jump_insn (insn);
-}
-
-/* Return branch condition mask to implement a branch
- specified by CODE. Return -1 for invalid comparisons. */
-
-int
-s390_branch_condition_mask (rtx code)
-{
- const int CC0 = 1 << 3;
- const int CC1 = 1 << 2;
- const int CC2 = 1 << 1;
- const int CC3 = 1 << 0;
-
- gcc_assert (GET_CODE (XEXP (code, 0)) == REG);
- gcc_assert (REGNO (XEXP (code, 0)) == CC_REGNUM);
- gcc_assert (XEXP (code, 1) == const0_rtx);
-
- switch (GET_MODE (XEXP (code, 0)))
- {
- case CCZmode:
- case CCZ1mode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- default: return -1;
- }
- break;
-
- case CCT1mode:
- switch (GET_CODE (code))
- {
- case EQ: return CC1;
- case NE: return CC0 | CC2 | CC3;
- default: return -1;
- }
- break;
-
- case CCT2mode:
- switch (GET_CODE (code))
- {
- case EQ: return CC2;
- case NE: return CC0 | CC1 | CC3;
- default: return -1;
- }
- break;
-
- case CCT3mode:
- switch (GET_CODE (code))
- {
- case EQ: return CC3;
- case NE: return CC0 | CC1 | CC2;
- default: return -1;
- }
- break;
-
- case CCLmode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0 | CC2;
- case NE: return CC1 | CC3;
- default: return -1;
- }
- break;
-
- case CCL1mode:
- switch (GET_CODE (code))
- {
- case LTU: return CC2 | CC3; /* carry */
- case GEU: return CC0 | CC1; /* no carry */
- default: return -1;
- }
- break;
-
- case CCL2mode:
- switch (GET_CODE (code))
- {
- case GTU: return CC0 | CC1; /* borrow */
- case LEU: return CC2 | CC3; /* no borrow */
- default: return -1;
- }
- break;
-
- case CCL3mode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0 | CC2;
- case NE: return CC1 | CC3;
- case LTU: return CC1;
- case GTU: return CC3;
- case LEU: return CC1 | CC2;
- case GEU: return CC2 | CC3;
- default: return -1;
- }
-
- case CCUmode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LTU: return CC1;
- case GTU: return CC2;
- case LEU: return CC0 | CC1;
- case GEU: return CC0 | CC2;
- default: return -1;
- }
- break;
-
- case CCURmode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC2 | CC1 | CC3;
- case LTU: return CC2;
- case GTU: return CC1;
- case LEU: return CC0 | CC2;
- case GEU: return CC0 | CC1;
- default: return -1;
- }
- break;
-
- case CCAPmode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LT: return CC1 | CC3;
- case GT: return CC2;
- case LE: return CC0 | CC1 | CC3;
- case GE: return CC0 | CC2;
- default: return -1;
- }
- break;
-
- case CCANmode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LT: return CC1;
- case GT: return CC2 | CC3;
- case LE: return CC0 | CC1;
- case GE: return CC0 | CC2 | CC3;
- default: return -1;
- }
- break;
-
- case CCSmode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC1 | CC2 | CC3;
- case LT: return CC1;
- case GT: return CC2;
- case LE: return CC0 | CC1;
- case GE: return CC0 | CC2;
- case UNORDERED: return CC3;
- case ORDERED: return CC0 | CC1 | CC2;
- case UNEQ: return CC0 | CC3;
- case UNLT: return CC1 | CC3;
- case UNGT: return CC2 | CC3;
- case UNLE: return CC0 | CC1 | CC3;
- case UNGE: return CC0 | CC2 | CC3;
- case LTGT: return CC1 | CC2;
- default: return -1;
- }
- break;
-
- case CCSRmode:
- switch (GET_CODE (code))
- {
- case EQ: return CC0;
- case NE: return CC2 | CC1 | CC3;
- case LT: return CC2;
- case GT: return CC1;
- case LE: return CC0 | CC2;
- case GE: return CC0 | CC1;
- case UNORDERED: return CC3;
- case ORDERED: return CC0 | CC2 | CC1;
- case UNEQ: return CC0 | CC3;
- case UNLT: return CC2 | CC3;
- case UNGT: return CC1 | CC3;
- case UNLE: return CC0 | CC2 | CC3;
- case UNGE: return CC0 | CC1 | CC3;
- case LTGT: return CC2 | CC1;
- default: return -1;
- }
- break;
-
- default:
- return -1;
- }
-}
-
-
-/* Return branch condition mask to implement a compare and branch
- specified by CODE. Return -1 for invalid comparisons. */
-
-int
-s390_compare_and_branch_condition_mask (rtx code)
-{
- const int CC0 = 1 << 3;
- const int CC1 = 1 << 2;
- const int CC2 = 1 << 1;
-
- switch (GET_CODE (code))
- {
- case EQ:
- return CC0;
- case NE:
- return CC1 | CC2;
- case LT:
- case LTU:
- return CC1;
- case GT:
- case GTU:
- return CC2;
- case LE:
- case LEU:
- return CC0 | CC1;
- case GE:
- case GEU:
- return CC0 | CC2;
- default:
- gcc_unreachable ();
- }
- return -1;
-}
-
-/* If INV is false, return assembler mnemonic string to implement
- a branch specified by CODE. If INV is true, return mnemonic
- for the corresponding inverted branch. */
-
-static const char *
-s390_branch_condition_mnemonic (rtx code, int inv)
-{
- int mask;
-
- static const char *const mnemonic[16] =
- {
- NULL, "o", "h", "nle",
- "l", "nhe", "lh", "ne",
- "e", "nlh", "he", "nl",
- "le", "nh", "no", NULL
- };
-
- if (GET_CODE (XEXP (code, 0)) == REG
- && REGNO (XEXP (code, 0)) == CC_REGNUM
- && XEXP (code, 1) == const0_rtx)
- mask = s390_branch_condition_mask (code);
- else
- mask = s390_compare_and_branch_condition_mask (code);
-
- gcc_assert (mask >= 0);
-
- if (inv)
- mask ^= 15;
-
- gcc_assert (mask >= 1 && mask <= 14);
-
- return mnemonic[mask];
-}
-
-/* Return the part of op which has a value different from def.
- The size of the part is determined by mode.
- Use this function only if you already know that op really
- contains such a part. */
-
-unsigned HOST_WIDE_INT
-s390_extract_part (rtx op, enum machine_mode mode, int def)
-{
- unsigned HOST_WIDE_INT value = 0;
- int max_parts = HOST_BITS_PER_WIDE_INT / GET_MODE_BITSIZE (mode);
- int part_bits = GET_MODE_BITSIZE (mode);
- unsigned HOST_WIDE_INT part_mask
- = ((unsigned HOST_WIDE_INT)1 << part_bits) - 1;
- int i;
-
- for (i = 0; i < max_parts; i++)
- {
- if (i == 0)
- value = (unsigned HOST_WIDE_INT) INTVAL (op);
- else
- value >>= part_bits;
-
- if ((value & part_mask) != (def & part_mask))
- return value & part_mask;
- }
-
- gcc_unreachable ();
-}
-
-/* If OP is an integer constant of mode MODE with exactly one
- part of mode PART_MODE unequal to DEF, return the number of that
- part. Otherwise, return -1. */
-
-int
-s390_single_part (rtx op,
- enum machine_mode mode,
- enum machine_mode part_mode,
- int def)
-{
- unsigned HOST_WIDE_INT value = 0;
- int n_parts = GET_MODE_SIZE (mode) / GET_MODE_SIZE (part_mode);
- unsigned HOST_WIDE_INT part_mask
- = ((unsigned HOST_WIDE_INT)1 << GET_MODE_BITSIZE (part_mode)) - 1;
- int i, part = -1;
-
- if (GET_CODE (op) != CONST_INT)
- return -1;
-
- for (i = 0; i < n_parts; i++)
- {
- if (i == 0)
- value = (unsigned HOST_WIDE_INT) INTVAL (op);
- else
- value >>= GET_MODE_BITSIZE (part_mode);
-
- if ((value & part_mask) != (def & part_mask))
- {
- if (part != -1)
- return -1;
- else
- part = i;
- }
- }
- return part == -1 ? -1 : n_parts - 1 - part;
-}
-
-/* Return true if IN contains a contiguous bitfield in the lower SIZE
- bits and no other bits are set in IN. POS and LENGTH can be used
- to obtain the start position and the length of the bitfield.
-
- POS gives the position of the first bit of the bitfield counting
- from the lowest order bit starting with zero. In order to use this
- value for S/390 instructions this has to be converted to "bits big
- endian" style. */
-
-bool
-s390_contiguous_bitmask_p (unsigned HOST_WIDE_INT in, int size,
- int *pos, int *length)
-{
- int tmp_pos = 0;
- int tmp_length = 0;
- int i;
- unsigned HOST_WIDE_INT mask = 1ULL;
- bool contiguous = false;
-
- for (i = 0; i < size; mask <<= 1, i++)
- {
- if (contiguous)
- {
- if (mask & in)
- tmp_length++;
- else
- break;
- }
- else
- {
- if (mask & in)
- {
- contiguous = true;
- tmp_length++;
- }
- else
- tmp_pos++;
- }
- }
-
- if (!tmp_length)
- return false;
-
- /* Calculate a mask for all bits beyond the contiguous bits. */
- mask = (-1LL & ~(((1ULL << (tmp_length + tmp_pos - 1)) << 1) - 1));
-
- if (mask & in)
- return false;
-
- if (tmp_length + tmp_pos - 1 > size)
- return false;
-
- if (length)
- *length = tmp_length;
-
- if (pos)
- *pos = tmp_pos;
-
- return true;
-}
-
-/* Check whether we can (and want to) split a double-word
- move in mode MODE from SRC to DST into two single-word
- moves, moving the subword FIRST_SUBWORD first. */
-
-bool
-s390_split_ok_p (rtx dst, rtx src, enum machine_mode mode, int first_subword)
-{
- /* Floating point registers cannot be split. */
- if (FP_REG_P (src) || FP_REG_P (dst))
- return false;
-
- /* We don't need to split if operands are directly accessible. */
- if (s_operand (src, mode) || s_operand (dst, mode))
- return false;
-
- /* Non-offsettable memory references cannot be split. */
- if ((GET_CODE (src) == MEM && !offsettable_memref_p (src))
- || (GET_CODE (dst) == MEM && !offsettable_memref_p (dst)))
- return false;
-
- /* Moving the first subword must not clobber a register
- needed to move the second subword. */
- if (register_operand (dst, mode))
- {
- rtx subreg = operand_subword (dst, first_subword, 0, mode);
- if (reg_overlap_mentioned_p (subreg, src))
- return false;
- }
-
- return true;
-}
-
-/* Return true if it can be proven that [MEM1, MEM1 + SIZE]
- and [MEM2, MEM2 + SIZE] do overlap and false
- otherwise. */
-
-bool
-s390_overlap_p (rtx mem1, rtx mem2, HOST_WIDE_INT size)
-{
- rtx addr1, addr2, addr_delta;
- HOST_WIDE_INT delta;
-
- if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
- return true;
-
- if (size == 0)
- return false;
-
- addr1 = XEXP (mem1, 0);
- addr2 = XEXP (mem2, 0);
-
- addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
-
- /* This overlapping check is used by peepholes merging memory block operations.
- Overlapping operations would otherwise be recognized by the S/390 hardware
- and would fall back to a slower implementation. Allowing overlapping
- operations would lead to slow code but not to wrong code. Therefore we are
- somewhat optimistic if we cannot prove that the memory blocks are
- overlapping.
- That's why we return false here although this may accept operations on
- overlapping memory areas. */
- if (!addr_delta || GET_CODE (addr_delta) != CONST_INT)
- return false;
-
- delta = INTVAL (addr_delta);
-
- if (delta == 0
- || (delta > 0 && delta < size)
- || (delta < 0 && -delta < size))
- return true;
-
- return false;
-}
-
-/* Check whether the address of memory reference MEM2 equals exactly
- the address of memory reference MEM1 plus DELTA. Return true if
- we can prove this to be the case, false otherwise. */
-
-bool
-s390_offset_p (rtx mem1, rtx mem2, rtx delta)
-{
- rtx addr1, addr2, addr_delta;
-
- if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
- return false;
-
- addr1 = XEXP (mem1, 0);
- addr2 = XEXP (mem2, 0);
-
- addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
- if (!addr_delta || !rtx_equal_p (addr_delta, delta))
- return false;
-
- return true;
-}
-
-/* Expand logical operator CODE in mode MODE with operands OPERANDS. */
-
-void
-s390_expand_logical_operator (enum rtx_code code, enum machine_mode mode,
- rtx *operands)
-{
- enum machine_mode wmode = mode;
- rtx dst = operands[0];
- rtx src1 = operands[1];
- rtx src2 = operands[2];
- rtx op, clob, tem;
-
- /* If we cannot handle the operation directly, use a temp register. */
- if (!s390_logical_operator_ok_p (operands))
- dst = gen_reg_rtx (mode);
-
- /* QImode and HImode patterns make sense only if we have a destination
- in memory. Otherwise perform the operation in SImode. */
- if ((mode == QImode || mode == HImode) && GET_CODE (dst) != MEM)
- wmode = SImode;
-
- /* Widen operands if required. */
- if (mode != wmode)
- {
- if (GET_CODE (dst) == SUBREG
- && (tem = simplify_subreg (wmode, dst, mode, 0)) != 0)
- dst = tem;
- else if (REG_P (dst))
- dst = gen_rtx_SUBREG (wmode, dst, 0);
- else
- dst = gen_reg_rtx (wmode);
-
- if (GET_CODE (src1) == SUBREG
- && (tem = simplify_subreg (wmode, src1, mode, 0)) != 0)
- src1 = tem;
- else if (GET_MODE (src1) != VOIDmode)
- src1 = gen_rtx_SUBREG (wmode, force_reg (mode, src1), 0);
-
- if (GET_CODE (src2) == SUBREG
- && (tem = simplify_subreg (wmode, src2, mode, 0)) != 0)
- src2 = tem;
- else if (GET_MODE (src2) != VOIDmode)
- src2 = gen_rtx_SUBREG (wmode, force_reg (mode, src2), 0);
- }
-
- /* Emit the instruction. */
- op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_ee (code, wmode, src1, src2));
- clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
-
- /* Fix up the destination if needed. */
- if (dst != operands[0])
- emit_move_insn (operands[0], gen_lowpart (mode, dst));
-}
-
-/* Check whether OPERANDS are OK for a logical operation (AND, IOR, XOR). */
-
-bool
-s390_logical_operator_ok_p (rtx *operands)
-{
- /* If the destination operand is in memory, it needs to coincide
- with one of the source operands. After reload, it has to be
- the first source operand. */
- if (GET_CODE (operands[0]) == MEM)
- return rtx_equal_p (operands[0], operands[1])
- || (!reload_completed && rtx_equal_p (operands[0], operands[2]));
-
- return true;
-}
-
-/* Narrow logical operation CODE of memory operand MEMOP with immediate
- operand IMMOP to switch from SS to SI type instructions. */
-
-void
-s390_narrow_logical_operator (enum rtx_code code, rtx *memop, rtx *immop)
-{
- int def = code == AND ? -1 : 0;
- HOST_WIDE_INT mask;
- int part;
-
- gcc_assert (GET_CODE (*memop) == MEM);
- gcc_assert (!MEM_VOLATILE_P (*memop));
-
- mask = s390_extract_part (*immop, QImode, def);
- part = s390_single_part (*immop, GET_MODE (*memop), QImode, def);
- gcc_assert (part >= 0);
-
- *memop = adjust_address (*memop, QImode, part);
- *immop = gen_int_mode (mask, QImode);
-}
-
-
-/* How to allocate a 'struct machine_function'. */
-
-static struct machine_function *
-s390_init_machine_status (void)
-{
- return ggc_alloc_cleared_machine_function ();
-}
-
-static void
-s390_option_override (void)
-{
- /* Set up function hooks. */
- init_machine_status = s390_init_machine_status;
-
- /* Architecture mode defaults according to ABI. */
- if (!(target_flags_explicit & MASK_ZARCH))
- {
- if (TARGET_64BIT)
- target_flags |= MASK_ZARCH;
- else
- target_flags &= ~MASK_ZARCH;
- }
-
- /* Set the march default in case it hasn't been specified on
- cmdline. */
- if (s390_arch == PROCESSOR_max)
- {
- s390_arch_string = TARGET_ZARCH? "z900" : "g5";
- s390_arch = TARGET_ZARCH ? PROCESSOR_2064_Z900 : PROCESSOR_9672_G5;
- s390_arch_flags = processor_flags_table[(int)s390_arch];
- }
-
- /* Determine processor to tune for. */
- if (s390_tune == PROCESSOR_max)
- {
- s390_tune = s390_arch;
- s390_tune_flags = s390_arch_flags;
- }
-
- /* Sanity checks. */
- if (TARGET_ZARCH && !TARGET_CPU_ZARCH)
- error ("z/Architecture mode not supported on %s", s390_arch_string);
- if (TARGET_64BIT && !TARGET_ZARCH)
- error ("64-bit ABI not supported in ESA/390 mode");
-
- /* Use hardware DFP if available and not explicitly disabled by
- user. E.g. with -m31 -march=z10 -mzarch */
- if (!(target_flags_explicit & MASK_HARD_DFP) && TARGET_DFP)
- target_flags |= MASK_HARD_DFP;
-
- if (TARGET_HARD_DFP && !TARGET_DFP)
- {
- if (target_flags_explicit & MASK_HARD_DFP)
- {
- if (!TARGET_CPU_DFP)
- error ("hardware decimal floating point instructions"
- " not available on %s", s390_arch_string);
- if (!TARGET_ZARCH)
- error ("hardware decimal floating point instructions"
- " not available in ESA/390 mode");
- }
- else
- target_flags &= ~MASK_HARD_DFP;
- }
-
- if ((target_flags_explicit & MASK_SOFT_FLOAT) && TARGET_SOFT_FLOAT)
- {
- if ((target_flags_explicit & MASK_HARD_DFP) && TARGET_HARD_DFP)
- error ("-mhard-dfp can%'t be used in conjunction with -msoft-float");
-
- target_flags &= ~MASK_HARD_DFP;
- }
-
- /* Set processor cost function. */
- switch (s390_tune)
- {
- case PROCESSOR_2084_Z990:
- s390_cost = &z990_cost;
- break;
- case PROCESSOR_2094_Z9_109:
- s390_cost = &z9_109_cost;
- break;
- case PROCESSOR_2097_Z10:
- s390_cost = &z10_cost;
- case PROCESSOR_2817_Z196:
- s390_cost = &z196_cost;
- break;
- default:
- s390_cost = &z900_cost;
- }
-
- if (TARGET_BACKCHAIN && TARGET_PACKED_STACK && TARGET_HARD_FLOAT)
- error ("-mbackchain -mpacked-stack -mhard-float are not supported "
- "in combination");
-
- if (s390_stack_size)
- {
- if (s390_stack_guard >= s390_stack_size)
- error ("stack size must be greater than the stack guard value");
- else if (s390_stack_size > 1 << 16)
- error ("stack size must not be greater than 64k");
- }
- else if (s390_stack_guard)
- error ("-mstack-guard implies use of -mstack-size");
-
-#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
- if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
- target_flags |= MASK_LONG_DOUBLE_128;
-#endif
-
- if (s390_tune == PROCESSOR_2097_Z10
- || s390_tune == PROCESSOR_2817_Z196)
- {
- maybe_set_param_value (PARAM_MAX_UNROLLED_INSNS, 100,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_MAX_UNROLL_TIMES, 32,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_MAX_COMPLETELY_PEELED_INSNS, 2000,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_MAX_COMPLETELY_PEEL_TIMES, 64,
- global_options.x_param_values,
- global_options_set.x_param_values);
- }
-
- maybe_set_param_value (PARAM_MAX_PENDING_LIST_LENGTH, 256,
- global_options.x_param_values,
- global_options_set.x_param_values);
- /* values for loop prefetching */
- maybe_set_param_value (PARAM_L1_CACHE_LINE_SIZE, 256,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_L1_CACHE_SIZE, 128,
- global_options.x_param_values,
- global_options_set.x_param_values);
- /* s390 has more than 2 levels and the size is much larger. Since
- we are always running virtualized assume that we only get a small
- part of the caches above l1. */
- maybe_set_param_value (PARAM_L2_CACHE_SIZE, 1500,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_PREFETCH_MIN_INSN_TO_MEM_RATIO, 2,
- global_options.x_param_values,
- global_options_set.x_param_values);
- maybe_set_param_value (PARAM_SIMULTANEOUS_PREFETCHES, 6,
- global_options.x_param_values,
- global_options_set.x_param_values);
-
- /* This cannot reside in s390_option_optimization_table since HAVE_prefetch
- requires the arch flags to be evaluated already. Since prefetching
- is beneficial on s390, we enable it if available. */
- if (flag_prefetch_loop_arrays < 0 && HAVE_prefetch && optimize >= 3)
- flag_prefetch_loop_arrays = 1;
-}
-
-/* Map for smallest class containing reg regno. */
-
-const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
-{ GENERAL_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
- ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
- ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
- ADDR_REGS, ADDR_REGS, ADDR_REGS, ADDR_REGS,
- FP_REGS, FP_REGS, FP_REGS, FP_REGS,
- 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, CC_REGS, ADDR_REGS, ADDR_REGS,
- ACCESS_REGS, ACCESS_REGS
-};
-
-/* Return attribute type of insn. */
-
-static enum attr_type
-s390_safe_attr_type (rtx insn)
-{
- if (recog_memoized (insn) >= 0)
- return get_attr_type (insn);
- else
- return TYPE_NONE;
-}
-
-/* Return true if DISP is a valid short displacement. */
-
-static bool
-s390_short_displacement (rtx disp)
-{
- /* No displacement is OK. */
- if (!disp)
- return true;
-
- /* Without the long displacement facility we don't need to
- distingiush between long and short displacement. */
- if (!TARGET_LONG_DISPLACEMENT)
- return true;
-
- /* Integer displacement in range. */
- if (GET_CODE (disp) == CONST_INT)
- return INTVAL (disp) >= 0 && INTVAL (disp) < 4096;
-
- /* GOT offset is not OK, the GOT can be large. */
- if (GET_CODE (disp) == CONST
- && GET_CODE (XEXP (disp, 0)) == UNSPEC
- && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT
- || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
- return false;
-
- /* All other symbolic constants are literal pool references,
- which are OK as the literal pool must be small. */
- if (GET_CODE (disp) == CONST)
- return true;
-
- return false;
-}
-
-/* Decompose a RTL expression ADDR for a memory address into
- its components, returned in OUT.
-
- Returns false if ADDR is not a valid memory address, true
- otherwise. If OUT is NULL, don't return the components,
- but check for validity only.
-
- Note: Only addresses in canonical form are recognized.
- LEGITIMIZE_ADDRESS should convert non-canonical forms to the
- canonical form so that they will be recognized. */
-
-static int
-s390_decompose_address (rtx addr, struct s390_address *out)
-{
- HOST_WIDE_INT offset = 0;
- rtx base = NULL_RTX;
- rtx indx = NULL_RTX;
- rtx disp = NULL_RTX;
- rtx orig_disp;
- bool pointer = false;
- bool base_ptr = false;
- bool indx_ptr = false;
- bool literal_pool = false;
-
- /* We may need to substitute the literal pool base register into the address
- below. However, at this point we do not know which register is going to
- be used as base, so we substitute the arg pointer register. This is going
- to be treated as holding a pointer below -- it shouldn't be used for any
- other purpose. */
- rtx fake_pool_base = gen_rtx_REG (Pmode, ARG_POINTER_REGNUM);
-
- /* Decompose address into base + index + displacement. */
-
- if (GET_CODE (addr) == REG || GET_CODE (addr) == UNSPEC)
- base = addr;
-
- else if (GET_CODE (addr) == PLUS)
- {
- rtx op0 = XEXP (addr, 0);
- rtx op1 = XEXP (addr, 1);
- enum rtx_code code0 = GET_CODE (op0);
- enum rtx_code code1 = GET_CODE (op1);
-
- if (code0 == REG || code0 == UNSPEC)
- {
- if (code1 == REG || code1 == UNSPEC)
- {
- indx = op0; /* index + base */
- base = op1;
- }
-
- else
- {
- base = op0; /* base + displacement */
- disp = op1;
- }
- }
-
- else if (code0 == PLUS)
- {
- indx = XEXP (op0, 0); /* index + base + disp */
- base = XEXP (op0, 1);
- disp = op1;
- }
-
- else
- {
- return false;
- }
- }
-
- else
- disp = addr; /* displacement */
-
- /* Extract integer part of displacement. */
- orig_disp = disp;
- if (disp)
- {
- if (GET_CODE (disp) == CONST_INT)
- {
- offset = INTVAL (disp);
- disp = NULL_RTX;
- }
- else if (GET_CODE (disp) == CONST
- && GET_CODE (XEXP (disp, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
- {
- offset = INTVAL (XEXP (XEXP (disp, 0), 1));
- disp = XEXP (XEXP (disp, 0), 0);
- }
- }
-
- /* Strip off CONST here to avoid special case tests later. */
- if (disp && GET_CODE (disp) == CONST)
- disp = XEXP (disp, 0);
-
- /* We can convert literal pool addresses to
- displacements by basing them off the base register. */
- if (disp && GET_CODE (disp) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (disp))
- {
- /* Either base or index must be free to hold the base register. */
- if (!base)
- base = fake_pool_base, literal_pool = true;
- else if (!indx)
- indx = fake_pool_base, literal_pool = true;
- else
- return false;
-
- /* Mark up the displacement. */
- disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),
- UNSPEC_LTREL_OFFSET);
- }
-
- /* Validate base register. */
- if (base)
- {
- if (GET_CODE (base) == UNSPEC)
- switch (XINT (base, 1))
- {
- case UNSPEC_LTREF:
- if (!disp)
- disp = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (1, XVECEXP (base, 0, 0)),
- UNSPEC_LTREL_OFFSET);
- else
- return false;
-
- base = XVECEXP (base, 0, 1);
- break;
-
- case UNSPEC_LTREL_BASE:
- if (XVECLEN (base, 0) == 1)
- base = fake_pool_base, literal_pool = true;
- else
- base = XVECEXP (base, 0, 1);
- break;
-
- default:
- return false;
- }
-
- if (!REG_P (base)
- || (GET_MODE (base) != SImode
- && GET_MODE (base) != Pmode))
- return false;
-
- if (REGNO (base) == STACK_POINTER_REGNUM
- || REGNO (base) == FRAME_POINTER_REGNUM
- || ((reload_completed || reload_in_progress)
- && frame_pointer_needed
- && REGNO (base) == HARD_FRAME_POINTER_REGNUM)
- || REGNO (base) == ARG_POINTER_REGNUM
- || (flag_pic
- && REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
- pointer = base_ptr = true;
-
- if ((reload_completed || reload_in_progress)
- && base == cfun->machine->base_reg)
- pointer = base_ptr = literal_pool = true;
- }
-
- /* Validate index register. */
- if (indx)
- {
- if (GET_CODE (indx) == UNSPEC)
- switch (XINT (indx, 1))
- {
- case UNSPEC_LTREF:
- if (!disp)
- disp = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (1, XVECEXP (indx, 0, 0)),
- UNSPEC_LTREL_OFFSET);
- else
- return false;
-
- indx = XVECEXP (indx, 0, 1);
- break;
-
- case UNSPEC_LTREL_BASE:
- if (XVECLEN (indx, 0) == 1)
- indx = fake_pool_base, literal_pool = true;
- else
- indx = XVECEXP (indx, 0, 1);
- break;
-
- default:
- return false;
- }
-
- if (!REG_P (indx)
- || (GET_MODE (indx) != SImode
- && GET_MODE (indx) != Pmode))
- return false;
-
- if (REGNO (indx) == STACK_POINTER_REGNUM
- || REGNO (indx) == FRAME_POINTER_REGNUM
- || ((reload_completed || reload_in_progress)
- && frame_pointer_needed
- && REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
- || REGNO (indx) == ARG_POINTER_REGNUM
- || (flag_pic
- && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
- pointer = indx_ptr = true;
-
- if ((reload_completed || reload_in_progress)
- && indx == cfun->machine->base_reg)
- pointer = indx_ptr = literal_pool = true;
- }
-
- /* Prefer to use pointer as base, not index. */
- if (base && indx && !base_ptr
- && (indx_ptr || (!REG_POINTER (base) && REG_POINTER (indx))))
- {
- rtx tmp = base;
- base = indx;
- indx = tmp;
- }
-
- /* Validate displacement. */
- if (!disp)
- {
- /* If virtual registers are involved, the displacement will change later
- anyway as the virtual registers get eliminated. This could make a
- valid displacement invalid, but it is more likely to make an invalid
- displacement valid, because we sometimes access the register save area
- via negative offsets to one of those registers.
- Thus we don't check the displacement for validity here. If after
- elimination the displacement turns out to be invalid after all,
- this is fixed up by reload in any case. */
- if (base != arg_pointer_rtx
- && indx != arg_pointer_rtx
- && base != return_address_pointer_rtx
- && indx != return_address_pointer_rtx
- && base != frame_pointer_rtx
- && indx != frame_pointer_rtx
- && base != virtual_stack_vars_rtx
- && indx != virtual_stack_vars_rtx)
- if (!DISP_IN_RANGE (offset))
- return false;
- }
- else
- {
- /* All the special cases are pointers. */
- pointer = true;
-
- /* In the small-PIC case, the linker converts @GOT
- and @GOTNTPOFF offsets to possible displacements. */
- if (GET_CODE (disp) == UNSPEC
- && (XINT (disp, 1) == UNSPEC_GOT
- || XINT (disp, 1) == UNSPEC_GOTNTPOFF)
- && flag_pic == 1)
- {
- ;
- }
-
- /* Accept pool label offsets. */
- else if (GET_CODE (disp) == UNSPEC
- && XINT (disp, 1) == UNSPEC_POOL_OFFSET)
- ;
-
- /* Accept literal pool references. */
- else if (GET_CODE (disp) == UNSPEC
- && XINT (disp, 1) == UNSPEC_LTREL_OFFSET)
- {
- /* In case CSE pulled a non literal pool reference out of
- the pool we have to reject the address. This is
- especially important when loading the GOT pointer on non
- zarch CPUs. In this case the literal pool contains an lt
- relative offset to the _GLOBAL_OFFSET_TABLE_ label which
- will most likely exceed the displacement. */
- if (GET_CODE (XVECEXP (disp, 0, 0)) != SYMBOL_REF
- || !CONSTANT_POOL_ADDRESS_P (XVECEXP (disp, 0, 0)))
- return false;
-
- orig_disp = gen_rtx_CONST (Pmode, disp);
- if (offset)
- {
- /* If we have an offset, make sure it does not
- exceed the size of the constant pool entry. */
- rtx sym = XVECEXP (disp, 0, 0);
- if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))
- return false;
-
- orig_disp = plus_constant (orig_disp, offset);
- }
- }
-
- else
- return false;
- }
-
- if (!base && !indx)
- pointer = true;
-
- if (out)
- {
- out->base = base;
- out->indx = indx;
- out->disp = orig_disp;
- out->pointer = pointer;
- out->literal_pool = literal_pool;
- }
-
- return true;
-}
-
-/* Decompose a RTL expression OP for a shift count into its components,
- and return the base register in BASE and the offset in OFFSET.
-
- Return true if OP is a valid shift count, false if not. */
-
-bool
-s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
-{
- HOST_WIDE_INT off = 0;
-
- /* We can have an integer constant, an address register,
- or a sum of the two. */
- if (GET_CODE (op) == CONST_INT)
- {
- off = INTVAL (op);
- op = NULL_RTX;
- }
- if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
- {
- off = INTVAL (XEXP (op, 1));
- op = XEXP (op, 0);
- }
- while (op && GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- if (op && GET_CODE (op) != REG)
- return false;
-
- if (offset)
- *offset = off;
- if (base)
- *base = op;
-
- return true;
-}
-
-
-/* Return true if CODE is a valid address without index. */
-
-bool
-s390_legitimate_address_without_index_p (rtx op)
-{
- struct s390_address addr;
-
- if (!s390_decompose_address (XEXP (op, 0), &addr))
- return false;
- if (addr.indx)
- return false;
-
- return true;
-}
-
-
-/* Return true if ADDR is of kind symbol_ref or symbol_ref + const_int
- and return these parts in SYMREF and ADDEND. You can pass NULL in
- SYMREF and/or ADDEND if you are not interested in these values.
- Literal pool references are *not* considered symbol references. */
-
-static bool
-s390_symref_operand_p (rtx addr, rtx *symref, HOST_WIDE_INT *addend)
-{
- HOST_WIDE_INT tmpaddend = 0;
-
- if (GET_CODE (addr) == CONST)
- addr = XEXP (addr, 0);
-
- if (GET_CODE (addr) == PLUS)
- {
- if (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
- && !CONSTANT_POOL_ADDRESS_P (XEXP (addr, 0))
- && CONST_INT_P (XEXP (addr, 1)))
- {
- tmpaddend = INTVAL (XEXP (addr, 1));
- addr = XEXP (addr, 0);
- }
- else
- return false;
- }
- else
- if (GET_CODE (addr) != SYMBOL_REF || CONSTANT_POOL_ADDRESS_P (addr))
- return false;
-
- if (symref)
- *symref = addr;
- if (addend)
- *addend = tmpaddend;
-
- return true;
-}
-
-
-/* Return true if the address in OP is valid for constraint letter C
- if wrapped in a MEM rtx. Set LIT_POOL_OK to true if it literal
- pool MEMs should be accepted. Only the Q, R, S, T constraint
- letters are allowed for C. */
-
-static int
-s390_check_qrst_address (char c, rtx op, bool lit_pool_ok)
-{
- struct s390_address addr;
- bool decomposed = false;
-
- /* This check makes sure that no symbolic address (except literal
- pool references) are accepted by the R or T constraints. */
- if (s390_symref_operand_p (op, NULL, NULL))
- return 0;
-
- /* Ensure literal pool references are only accepted if LIT_POOL_OK. */
- if (!lit_pool_ok)
- {
- if (!s390_decompose_address (op, &addr))
- return 0;
- if (addr.literal_pool)
- return 0;
- decomposed = true;
- }
-
- switch (c)
- {
- case 'Q': /* no index short displacement */
- if (!decomposed && !s390_decompose_address (op, &addr))
- return 0;
- if (addr.indx)
- return 0;
- if (!s390_short_displacement (addr.disp))
- return 0;
- break;
-
- case 'R': /* with index short displacement */
- if (TARGET_LONG_DISPLACEMENT)
- {
- if (!decomposed && !s390_decompose_address (op, &addr))
- return 0;
- if (!s390_short_displacement (addr.disp))
- return 0;
- }
- /* Any invalid address here will be fixed up by reload,
- so accept it for the most generic constraint. */
- break;
-
- case 'S': /* no index long displacement */
- if (!TARGET_LONG_DISPLACEMENT)
- return 0;
- if (!decomposed && !s390_decompose_address (op, &addr))
- return 0;
- if (addr.indx)
- return 0;
- if (s390_short_displacement (addr.disp))
- return 0;
- break;
-
- case 'T': /* with index long displacement */
- if (!TARGET_LONG_DISPLACEMENT)
- return 0;
- /* Any invalid address here will be fixed up by reload,
- so accept it for the most generic constraint. */
- if ((decomposed || s390_decompose_address (op, &addr))
- && s390_short_displacement (addr.disp))
- return 0;
- break;
- default:
- return 0;
- }
- return 1;
-}
-
-
-/* Evaluates constraint strings described by the regular expression
- ([A|B|Z](Q|R|S|T))|U|W|Y and returns 1 if OP is a valid operand for
- the constraint given in STR, or 0 else. */
-
-int
-s390_mem_constraint (const char *str, rtx op)
-{
- char c = str[0];
-
- switch (c)
- {
- case 'A':
- /* Check for offsettable variants of memory constraints. */
- if (!MEM_P (op) || MEM_VOLATILE_P (op))
- return 0;
- if ((reload_completed || reload_in_progress)
- ? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op))
- return 0;
- return s390_check_qrst_address (str[1], XEXP (op, 0), true);
- case 'B':
- /* Check for non-literal-pool variants of memory constraints. */
- if (!MEM_P (op))
- return 0;
- return s390_check_qrst_address (str[1], XEXP (op, 0), false);
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- if (GET_CODE (op) != MEM)
- return 0;
- return s390_check_qrst_address (c, XEXP (op, 0), true);
- case 'U':
- return (s390_check_qrst_address ('Q', op, true)
- || s390_check_qrst_address ('R', op, true));
- case 'W':
- return (s390_check_qrst_address ('S', op, true)
- || s390_check_qrst_address ('T', op, true));
- case 'Y':
- /* Simply check for the basic form of a shift count. Reload will
- take care of making sure we have a proper base register. */
- if (!s390_decompose_shift_count (op, NULL, NULL))
- return 0;
- break;
- case 'Z':
- return s390_check_qrst_address (str[1], op, true);
- default:
- return 0;
- }
- return 1;
-}
-
-
-/* Evaluates constraint strings starting with letter O. Input
- parameter C is the second letter following the "O" in the constraint
- string. Returns 1 if VALUE meets the respective constraint and 0
- otherwise. */
-
-int
-s390_O_constraint_str (const char c, HOST_WIDE_INT value)
-{
- if (!TARGET_EXTIMM)
- return 0;
-
- switch (c)
- {
- case 's':
- return trunc_int_for_mode (value, SImode) == value;
-
- case 'p':
- return value == 0
- || s390_single_part (GEN_INT (value), DImode, SImode, 0) == 1;
-
- case 'n':
- return s390_single_part (GEN_INT (value - 1), DImode, SImode, -1) == 1;
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-/* Evaluates constraint strings starting with letter N. Parameter STR
- contains the letters following letter "N" in the constraint string.
- Returns true if VALUE matches the constraint. */
-
-int
-s390_N_constraint_str (const char *str, HOST_WIDE_INT value)
-{
- enum machine_mode mode, part_mode;
- int def;
- int part, part_goal;
-
-
- if (str[0] == 'x')
- part_goal = -1;
- else
- part_goal = str[0] - '0';
-
- switch (str[1])
- {
- case 'Q':
- part_mode = QImode;
- break;
- case 'H':
- part_mode = HImode;
- break;
- case 'S':
- part_mode = SImode;
- break;
- default:
- return 0;
- }
-
- switch (str[2])
- {
- case 'H':
- mode = HImode;
- break;
- case 'S':
- mode = SImode;
- break;
- case 'D':
- mode = DImode;
- break;
- default:
- return 0;
- }
-
- switch (str[3])
- {
- case '0':
- def = 0;
- break;
- case 'F':
- def = -1;
- break;
- default:
- return 0;
- }
-
- if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (part_mode))
- return 0;
-
- part = s390_single_part (GEN_INT (value), mode, part_mode, def);
- if (part < 0)
- return 0;
- if (part_goal != -1 && part_goal != part)
- return 0;
-
- return 1;
-}
-
-
-/* Returns true if the input parameter VALUE is a float zero. */
-
-int
-s390_float_const_zero_p (rtx value)
-{
- return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
- && value == CONST0_RTX (GET_MODE (value)));
-}
-
-/* Implement TARGET_REGISTER_MOVE_COST. */
-
-static int
-s390_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
- reg_class_t from, reg_class_t to)
-{
-/* On s390, copy between fprs and gprs is expensive. */
- if ((reg_classes_intersect_p (from, GENERAL_REGS)
- && reg_classes_intersect_p (to, FP_REGS))
- || (reg_classes_intersect_p (from, FP_REGS)
- && reg_classes_intersect_p (to, GENERAL_REGS)))
- return 10;
-
- return 1;
-}
-
-/* Implement TARGET_MEMORY_MOVE_COST. */
-
-static int
-s390_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
- reg_class_t rclass ATTRIBUTE_UNUSED,
- bool in ATTRIBUTE_UNUSED)
-{
- return 1;
-}
-
-/* Compute a (partial) cost for rtx X. Return true if the complete
- cost has been computed, and false if subexpressions should be
- scanned. In either case, *TOTAL contains the cost result.
- CODE contains GET_CODE (x), OUTER_CODE contains the code
- of the superexpression of x. */
-
-static bool
-s390_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
- int *total, bool speed ATTRIBUTE_UNUSED)
-{
- switch (code)
- {
- case CONST:
- case CONST_INT:
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST_DOUBLE:
- case MEM:
- *total = 0;
- return true;
-
- case ASHIFT:
- case ASHIFTRT:
- case LSHIFTRT:
- case ROTATE:
- case ROTATERT:
- case AND:
- case IOR:
- case XOR:
- case NEG:
- case NOT:
- *total = COSTS_N_INSNS (1);
- return false;
-
- case PLUS:
- case MINUS:
- *total = COSTS_N_INSNS (1);
- return false;
-
- case MULT:
- switch (GET_MODE (x))
- {
- case SImode:
- {
- rtx left = XEXP (x, 0);
- rtx right = XEXP (x, 1);
- if (GET_CODE (right) == CONST_INT
- && CONST_OK_FOR_K (INTVAL (right)))
- *total = s390_cost->mhi;
- else if (GET_CODE (left) == SIGN_EXTEND)
- *total = s390_cost->mh;
- else
- *total = s390_cost->ms; /* msr, ms, msy */
- break;
- }
- case DImode:
- {
- rtx left = XEXP (x, 0);
- rtx right = XEXP (x, 1);
- if (TARGET_ZARCH)
- {
- if (GET_CODE (right) == CONST_INT
- && CONST_OK_FOR_K (INTVAL (right)))
- *total = s390_cost->mghi;
- else if (GET_CODE (left) == SIGN_EXTEND)
- *total = s390_cost->msgf;
- else
- *total = s390_cost->msg; /* msgr, msg */
- }
- else /* TARGET_31BIT */
- {
- if (GET_CODE (left) == SIGN_EXTEND
- && GET_CODE (right) == SIGN_EXTEND)
- /* mulsidi case: mr, m */
- *total = s390_cost->m;
- else if (GET_CODE (left) == ZERO_EXTEND
- && GET_CODE (right) == ZERO_EXTEND
- && TARGET_CPU_ZARCH)
- /* umulsidi case: ml, mlr */
- *total = s390_cost->ml;
- else
- /* Complex calculation is required. */
- *total = COSTS_N_INSNS (40);
- }
- break;
- }
- case SFmode:
- case DFmode:
- *total = s390_cost->mult_df;
- break;
- case TFmode:
- *total = s390_cost->mxbr;
- break;
- default:
- return false;
- }
- return false;
-
- case FMA:
- switch (GET_MODE (x))
- {
- case DFmode:
- *total = s390_cost->madbr;
- break;
- case SFmode:
- *total = s390_cost->maebr;
- break;
- default:
- return false;
- }
- /* Negate in the third argument is free: FMSUB. */
- if (GET_CODE (XEXP (x, 2)) == NEG)
- {
- *total += (rtx_cost (XEXP (x, 0), FMA, 0, speed)
- + rtx_cost (XEXP (x, 1), FMA, 1, speed)
- + rtx_cost (XEXP (XEXP (x, 2), 0), FMA, 2, speed));
- return true;
- }
- return false;
-
- case UDIV:
- case UMOD:
- if (GET_MODE (x) == TImode) /* 128 bit division */
- *total = s390_cost->dlgr;
- else if (GET_MODE (x) == DImode)
- {
- rtx right = XEXP (x, 1);
- if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
- *total = s390_cost->dlr;
- else /* 64 by 64 bit division */
- *total = s390_cost->dlgr;
- }
- else if (GET_MODE (x) == SImode) /* 32 bit division */
- *total = s390_cost->dlr;
- return false;
-
- case DIV:
- case MOD:
- if (GET_MODE (x) == DImode)
- {
- rtx right = XEXP (x, 1);
- if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
- if (TARGET_ZARCH)
- *total = s390_cost->dsgfr;
- else
- *total = s390_cost->dr;
- else /* 64 by 64 bit division */
- *total = s390_cost->dsgr;
- }
- else if (GET_MODE (x) == SImode) /* 32 bit division */
- *total = s390_cost->dlr;
- else if (GET_MODE (x) == SFmode)
- {
- *total = s390_cost->debr;
- }
- else if (GET_MODE (x) == DFmode)
- {
- *total = s390_cost->ddbr;
- }
- else if (GET_MODE (x) == TFmode)
- {
- *total = s390_cost->dxbr;
- }
- return false;
-
- case SQRT:
- if (GET_MODE (x) == SFmode)
- *total = s390_cost->sqebr;
- else if (GET_MODE (x) == DFmode)
- *total = s390_cost->sqdbr;
- else /* TFmode */
- *total = s390_cost->sqxbr;
- return false;
-
- case SIGN_EXTEND:
- case ZERO_EXTEND:
- if (outer_code == MULT || outer_code == DIV || outer_code == MOD
- || outer_code == PLUS || outer_code == MINUS
- || outer_code == COMPARE)
- *total = 0;
- return false;
-
- case COMPARE:
- *total = COSTS_N_INSNS (1);
- if (GET_CODE (XEXP (x, 0)) == AND
- && GET_CODE (XEXP (x, 1)) == CONST_INT
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
- {
- rtx op0 = XEXP (XEXP (x, 0), 0);
- rtx op1 = XEXP (XEXP (x, 0), 1);
- rtx op2 = XEXP (x, 1);
-
- if (memory_operand (op0, GET_MODE (op0))
- && s390_tm_ccmode (op1, op2, 0) != VOIDmode)
- return true;
- if (register_operand (op0, GET_MODE (op0))
- && s390_tm_ccmode (op1, op2, 1) != VOIDmode)
- return true;
- }
- return false;
-
- default:
- return false;
- }
-}
-
-/* Return the cost of an address rtx ADDR. */
-
-static int
-s390_address_cost (rtx addr, bool speed ATTRIBUTE_UNUSED)
-{
- struct s390_address ad;
- if (!s390_decompose_address (addr, &ad))
- return 1000;
-
- return ad.indx? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (1);
-}
-
-/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
- otherwise return 0. */
-
-int
-tls_symbolic_operand (rtx op)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
- return SYMBOL_REF_TLS_MODEL (op);
-}
-
-/* Split DImode access register reference REG (on 64-bit) into its constituent
- low and high parts, and store them into LO and HI. Note that gen_lowpart/
- gen_highpart cannot be used as they assume all registers are word-sized,
- while our access registers have only half that size. */
-
-void
-s390_split_access_reg (rtx reg, rtx *lo, rtx *hi)
-{
- gcc_assert (TARGET_64BIT);
- gcc_assert (ACCESS_REG_P (reg));
- gcc_assert (GET_MODE (reg) == DImode);
- gcc_assert (!(REGNO (reg) & 1));
-
- *lo = gen_rtx_REG (SImode, REGNO (reg) + 1);
- *hi = gen_rtx_REG (SImode, REGNO (reg));
-}
-
-/* Return true if OP contains a symbol reference */
-
-bool
-symbolic_reference_mentioned_p (rtx op)
-{
- const char *fmt;
- int i;
-
- if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
- return 1;
-
- fmt = GET_RTX_FORMAT (GET_CODE (op));
- for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'E')
- {
- int j;
-
- for (j = XVECLEN (op, i) - 1; j >= 0; j--)
- if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
- return 1;
- }
-
- else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
- return 1;
- }
-
- return 0;
-}
-
-/* Return true if OP contains a reference to a thread-local symbol. */
-
-bool
-tls_symbolic_reference_mentioned_p (rtx op)
-{
- const char *fmt;
- int i;
-
- if (GET_CODE (op) == SYMBOL_REF)
- return tls_symbolic_operand (op);
-
- fmt = GET_RTX_FORMAT (GET_CODE (op));
- for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'E')
- {
- int j;
-
- for (j = XVECLEN (op, i) - 1; j >= 0; j--)
- if (tls_symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
- return true;
- }
-
- else if (fmt[i] == 'e' && tls_symbolic_reference_mentioned_p (XEXP (op, i)))
- return true;
- }
-
- return false;
-}
-
-
-/* Return true if OP is a legitimate general operand when
- generating PIC code. It is given that flag_pic is on
- and that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
-
-int
-legitimate_pic_operand_p (rtx op)
-{
- /* Accept all non-symbolic constants. */
- if (!SYMBOLIC_CONST (op))
- return 1;
-
- /* Reject everything else; must be handled
- via emit_symbolic_move. */
- return 0;
-}
-
-/* Returns true if the constant value OP is a legitimate general operand.
- It is given that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
-
-static bool
-s390_legitimate_constant_p (enum machine_mode mode, rtx op)
-{
- /* Accept all non-symbolic constants. */
- if (!SYMBOLIC_CONST (op))
- return 1;
-
- /* Accept immediate LARL operands. */
- if (TARGET_CPU_ZARCH && larl_operand (op, mode))
- return 1;
-
- /* Thread-local symbols are never legal constants. This is
- so that emit_call knows that computing such addresses
- might require a function call. */
- if (TLS_SYMBOLIC_CONST (op))
- return 0;
-
- /* In the PIC case, symbolic constants must *not* be
- forced into the literal pool. We accept them here,
- so that they will be handled by emit_symbolic_move. */
- if (flag_pic)
- return 1;
-
- /* All remaining non-PIC symbolic constants are
- forced into the literal pool. */
- return 0;
-}
-
-/* Determine if it's legal to put X into the constant pool. This
- is not possible if X contains the address of a symbol that is
- not constant (TLS) or not known at final link time (PIC). */
-
-static bool
-s390_cannot_force_const_mem (enum machine_mode mode, rtx x)
-{
- switch (GET_CODE (x))
- {
- case CONST_INT:
- case CONST_DOUBLE:
- /* Accept all non-symbolic constants. */
- return false;
-
- case LABEL_REF:
- /* Labels are OK iff we are non-PIC. */
- return flag_pic != 0;
-
- case SYMBOL_REF:
- /* 'Naked' TLS symbol references are never OK,
- non-TLS symbols are OK iff we are non-PIC. */
- if (tls_symbolic_operand (x))
- return true;
- else
- return flag_pic != 0;
-
- case CONST:
- return s390_cannot_force_const_mem (mode, XEXP (x, 0));
- case PLUS:
- case MINUS:
- return s390_cannot_force_const_mem (mode, XEXP (x, 0))
- || s390_cannot_force_const_mem (mode, XEXP (x, 1));
-
- case UNSPEC:
- switch (XINT (x, 1))
- {
- /* Only lt-relative or GOT-relative UNSPECs are OK. */
- case UNSPEC_LTREL_OFFSET:
- case UNSPEC_GOT:
- case UNSPEC_GOTOFF:
- case UNSPEC_PLTOFF:
- case UNSPEC_TLSGD:
- case UNSPEC_TLSLDM:
- case UNSPEC_NTPOFF:
- case UNSPEC_DTPOFF:
- case UNSPEC_GOTNTPOFF:
- 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;
- }
- break;
-
- default:
- gcc_unreachable ();
- }
-}
-
-/* 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.
- This function accepts all constants which can be loaded directly
- into a GPR. */
-
-bool
-legitimate_reload_constant_p (rtx op)
-{
- /* Accept la(y) operands. */
- if (GET_CODE (op) == CONST_INT
- && DISP_IN_RANGE (INTVAL (op)))
- return true;
-
- /* Accept l(g)hi/l(g)fi operands. */
- if (GET_CODE (op) == CONST_INT
- && (CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_Os (INTVAL (op))))
- return true;
-
- /* Accept lliXX operands. */
- if (TARGET_ZARCH
- && GET_CODE (op) == CONST_INT
- && trunc_int_for_mode (INTVAL (op), word_mode) == INTVAL (op)
- && s390_single_part (op, word_mode, HImode, 0) >= 0)
- return true;
-
- if (TARGET_EXTIMM
- && GET_CODE (op) == CONST_INT
- && trunc_int_for_mode (INTVAL (op), word_mode) == INTVAL (op)
- && s390_single_part (op, word_mode, SImode, 0) >= 0)
- return true;
-
- /* Accept larl operands. */
- if (TARGET_CPU_ZARCH
- && larl_operand (op, VOIDmode))
- return true;
-
- /* Accept floating-point zero operands that fit into a single GPR. */
- if (GET_CODE (op) == CONST_DOUBLE
- && s390_float_const_zero_p (op)
- && GET_MODE_SIZE (GET_MODE (op)) <= UNITS_PER_WORD)
- return true;
-
- /* Accept double-word operands that can be split. */
- if (GET_CODE (op) == CONST_INT
- && trunc_int_for_mode (INTVAL (op), word_mode) != INTVAL (op))
- {
- enum machine_mode dword_mode = word_mode == SImode ? DImode : TImode;
- rtx hi = operand_subword (op, 0, 0, dword_mode);
- rtx lo = operand_subword (op, 1, 0, dword_mode);
- return legitimate_reload_constant_p (hi)
- && legitimate_reload_constant_p (lo);
- }
-
- /* Everything else cannot be handled without reload. */
- return false;
-}
-
-/* Returns true if the constant value OP is a legitimate fp operand
- during and after reload.
- This function accepts all constants which can be loaded directly
- into an FPR. */
-
-static bool
-legitimate_reload_fp_constant_p (rtx op)
-{
- /* Accept floating-point zero operands if the load zero instruction
- can be used. */
- if (TARGET_Z196
- && GET_CODE (op) == CONST_DOUBLE
- && s390_float_const_zero_p (op))
- return true;
-
- return false;
-}
-
-/* Given an rtx OP being reloaded into a reg required to be in class RCLASS,
- return the class of reg to actually use. */
-
-static reg_class_t
-s390_preferred_reload_class (rtx op, reg_class_t rclass)
-{
- switch (GET_CODE (op))
- {
- /* Constants we cannot reload into general registers
- must be forced into the literal pool. */
- case CONST_DOUBLE:
- case CONST_INT:
- if (reg_class_subset_p (GENERAL_REGS, rclass)
- && legitimate_reload_constant_p (op))
- return GENERAL_REGS;
- else if (reg_class_subset_p (ADDR_REGS, rclass)
- && legitimate_reload_constant_p (op))
- return ADDR_REGS;
- else if (reg_class_subset_p (FP_REGS, rclass)
- && legitimate_reload_fp_constant_p (op))
- return FP_REGS;
- return NO_REGS;
-
- /* If a symbolic constant or a PLUS is reloaded,
- it is most likely being used as an address, so
- prefer ADDR_REGS. If 'class' is not a superset
- of ADDR_REGS, e.g. FP_REGS, reject this reload. */
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST:
- if (!legitimate_reload_constant_p (op))
- return NO_REGS;
- /* fallthrough */
- case PLUS:
- /* load address will be used. */
- if (reg_class_subset_p (ADDR_REGS, rclass))
- return ADDR_REGS;
- else
- return NO_REGS;
-
- default:
- break;
- }
-
- return rclass;
-}
-
-/* Return true if ADDR is SYMBOL_REF + addend with addend being a
- multiple of ALIGNMENT and the SYMBOL_REF being naturally
- aligned. */
-
-bool
-s390_check_symref_alignment (rtx addr, HOST_WIDE_INT alignment)
-{
- HOST_WIDE_INT addend;
- rtx symref;
-
- if (!s390_symref_operand_p (addr, &symref, &addend))
- return false;
-
- return (!SYMBOL_REF_NOT_NATURALLY_ALIGNED_P (symref)
- && !(addend & (alignment - 1)));
-}
-
-/* ADDR is moved into REG using larl. If ADDR isn't a valid larl
- operand SCRATCH is used to reload the even part of the address and
- adding one. */
-
-void
-s390_reload_larl_operand (rtx reg, rtx addr, rtx scratch)
-{
- HOST_WIDE_INT addend;
- rtx symref;
-
- if (!s390_symref_operand_p (addr, &symref, &addend))
- gcc_unreachable ();
-
- if (!(addend & 1))
- /* Easy case. The addend is even so larl will do fine. */
- emit_move_insn (reg, addr);
- else
- {
- /* We can leave the scratch register untouched if the target
- register is a valid base register. */
- if (REGNO (reg) < FIRST_PSEUDO_REGISTER
- && REGNO_REG_CLASS (REGNO (reg)) == ADDR_REGS)
- scratch = reg;
-
- gcc_assert (REGNO (scratch) < FIRST_PSEUDO_REGISTER);
- gcc_assert (REGNO_REG_CLASS (REGNO (scratch)) == ADDR_REGS);
-
- if (addend != 1)
- emit_move_insn (scratch,
- gen_rtx_CONST (Pmode,
- gen_rtx_PLUS (Pmode, symref,
- GEN_INT (addend - 1))));
- else
- emit_move_insn (scratch, symref);
-
- /* Increment the address using la in order to avoid clobbering cc. */
- emit_move_insn (reg, gen_rtx_PLUS (Pmode, scratch, const1_rtx));
- }
-}
-
-/* Generate what is necessary to move between REG and MEM using
- SCRATCH. The direction is given by TOMEM. */
-
-void
-s390_reload_symref_address (rtx reg, rtx mem, rtx scratch, bool tomem)
-{
- /* Reload might have pulled a constant out of the literal pool.
- Force it back in. */
- if (CONST_INT_P (mem) || GET_CODE (mem) == CONST_DOUBLE
- || GET_CODE (mem) == CONST)
- mem = force_const_mem (GET_MODE (reg), mem);
-
- gcc_assert (MEM_P (mem));
-
- /* For a load from memory we can leave the scratch register
- untouched if the target register is a valid base register. */
- if (!tomem
- && REGNO (reg) < FIRST_PSEUDO_REGISTER
- && REGNO_REG_CLASS (REGNO (reg)) == ADDR_REGS
- && GET_MODE (reg) == GET_MODE (scratch))
- scratch = reg;
-
- /* Load address into scratch register. Since we can't have a
- secondary reload for a secondary reload we have to cover the case
- where larl would need a secondary reload here as well. */
- s390_reload_larl_operand (scratch, XEXP (mem, 0), scratch);
-
- /* Now we can use a standard load/store to do the move. */
- if (tomem)
- emit_move_insn (replace_equiv_address (mem, scratch), reg);
- else
- emit_move_insn (reg, replace_equiv_address (mem, scratch));
-}
-
-/* Inform reload about cases where moving X with a mode MODE to a register in
- RCLASS requires an extra scratch or immediate register. Return the class
- needed for the immediate register. */
-
-static reg_class_t
-s390_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
- enum machine_mode mode, secondary_reload_info *sri)
-{
- enum reg_class rclass = (enum reg_class) rclass_i;
-
- /* Intermediate register needed. */
- if (reg_classes_intersect_p (CC_REGS, rclass))
- return GENERAL_REGS;
-
- if (TARGET_Z10)
- {
- HOST_WIDE_INT offset;
- rtx symref;
-
- /* On z10 several optimizer steps may generate larl operands with
- an odd addend. */
- if (in_p
- && s390_symref_operand_p (x, &symref, &offset)
- && mode == Pmode
- && !SYMBOL_REF_ALIGN1_P (symref)
- && (offset & 1) == 1)
- sri->icode = ((mode == DImode) ? CODE_FOR_reloaddi_larl_odd_addend_z10
- : CODE_FOR_reloadsi_larl_odd_addend_z10);
-
- /* On z10 we need a scratch register when moving QI, TI or floating
- point mode values from or to a memory location with a SYMBOL_REF
- or if the symref addend of a SI or DI move is not aligned to the
- width of the access. */
- if (MEM_P (x)
- && s390_symref_operand_p (XEXP (x, 0), NULL, NULL)
- && (mode == QImode || mode == TImode || FLOAT_MODE_P (mode)
- || (!TARGET_ZARCH && mode == DImode)
- || ((mode == HImode || mode == SImode || mode == DImode)
- && (!s390_check_symref_alignment (XEXP (x, 0),
- GET_MODE_SIZE (mode))))))
- {
-#define __SECONDARY_RELOAD_CASE(M,m) \
- case M##mode: \
- if (TARGET_64BIT) \
- sri->icode = in_p ? CODE_FOR_reload##m##di_toreg_z10 : \
- CODE_FOR_reload##m##di_tomem_z10; \
- else \
- sri->icode = in_p ? CODE_FOR_reload##m##si_toreg_z10 : \
- CODE_FOR_reload##m##si_tomem_z10; \
- break;
-
- switch (GET_MODE (x))
- {
- __SECONDARY_RELOAD_CASE (QI, qi);
- __SECONDARY_RELOAD_CASE (HI, hi);
- __SECONDARY_RELOAD_CASE (SI, si);
- __SECONDARY_RELOAD_CASE (DI, di);
- __SECONDARY_RELOAD_CASE (TI, ti);
- __SECONDARY_RELOAD_CASE (SF, sf);
- __SECONDARY_RELOAD_CASE (DF, df);
- __SECONDARY_RELOAD_CASE (TF, tf);
- __SECONDARY_RELOAD_CASE (SD, sd);
- __SECONDARY_RELOAD_CASE (DD, dd);
- __SECONDARY_RELOAD_CASE (TD, td);
-
- default:
- gcc_unreachable ();
- }
-#undef __SECONDARY_RELOAD_CASE
- }
- }
-
- /* We need a scratch register when loading a PLUS expression which
- is not a legitimate operand of the LOAD ADDRESS instruction. */
- if (in_p && s390_plus_operand (x, mode))
- sri->icode = (TARGET_64BIT ?
- CODE_FOR_reloaddi_plus : CODE_FOR_reloadsi_plus);
-
- /* Performing a multiword move from or to memory we have to make sure the
- second chunk in memory is addressable without causing a displacement
- overflow. If that would be the case we calculate the address in
- a scratch register. */
- if (MEM_P (x)
- && GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
- && !DISP_IN_RANGE (INTVAL (XEXP (XEXP (x, 0), 1))
- + GET_MODE_SIZE (mode) - 1))
- {
- /* For GENERAL_REGS a displacement overflow is no problem if occurring
- in a s_operand address since we may fallback to lm/stm. So we only
- have to care about overflows in the b+i+d case. */
- if ((reg_classes_intersect_p (GENERAL_REGS, rclass)
- && s390_class_max_nregs (GENERAL_REGS, mode) > 1
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
- /* For FP_REGS no lm/stm is available so this check is triggered
- for displacement overflows in b+i+d and b+d like addresses. */
- || (reg_classes_intersect_p (FP_REGS, rclass)
- && s390_class_max_nregs (FP_REGS, mode) > 1))
- {
- if (in_p)
- sri->icode = (TARGET_64BIT ?
- CODE_FOR_reloaddi_nonoffmem_in :
- CODE_FOR_reloadsi_nonoffmem_in);
- else
- sri->icode = (TARGET_64BIT ?
- CODE_FOR_reloaddi_nonoffmem_out :
- CODE_FOR_reloadsi_nonoffmem_out);
- }
- }
-
- /* A scratch address register is needed when a symbolic constant is
- copied to r0 compiling with -fPIC. In other cases the target
- register might be used as temporary (see legitimize_pic_address). */
- if (in_p && SYMBOLIC_CONST (x) && flag_pic == 2 && rclass != ADDR_REGS)
- sri->icode = (TARGET_64BIT ?
- CODE_FOR_reloaddi_PIC_addr :
- CODE_FOR_reloadsi_PIC_addr);
-
- /* Either scratch or no register needed. */
- return NO_REGS;
-}
-
-/* Generate code to load SRC, which is PLUS that is not a
- legitimate operand for the LA instruction, into TARGET.
- SCRATCH may be used as scratch register. */
-
-void
-s390_expand_plus_operand (rtx target, rtx src,
- rtx scratch)
-{
- rtx sum1, sum2;
- struct s390_address ad;
-
- /* src must be a PLUS; get its two operands. */
- gcc_assert (GET_CODE (src) == PLUS);
- gcc_assert (GET_MODE (src) == Pmode);
-
- /* Check if any of the two operands is already scheduled
- for replacement by reload. This can happen e.g. when
- float registers occur in an address. */
- sum1 = find_replacement (&XEXP (src, 0));
- sum2 = find_replacement (&XEXP (src, 1));
- src = gen_rtx_PLUS (Pmode, sum1, sum2);
-
- /* If the address is already strictly valid, there's nothing to do. */
- if (!s390_decompose_address (src, &ad)
- || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
- || (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
- {
- /* Otherwise, one of the operands cannot be an address register;
- we reload its value into the scratch register. */
- if (true_regnum (sum1) < 1 || true_regnum (sum1) > 15)
- {
- emit_move_insn (scratch, sum1);
- sum1 = scratch;
- }
- if (true_regnum (sum2) < 1 || true_regnum (sum2) > 15)
- {
- emit_move_insn (scratch, sum2);
- sum2 = scratch;
- }
-
- /* According to the way these invalid addresses are generated
- in reload.c, it should never happen (at least on s390) that
- *neither* of the PLUS components, after find_replacements
- was applied, is an address register. */
- if (sum1 == scratch && sum2 == scratch)
- {
- debug_rtx (src);
- gcc_unreachable ();
- }
-
- src = gen_rtx_PLUS (Pmode, sum1, sum2);
- }
-
- /* Emit the LOAD ADDRESS pattern. Note that reload of PLUS
- is only ever performed on addresses, so we can mark the
- sum as legitimate for LA in any case. */
- s390_load_address (target, src);
-}
-
-
-/* Return true if ADDR is a valid memory address.
- STRICT specifies whether strict register checking applies. */
-
-static bool
-s390_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
-{
- struct s390_address ad;
-
- if (TARGET_Z10
- && larl_operand (addr, VOIDmode)
- && (mode == VOIDmode
- || s390_check_symref_alignment (addr, GET_MODE_SIZE (mode))))
- return true;
-
- if (!s390_decompose_address (addr, &ad))
- return false;
-
- if (strict)
- {
- if (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
- return false;
-
- if (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx)))
- return false;
- }
- else
- {
- if (ad.base
- && !(REGNO (ad.base) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (ad.base)) == ADDR_REGS))
- return false;
-
- if (ad.indx
- && !(REGNO (ad.indx) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (ad.indx)) == ADDR_REGS))
- return false;
- }
- return true;
-}
-
-/* Return true if OP is a valid operand for the LA instruction.
- In 31-bit, we need to prove that the result is used as an
- address, as LA performs only a 31-bit addition. */
-
-bool
-legitimate_la_operand_p (rtx op)
-{
- struct s390_address addr;
- if (!s390_decompose_address (op, &addr))
- return false;
-
- return (TARGET_64BIT || addr.pointer);
-}
-
-/* Return true if it is valid *and* preferable to use LA to
- compute the sum of OP1 and OP2. */
-
-bool
-preferred_la_operand_p (rtx op1, rtx op2)
-{
- struct s390_address addr;
-
- if (op2 != const0_rtx)
- op1 = gen_rtx_PLUS (Pmode, op1, op2);
-
- if (!s390_decompose_address (op1, &addr))
- return false;
- if (addr.base && !REGNO_OK_FOR_BASE_P (REGNO (addr.base)))
- return false;
- if (addr.indx && !REGNO_OK_FOR_INDEX_P (REGNO (addr.indx)))
- return false;
-
- /* Avoid LA instructions with index register on z196; it is
- preferable to use regular add instructions when possible. */
- if (addr.indx && s390_tune == PROCESSOR_2817_Z196)
- return false;
-
- if (!TARGET_64BIT && !addr.pointer)
- return false;
-
- if (addr.pointer)
- return true;
-
- if ((addr.base && REG_P (addr.base) && REG_POINTER (addr.base))
- || (addr.indx && REG_P (addr.indx) && REG_POINTER (addr.indx)))
- return true;
-
- return false;
-}
-
-/* Emit a forced load-address operation to load SRC into DST.
- This will use the LOAD ADDRESS instruction even in situations
- where legitimate_la_operand_p (SRC) returns false. */
-
-void
-s390_load_address (rtx dst, rtx src)
-{
- if (TARGET_64BIT)
- emit_move_insn (dst, src);
- else
- emit_insn (gen_force_la_31 (dst, src));
-}
-
-/* Return a legitimate reference for ORIG (an address) using the
- register REG. If REG is 0, a new pseudo is generated.
-
- There are two types of references that must be handled:
-
- 1. Global data references must load the address from the GOT, via
- the PIC reg. An insn is emitted to do this load, and the reg is
- returned.
-
- 2. Static data references, constant pool addresses, and code labels
- compute the address as an offset from the GOT, whose base is in
- the PIC reg. Static data objects have SYMBOL_FLAG_LOCAL set to
- differentiate them from global data objects. The returned
- address is the PIC reg + an unspec constant.
-
- TARGET_LEGITIMIZE_ADDRESS_P rejects symbolic references unless the PIC
- reg also appears in the address. */
-
-rtx
-legitimize_pic_address (rtx orig, rtx reg)
-{
- rtx addr = orig;
- rtx new_rtx = orig;
- rtx base;
-
- gcc_assert (!TLS_SYMBOLIC_CONST (addr));
-
- if (GET_CODE (addr) == LABEL_REF
- || (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr)))
- {
- /* This is a local symbol. */
- if (TARGET_CPU_ZARCH && larl_operand (addr, VOIDmode))
- {
- /* Access local symbols PC-relative via LARL.
- This is the same as in the non-PIC case, so it is
- handled automatically ... */
- }
- else
- {
- /* Access local symbols relative to the GOT. */
-
- rtx temp = reg? reg : gen_reg_rtx (Pmode);
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF);
- addr = gen_rtx_CONST (Pmode, addr);
- addr = force_const_mem (Pmode, addr);
- emit_move_insn (temp, addr);
-
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- }
- }
- else if (GET_CODE (addr) == SYMBOL_REF)
- {
- if (reg == 0)
- reg = gen_reg_rtx (Pmode);
-
- if (flag_pic == 1)
- {
- /* Assume GOT offset < 4k. This is handled the same way
- in both 31- and 64-bit code (@GOT). */
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
- new_rtx = gen_const_mem (Pmode, new_rtx);
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
- }
- else if (TARGET_CPU_ZARCH)
- {
- /* If the GOT offset might be >= 4k, we determine the position
- of the GOT entry via a PC-relative LARL (@GOTENT). */
-
- rtx temp = reg ? reg : gen_reg_rtx (Pmode);
-
- gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = gen_const_mem (Pmode, temp);
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
- }
- else
- {
- /* If the GOT offset might be >= 4k, we have to load it
- from the literal pool (@GOT). */
-
- rtx temp = reg ? reg : gen_reg_rtx (Pmode);
-
- gcc_assert (REGNO (temp) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (temp)) == ADDR_REGS);
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
- addr = gen_rtx_CONST (Pmode, addr);
- addr = force_const_mem (Pmode, addr);
- emit_move_insn (temp, addr);
-
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- new_rtx = gen_const_mem (Pmode, new_rtx);
- emit_move_insn (reg, new_rtx);
- new_rtx = reg;
- }
- }
- else
- {
- if (GET_CODE (addr) == CONST)
- {
- addr = XEXP (addr, 0);
- if (GET_CODE (addr) == UNSPEC)
- {
- gcc_assert (XVECLEN (addr, 0) == 1);
- switch (XINT (addr, 1))
- {
- /* If someone moved a GOT-relative UNSPEC
- out of the literal pool, force them back in. */
- case UNSPEC_GOTOFF:
- case UNSPEC_PLTOFF:
- new_rtx = force_const_mem (Pmode, orig);
- break;
-
- /* @GOT is OK as is if small. */
- case UNSPEC_GOT:
- if (flag_pic == 2)
- new_rtx = force_const_mem (Pmode, orig);
- break;
-
- /* @GOTENT is OK as is. */
- case UNSPEC_GOTENT:
- break;
-
- /* @PLT is OK as is on 64-bit, must be converted to
- GOT-relative @PLTOFF on 31-bit. */
- case UNSPEC_PLT:
- if (!TARGET_CPU_ZARCH)
- {
- rtx temp = reg? reg : gen_reg_rtx (Pmode);
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- addr = XVECEXP (addr, 0, 0);
- addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
- UNSPEC_PLTOFF);
- addr = gen_rtx_CONST (Pmode, addr);
- addr = force_const_mem (Pmode, addr);
- emit_move_insn (temp, addr);
-
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- }
- break;
-
- /* Everything else cannot happen. */
- default:
- gcc_unreachable ();
- }
- }
- else
- gcc_assert (GET_CODE (addr) == PLUS);
- }
- if (GET_CODE (addr) == PLUS)
- {
- rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
-
- gcc_assert (!TLS_SYMBOLIC_CONST (op0));
- gcc_assert (!TLS_SYMBOLIC_CONST (op1));
-
- /* Check first to see if this is a constant offset
- from a local symbol reference. */
- if ((GET_CODE (op0) == LABEL_REF
- || (GET_CODE (op0) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (op0)))
- && GET_CODE (op1) == CONST_INT)
- {
- if (TARGET_CPU_ZARCH
- && larl_operand (op0, VOIDmode)
- && INTVAL (op1) < (HOST_WIDE_INT)1 << 31
- && INTVAL (op1) >= -((HOST_WIDE_INT)1 << 31))
- {
- if (INTVAL (op1) & 1)
- {
- /* LARL can't handle odd offsets, so emit a
- pair of LARL and LA. */
- rtx temp = reg? reg : gen_reg_rtx (Pmode);
-
- if (!DISP_IN_RANGE (INTVAL (op1)))
- {
- HOST_WIDE_INT even = INTVAL (op1) - 1;
- op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
- op0 = gen_rtx_CONST (Pmode, op0);
- op1 = const1_rtx;
- }
-
- emit_move_insn (temp, op0);
- new_rtx = gen_rtx_PLUS (Pmode, temp, op1);
-
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- }
- else
- {
- /* If the offset is even, we can just use LARL.
- This will happen automatically. */
- }
- }
- else
- {
- /* Access local symbols relative to the GOT. */
-
- rtx temp = reg? reg : gen_reg_rtx (Pmode);
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0),
- UNSPEC_GOTOFF);
- addr = gen_rtx_PLUS (Pmode, addr, op1);
- addr = gen_rtx_CONST (Pmode, addr);
- addr = force_const_mem (Pmode, addr);
- emit_move_insn (temp, addr);
-
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- }
- }
-
- /* Now, check whether it is a GOT relative symbol plus offset
- that was pulled out of the literal pool. Force it back in. */
-
- else if (GET_CODE (op0) == UNSPEC
- && GET_CODE (op1) == CONST_INT
- && XINT (op0, 1) == UNSPEC_GOTOFF)
- {
- gcc_assert (XVECLEN (op0, 0) == 1);
-
- new_rtx = force_const_mem (Pmode, orig);
- }
-
- /* Otherwise, compute the sum. */
- else
- {
- base = legitimize_pic_address (XEXP (addr, 0), reg);
- new_rtx = legitimize_pic_address (XEXP (addr, 1),
- base == reg ? NULL_RTX : reg);
- if (GET_CODE (new_rtx) == CONST_INT)
- new_rtx = plus_constant (base, INTVAL (new_rtx));
- else
- {
- if (GET_CODE (new_rtx) == PLUS && CONSTANT_P (XEXP (new_rtx, 1)))
- {
- base = gen_rtx_PLUS (Pmode, base, XEXP (new_rtx, 0));
- new_rtx = XEXP (new_rtx, 1);
- }
- new_rtx = gen_rtx_PLUS (Pmode, base, new_rtx);
- }
-
- if (GET_CODE (new_rtx) == CONST)
- new_rtx = XEXP (new_rtx, 0);
- new_rtx = force_operand (new_rtx, 0);
- }
- }
- }
- return new_rtx;
-}
-
-/* Load the thread pointer into a register. */
-
-rtx
-s390_get_thread_pointer (void)
-{
- rtx tp = gen_reg_rtx (Pmode);
-
- emit_move_insn (tp, gen_rtx_REG (Pmode, TP_REGNUM));
- mark_reg_pointer (tp, BITS_PER_WORD);
-
- return tp;
-}
-
-/* Emit a tls call insn. The call target is the SYMBOL_REF stored
- in s390_tls_symbol which always refers to __tls_get_offset.
- The returned offset is written to RESULT_REG and an USE rtx is
- generated for TLS_CALL. */
-
-static GTY(()) rtx s390_tls_symbol;
-
-static void
-s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
-{
- rtx insn;
-
- if (!flag_pic)
- emit_insn (s390_load_got ());
-
- if (!s390_tls_symbol)
- s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset");
-
- insn = s390_emit_call (s390_tls_symbol, tls_call, result_reg,
- gen_rtx_REG (Pmode, RETURN_REGNUM));
-
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), result_reg);
- RTL_CONST_CALL_P (insn) = 1;
-}
-
-/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
- this (thread-local) address. REG may be used as temporary. */
-
-static rtx
-legitimize_tls_address (rtx addr, rtx reg)
-{
- rtx new_rtx, tls_call, temp, base, r2, insn;
-
- if (GET_CODE (addr) == SYMBOL_REF)
- switch (tls_symbolic_operand (addr))
- {
- case TLS_MODEL_GLOBAL_DYNAMIC:
- start_sequence ();
- r2 = gen_rtx_REG (Pmode, 2);
- tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_TLSGD);
- new_rtx = gen_rtx_CONST (Pmode, tls_call);
- new_rtx = force_const_mem (Pmode, new_rtx);
- emit_move_insn (r2, new_rtx);
- s390_emit_tls_call_insn (r2, tls_call);
- insn = get_insns ();
- end_sequence ();
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);
- temp = gen_reg_rtx (Pmode);
- emit_libcall_block (insn, temp, r2, new_rtx);
-
- new_rtx = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- break;
-
- case TLS_MODEL_LOCAL_DYNAMIC:
- start_sequence ();
- r2 = gen_rtx_REG (Pmode, 2);
- tls_call = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM);
- new_rtx = gen_rtx_CONST (Pmode, tls_call);
- new_rtx = force_const_mem (Pmode, new_rtx);
- emit_move_insn (r2, new_rtx);
- s390_emit_tls_call_insn (r2, tls_call);
- insn = get_insns ();
- end_sequence ();
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TLSLDM_NTPOFF);
- temp = gen_reg_rtx (Pmode);
- emit_libcall_block (insn, temp, r2, new_rtx);
-
- new_rtx = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
- base = gen_reg_rtx (Pmode);
- s390_load_address (base, new_rtx);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_DTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = force_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = gen_rtx_PLUS (Pmode, base, temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- break;
-
- case TLS_MODEL_INITIAL_EXEC:
- if (flag_pic == 1)
- {
- /* Assume GOT offset < 4k. This is handled the same way
- in both 31- and 64-bit code. */
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new_rtx);
- new_rtx = gen_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
- }
- else if (TARGET_CPU_ZARCH)
- {
- /* If the GOT offset might be >= 4k, we determine the position
- of the GOT entry via a PC-relative LARL. */
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = gen_const_mem (Pmode, temp);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
- }
- else if (flag_pic)
- {
- /* If the GOT offset might be >= 4k, we have to load it
- from the literal pool. */
-
- if (reload_in_progress || reload_completed)
- df_set_regs_ever_live (PIC_OFFSET_TABLE_REGNUM, true);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = force_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- new_rtx = gen_const_mem (Pmode, new_rtx);
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new_rtx, addr), UNSPEC_TLS_LOAD);
- temp = gen_reg_rtx (Pmode);
- emit_insn (gen_rtx_SET (Pmode, temp, new_rtx));
- }
- else
- {
- /* In position-dependent code, load the absolute address of
- the GOT entry from the literal pool. */
-
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_INDNTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = force_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = temp;
- new_rtx = gen_const_mem (Pmode, new_rtx);
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new_rtx, addr), UNSPEC_TLS_LOAD);
- temp = gen_reg_rtx (Pmode);
- emit_insn (gen_rtx_SET (Pmode, temp, new_rtx));
- }
-
- new_rtx = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- break;
-
- case TLS_MODEL_LOCAL_EXEC:
- new_rtx = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_NTPOFF);
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
- new_rtx = force_const_mem (Pmode, new_rtx);
- temp = gen_reg_rtx (Pmode);
- emit_move_insn (temp, new_rtx);
-
- new_rtx = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
- if (reg != 0)
- {
- s390_load_address (reg, new_rtx);
- new_rtx = reg;
- }
- break;
-
- default:
- gcc_unreachable ();
- }
-
- else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == UNSPEC)
- {
- switch (XINT (XEXP (addr, 0), 1))
- {
- case UNSPEC_INDNTPOFF:
- gcc_assert (TARGET_CPU_ZARCH);
- new_rtx = addr;
- break;
-
- default:
- gcc_unreachable ();
- }
- }
-
- else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
- {
- new_rtx = XEXP (XEXP (addr, 0), 0);
- if (GET_CODE (new_rtx) != SYMBOL_REF)
- new_rtx = gen_rtx_CONST (Pmode, new_rtx);
-
- new_rtx = legitimize_tls_address (new_rtx, reg);
- new_rtx = plus_constant (new_rtx, INTVAL (XEXP (XEXP (addr, 0), 1)));
- new_rtx = force_operand (new_rtx, 0);
- }
-
- else
- gcc_unreachable (); /* for now ... */
-
- return new_rtx;
-}
-
-/* Emit insns making the address in operands[1] valid for a standard
- move to operands[0]. operands[1] is replaced by an address which
- should be used instead of the former RTX to emit the move
- pattern. */
-
-void
-emit_symbolic_move (rtx *operands)
-{
- rtx temp = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (Pmode, operands[1]);
- else if (TLS_SYMBOLIC_CONST (operands[1]))
- operands[1] = legitimize_tls_address (operands[1], temp);
- else if (flag_pic)
- operands[1] = legitimize_pic_address (operands[1], temp);
-}
-
-/* Try machine-dependent ways of modifying an illegitimate address X
- to be legitimate. If we find one, return the new, valid address.
-
- OLDX is the address as it was before break_out_memory_refs was called.
- In some cases it is useful to look at this to decide what needs to be done.
-
- MODE is the mode of the operand pointed to by X.
-
- When -fpic is used, special handling is needed for symbolic references.
- See comments by legitimize_pic_address for details. */
-
-static rtx
-s390_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- rtx constant_term = const0_rtx;
-
- if (TLS_SYMBOLIC_CONST (x))
- {
- x = legitimize_tls_address (x, 0);
-
- if (s390_legitimate_address_p (mode, x, FALSE))
- return x;
- }
- else if (GET_CODE (x) == PLUS
- && (TLS_SYMBOLIC_CONST (XEXP (x, 0))
- || TLS_SYMBOLIC_CONST (XEXP (x, 1))))
- {
- return x;
- }
- else if (flag_pic)
- {
- if (SYMBOLIC_CONST (x)
- || (GET_CODE (x) == PLUS
- && (SYMBOLIC_CONST (XEXP (x, 0))
- || SYMBOLIC_CONST (XEXP (x, 1)))))
- x = legitimize_pic_address (x, 0);
-
- if (s390_legitimate_address_p (mode, x, FALSE))
- return x;
- }
-
- x = eliminate_constant_term (x, &constant_term);
-
- /* Optimize loading of large displacements by splitting them
- into the multiple of 4K and the rest; this allows the
- former to be CSE'd if possible.
-
- Don't do this if the displacement is added to a register
- pointing into the stack frame, as the offsets will
- change later anyway. */
-
- if (GET_CODE (constant_term) == CONST_INT
- && !TARGET_LONG_DISPLACEMENT
- && !DISP_IN_RANGE (INTVAL (constant_term))
- && !(REG_P (x) && REGNO_PTR_FRAME_P (REGNO (x))))
- {
- HOST_WIDE_INT lower = INTVAL (constant_term) & 0xfff;
- HOST_WIDE_INT upper = INTVAL (constant_term) ^ lower;
-
- rtx temp = gen_reg_rtx (Pmode);
- rtx val = force_operand (GEN_INT (upper), temp);
- if (val != temp)
- emit_move_insn (temp, val);
-
- x = gen_rtx_PLUS (Pmode, x, temp);
- constant_term = GEN_INT (lower);
- }
-
- if (GET_CODE (x) == PLUS)
- {
- if (GET_CODE (XEXP (x, 0)) == REG)
- {
- rtx temp = gen_reg_rtx (Pmode);
- rtx val = force_operand (XEXP (x, 1), temp);
- if (val != temp)
- emit_move_insn (temp, val);
-
- x = gen_rtx_PLUS (Pmode, XEXP (x, 0), temp);
- }
-
- else if (GET_CODE (XEXP (x, 1)) == REG)
- {
- rtx temp = gen_reg_rtx (Pmode);
- rtx val = force_operand (XEXP (x, 0), temp);
- if (val != temp)
- emit_move_insn (temp, val);
-
- x = gen_rtx_PLUS (Pmode, temp, XEXP (x, 1));
- }
- }
-
- if (constant_term != const0_rtx)
- x = gen_rtx_PLUS (Pmode, x, constant_term);
-
- return x;
-}
-
-/* Try a machine-dependent way of reloading an illegitimate address AD
- operand. If we find one, push the reload and return the new address.
-
- MODE is the mode of the enclosing MEM. OPNUM is the operand number
- and TYPE is the reload type of the current reload. */
-
-rtx
-legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED,
- int opnum, int type)
-{
- if (!optimize || TARGET_LONG_DISPLACEMENT)
- return NULL_RTX;
-
- if (GET_CODE (ad) == PLUS)
- {
- rtx tem = simplify_binary_operation (PLUS, Pmode,
- XEXP (ad, 0), XEXP (ad, 1));
- if (tem)
- ad = tem;
- }
-
- if (GET_CODE (ad) == PLUS
- && GET_CODE (XEXP (ad, 0)) == REG
- && GET_CODE (XEXP (ad, 1)) == CONST_INT
- && !DISP_IN_RANGE (INTVAL (XEXP (ad, 1))))
- {
- HOST_WIDE_INT lower = INTVAL (XEXP (ad, 1)) & 0xfff;
- HOST_WIDE_INT upper = INTVAL (XEXP (ad, 1)) ^ lower;
- rtx cst, tem, new_rtx;
-
- cst = GEN_INT (upper);
- if (!legitimate_reload_constant_p (cst))
- cst = force_const_mem (Pmode, cst);
-
- tem = gen_rtx_PLUS (Pmode, XEXP (ad, 0), cst);
- new_rtx = gen_rtx_PLUS (Pmode, tem, GEN_INT (lower));
-
- push_reload (XEXP (tem, 1), 0, &XEXP (tem, 1), 0,
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type) type);
- return new_rtx;
- }
-
- return NULL_RTX;
-}
-
-/* Emit code to move LEN bytes from DST to SRC. */
-
-void
-s390_expand_movmem (rtx dst, rtx src, rtx len)
-{
- if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
- {
- if (INTVAL (len) > 0)
- emit_insn (gen_movmem_short (dst, src, GEN_INT (INTVAL (len) - 1)));
- }
-
- else if (TARGET_MVCLE)
- {
- emit_insn (gen_movmem_long (dst, src, convert_to_mode (Pmode, len, 1)));
- }
-
- else
- {
- rtx dst_addr, src_addr, count, blocks, temp;
- rtx loop_start_label = gen_label_rtx ();
- rtx loop_end_label = gen_label_rtx ();
- rtx end_label = gen_label_rtx ();
- enum machine_mode mode;
-
- mode = GET_MODE (len);
- if (mode == VOIDmode)
- mode = Pmode;
-
- dst_addr = gen_reg_rtx (Pmode);
- src_addr = gen_reg_rtx (Pmode);
- count = gen_reg_rtx (mode);
- blocks = gen_reg_rtx (mode);
-
- convert_move (count, len, 1);
- emit_cmp_and_jump_insns (count, const0_rtx,
- EQ, NULL_RTX, mode, 1, end_label);
-
- emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
- emit_move_insn (src_addr, force_operand (XEXP (src, 0), NULL_RTX));
- dst = change_address (dst, VOIDmode, dst_addr);
- src = change_address (src, VOIDmode, src_addr);
-
- temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1,
- OPTAB_DIRECT);
- if (temp != count)
- emit_move_insn (count, temp);
-
- temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1,
- OPTAB_DIRECT);
- if (temp != blocks)
- emit_move_insn (blocks, temp);
-
- emit_cmp_and_jump_insns (blocks, const0_rtx,
- EQ, NULL_RTX, mode, 1, loop_end_label);
-
- emit_label (loop_start_label);
-
- if (TARGET_Z10
- && (GET_CODE (len) != CONST_INT || INTVAL (len) > 768))
- {
- rtx prefetch;
-
- /* Issue a read prefetch for the +3 cache line. */
- prefetch = gen_prefetch (gen_rtx_PLUS (Pmode, src_addr, GEN_INT (768)),
- const0_rtx, const0_rtx);
- PREFETCH_SCHEDULE_BARRIER_P (prefetch) = true;
- emit_insn (prefetch);
-
- /* Issue a write prefetch for the +3 cache line. */
- prefetch = gen_prefetch (gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (768)),
- const1_rtx, const0_rtx);
- PREFETCH_SCHEDULE_BARRIER_P (prefetch) = true;
- emit_insn (prefetch);
- }
-
- emit_insn (gen_movmem_short (dst, src, GEN_INT (255)));
- s390_load_address (dst_addr,
- gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
- s390_load_address (src_addr,
- gen_rtx_PLUS (Pmode, src_addr, GEN_INT (256)));
-
- temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1,
- OPTAB_DIRECT);
- if (temp != blocks)
- emit_move_insn (blocks, temp);
-
- emit_cmp_and_jump_insns (blocks, const0_rtx,
- EQ, NULL_RTX, mode, 1, loop_end_label);
-
- emit_jump (loop_start_label);
- emit_label (loop_end_label);
-
- emit_insn (gen_movmem_short (dst, src,
- convert_to_mode (Pmode, count, 1)));
- emit_label (end_label);
- }
-}
-
-/* Emit code to set LEN bytes at DST to VAL.
- Make use of clrmem if VAL is zero. */
-
-void
-s390_expand_setmem (rtx dst, rtx len, rtx val)
-{
- if (GET_CODE (len) == CONST_INT && INTVAL (len) == 0)
- return;
-
- gcc_assert (GET_CODE (val) == CONST_INT || GET_MODE (val) == QImode);
-
- if (GET_CODE (len) == CONST_INT && INTVAL (len) > 0 && INTVAL (len) <= 257)
- {
- if (val == const0_rtx && INTVAL (len) <= 256)
- emit_insn (gen_clrmem_short (dst, GEN_INT (INTVAL (len) - 1)));
- else
- {
- /* Initialize memory by storing the first byte. */
- emit_move_insn (adjust_address (dst, QImode, 0), val);
-
- if (INTVAL (len) > 1)
- {
- /* Initiate 1 byte overlap move.
- The first byte of DST is propagated through DSTP1.
- Prepare a movmem for: DST+1 = DST (length = LEN - 1).
- DST is set to size 1 so the rest of the memory location
- does not count as source operand. */
- rtx dstp1 = adjust_address (dst, VOIDmode, 1);
- set_mem_size (dst, 1);
-
- emit_insn (gen_movmem_short (dstp1, dst,
- GEN_INT (INTVAL (len) - 2)));
- }
- }
- }
-
- else if (TARGET_MVCLE)
- {
- val = force_not_mem (convert_modes (Pmode, QImode, val, 1));
- emit_insn (gen_setmem_long (dst, convert_to_mode (Pmode, len, 1), val));
- }
-
- else
- {
- rtx dst_addr, count, blocks, temp, dstp1 = NULL_RTX;
- rtx loop_start_label = gen_label_rtx ();
- rtx loop_end_label = gen_label_rtx ();
- rtx end_label = gen_label_rtx ();
- enum machine_mode mode;
-
- mode = GET_MODE (len);
- if (mode == VOIDmode)
- mode = Pmode;
-
- dst_addr = gen_reg_rtx (Pmode);
- count = gen_reg_rtx (mode);
- blocks = gen_reg_rtx (mode);
-
- convert_move (count, len, 1);
- emit_cmp_and_jump_insns (count, const0_rtx,
- EQ, NULL_RTX, mode, 1, end_label);
-
- emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
- dst = change_address (dst, VOIDmode, dst_addr);
-
- if (val == const0_rtx)
- temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1,
- OPTAB_DIRECT);
- else
- {
- dstp1 = adjust_address (dst, VOIDmode, 1);
- set_mem_size (dst, 1);
-
- /* Initialize memory by storing the first byte. */
- emit_move_insn (adjust_address (dst, QImode, 0), val);
-
- /* If count is 1 we are done. */
- emit_cmp_and_jump_insns (count, const1_rtx,
- EQ, NULL_RTX, mode, 1, end_label);
-
- temp = expand_binop (mode, add_optab, count, GEN_INT (-2), count, 1,
- OPTAB_DIRECT);
- }
- if (temp != count)
- emit_move_insn (count, temp);
-
- temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1,
- OPTAB_DIRECT);
- if (temp != blocks)
- emit_move_insn (blocks, temp);
-
- emit_cmp_and_jump_insns (blocks, const0_rtx,
- EQ, NULL_RTX, mode, 1, loop_end_label);
-
- emit_label (loop_start_label);
-
- if (TARGET_Z10
- && (GET_CODE (len) != CONST_INT || INTVAL (len) > 1024))
- {
- /* Issue a write prefetch for the +4 cache line. */
- rtx prefetch = gen_prefetch (gen_rtx_PLUS (Pmode, dst_addr,
- GEN_INT (1024)),
- const1_rtx, const0_rtx);
- emit_insn (prefetch);
- PREFETCH_SCHEDULE_BARRIER_P (prefetch) = true;
- }
-
- if (val == const0_rtx)
- emit_insn (gen_clrmem_short (dst, GEN_INT (255)));
- else
- emit_insn (gen_movmem_short (dstp1, dst, GEN_INT (255)));
- s390_load_address (dst_addr,
- gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
-
- temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1,
- OPTAB_DIRECT);
- if (temp != blocks)
- emit_move_insn (blocks, temp);
-
- emit_cmp_and_jump_insns (blocks, const0_rtx,
- EQ, NULL_RTX, mode, 1, loop_end_label);
-
- emit_jump (loop_start_label);
- emit_label (loop_end_label);
-
- if (val == const0_rtx)
- emit_insn (gen_clrmem_short (dst, convert_to_mode (Pmode, count, 1)));
- else
- emit_insn (gen_movmem_short (dstp1, dst, convert_to_mode (Pmode, count, 1)));
- emit_label (end_label);
- }
-}
-
-/* Emit code to compare LEN bytes at OP0 with those at OP1,
- and return the result in TARGET. */
-
-void
-s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
-{
- rtx ccreg = gen_rtx_REG (CCUmode, CC_REGNUM);
- rtx tmp;
-
- /* As the result of CMPINT is inverted compared to what we need,
- we have to swap the operands. */
- tmp = op0; op0 = op1; op1 = tmp;
-
- if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
- {
- if (INTVAL (len) > 0)
- {
- emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
- emit_insn (gen_cmpint (target, ccreg));
- }
- else
- emit_move_insn (target, const0_rtx);
- }
- else if (TARGET_MVCLE)
- {
- emit_insn (gen_cmpmem_long (op0, op1, convert_to_mode (Pmode, len, 1)));
- emit_insn (gen_cmpint (target, ccreg));
- }
- else
- {
- rtx addr0, addr1, count, blocks, temp;
- rtx loop_start_label = gen_label_rtx ();
- rtx loop_end_label = gen_label_rtx ();
- rtx end_label = gen_label_rtx ();
- enum machine_mode mode;
-
- mode = GET_MODE (len);
- if (mode == VOIDmode)
- mode = Pmode;
-
- addr0 = gen_reg_rtx (Pmode);
- addr1 = gen_reg_rtx (Pmode);
- count = gen_reg_rtx (mode);
- blocks = gen_reg_rtx (mode);
-
- convert_move (count, len, 1);
- emit_cmp_and_jump_insns (count, const0_rtx,
- EQ, NULL_RTX, mode, 1, end_label);
-
- emit_move_insn (addr0, force_operand (XEXP (op0, 0), NULL_RTX));
- emit_move_insn (addr1, force_operand (XEXP (op1, 0), NULL_RTX));
- op0 = change_address (op0, VOIDmode, addr0);
- op1 = change_address (op1, VOIDmode, addr1);
-
- temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1,
- OPTAB_DIRECT);
- if (temp != count)
- emit_move_insn (count, temp);
-
- temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1,
- OPTAB_DIRECT);
- if (temp != blocks)
- emit_move_insn (blocks, temp);
-
- emit_cmp_and_jump_insns (blocks, const0_rtx,
- EQ, NULL_RTX, mode, 1, loop_end_label);
-
- emit_label (loop_start_label);
-
- if (TARGET_Z10
- && (GET_CODE (len) != CONST_INT || INTVAL (len) > 512))
- {
- rtx prefetch;
-
- /* Issue a read prefetch for the +2 cache line of operand 1. */
- prefetch = gen_prefetch (gen_rtx_PLUS (Pmode, addr0, GEN_INT (512)),
- const0_rtx, const0_rtx);
- emit_insn (prefetch);
- PREFETCH_SCHEDULE_BARRIER_P (prefetch) = true;
-
- /* Issue a read prefetch for the +2 cache line of operand 2. */
- prefetch = gen_prefetch (gen_rtx_PLUS (Pmode, addr1, GEN_INT (512)),
- const0_rtx, const0_rtx);
- emit_insn (prefetch);
- PREFETCH_SCHEDULE_BARRIER_P (prefetch) = true;
- }
-
- emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (255)));
- temp = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
- temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
- gen_rtx_LABEL_REF (VOIDmode, end_label), pc_rtx);
- temp = gen_rtx_SET (VOIDmode, pc_rtx, temp);
- emit_jump_insn (temp);
-
- s390_load_address (addr0,
- gen_rtx_PLUS (Pmode, addr0, GEN_INT (256)));
- s390_load_address (addr1,
- gen_rtx_PLUS (Pmode, addr1, GEN_INT (256)));
-
- temp = expand_binop (mode, add_optab, blocks, constm1_rtx, blocks, 1,
- OPTAB_DIRECT);
- if (temp != blocks)
- emit_move_insn (blocks, temp);
-
- emit_cmp_and_jump_insns (blocks, const0_rtx,
- EQ, NULL_RTX, mode, 1, loop_end_label);
-
- emit_jump (loop_start_label);
- emit_label (loop_end_label);
-
- emit_insn (gen_cmpmem_short (op0, op1,
- convert_to_mode (Pmode, count, 1)));
- emit_label (end_label);
-
- emit_insn (gen_cmpint (target, ccreg));
- }
-}
-
-
-/* Expand conditional increment or decrement using alc/slb instructions.
- Should generate code setting DST to either SRC or SRC + INCREMENT,
- depending on the result of the comparison CMP_OP0 CMP_CODE CMP_OP1.
- Returns true if successful, false otherwise.
-
- That makes it possible to implement some if-constructs without jumps e.g.:
- (borrow = CC0 | CC1 and carry = CC2 | CC3)
- unsigned int a, b, c;
- if (a < b) c++; -> CCU b > a -> CC2; c += carry;
- if (a < b) c--; -> CCL3 a - b -> borrow; c -= borrow;
- if (a <= b) c++; -> CCL3 b - a -> borrow; c += carry;
- if (a <= b) c--; -> CCU a <= b -> borrow; c -= borrow;
-
- Checks for EQ and NE with a nonzero value need an additional xor e.g.:
- if (a == b) c++; -> CCL3 a ^= b; 0 - a -> borrow; c += carry;
- if (a == b) c--; -> CCU a ^= b; a <= 0 -> CC0 | CC1; c -= borrow;
- if (a != b) c++; -> CCU a ^= b; a > 0 -> CC2; c += carry;
- if (a != b) c--; -> CCL3 a ^= b; 0 - a -> borrow; c -= borrow; */
-
-bool
-s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
- rtx dst, rtx src, rtx increment)
-{
- enum machine_mode cmp_mode;
- enum machine_mode cc_mode;
- rtx op_res;
- rtx insn;
- rtvec p;
- int ret;
-
- if ((GET_MODE (cmp_op0) == SImode || GET_MODE (cmp_op0) == VOIDmode)
- && (GET_MODE (cmp_op1) == SImode || GET_MODE (cmp_op1) == VOIDmode))
- cmp_mode = SImode;
- else if ((GET_MODE (cmp_op0) == DImode || GET_MODE (cmp_op0) == VOIDmode)
- && (GET_MODE (cmp_op1) == DImode || GET_MODE (cmp_op1) == VOIDmode))
- cmp_mode = DImode;
- else
- return false;
-
- /* Try ADD LOGICAL WITH CARRY. */
- if (increment == const1_rtx)
- {
- /* Determine CC mode to use. */
- if (cmp_code == EQ || cmp_code == NE)
- {
- if (cmp_op1 != const0_rtx)
- {
- cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1,
- NULL_RTX, 0, OPTAB_WIDEN);
- cmp_op1 = const0_rtx;
- }
-
- cmp_code = cmp_code == EQ ? LEU : GTU;
- }
-
- if (cmp_code == LTU || cmp_code == LEU)
- {
- rtx tem = cmp_op0;
- cmp_op0 = cmp_op1;
- cmp_op1 = tem;
- cmp_code = swap_condition (cmp_code);
- }
-
- switch (cmp_code)
- {
- case GTU:
- cc_mode = CCUmode;
- break;
-
- case GEU:
- cc_mode = CCL3mode;
- break;
-
- default:
- return false;
- }
-
- /* Emit comparison instruction pattern. */
- if (!register_operand (cmp_op0, cmp_mode))
- cmp_op0 = force_reg (cmp_mode, cmp_op0);
-
- insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM),
- gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1));
- /* We use insn_invalid_p here to add clobbers if required. */
- ret = insn_invalid_p (emit_insn (insn));
- gcc_assert (!ret);
-
- /* Emit ALC instruction pattern. */
- op_res = gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
- gen_rtx_REG (cc_mode, CC_REGNUM),
- const0_rtx);
-
- if (src != const0_rtx)
- {
- if (!register_operand (src, GET_MODE (dst)))
- src = force_reg (GET_MODE (dst), src);
-
- op_res = gen_rtx_PLUS (GET_MODE (dst), op_res, src);
- op_res = gen_rtx_PLUS (GET_MODE (dst), op_res, const0_rtx);
- }
-
- p = rtvec_alloc (2);
- RTVEC_ELT (p, 0) =
- gen_rtx_SET (VOIDmode, dst, op_res);
- RTVEC_ELT (p, 1) =
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
- emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
-
- return true;
- }
-
- /* Try SUBTRACT LOGICAL WITH BORROW. */
- if (increment == constm1_rtx)
- {
- /* Determine CC mode to use. */
- if (cmp_code == EQ || cmp_code == NE)
- {
- if (cmp_op1 != const0_rtx)
- {
- cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1,
- NULL_RTX, 0, OPTAB_WIDEN);
- cmp_op1 = const0_rtx;
- }
-
- cmp_code = cmp_code == EQ ? LEU : GTU;
- }
-
- if (cmp_code == GTU || cmp_code == GEU)
- {
- rtx tem = cmp_op0;
- cmp_op0 = cmp_op1;
- cmp_op1 = tem;
- cmp_code = swap_condition (cmp_code);
- }
-
- switch (cmp_code)
- {
- case LEU:
- cc_mode = CCUmode;
- break;
-
- case LTU:
- cc_mode = CCL3mode;
- break;
-
- default:
- return false;
- }
-
- /* Emit comparison instruction pattern. */
- if (!register_operand (cmp_op0, cmp_mode))
- cmp_op0 = force_reg (cmp_mode, cmp_op0);
-
- insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM),
- gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1));
- /* We use insn_invalid_p here to add clobbers if required. */
- ret = insn_invalid_p (emit_insn (insn));
- gcc_assert (!ret);
-
- /* Emit SLB instruction pattern. */
- if (!register_operand (src, GET_MODE (dst)))
- src = force_reg (GET_MODE (dst), src);
-
- op_res = gen_rtx_MINUS (GET_MODE (dst),
- gen_rtx_MINUS (GET_MODE (dst), src, const0_rtx),
- gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
- gen_rtx_REG (cc_mode, CC_REGNUM),
- const0_rtx));
- p = rtvec_alloc (2);
- RTVEC_ELT (p, 0) =
- gen_rtx_SET (VOIDmode, dst, op_res);
- RTVEC_ELT (p, 1) =
- gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
- emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
-
- return true;
- }
-
- return false;
-}
-
-/* Expand code for the insv template. Return true if successful. */
-
-bool
-s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
-{
- int bitsize = INTVAL (op1);
- int bitpos = INTVAL (op2);
-
- /* On z10 we can use the risbg instruction to implement insv. */
- if (TARGET_Z10
- && ((GET_MODE (dest) == DImode && GET_MODE (src) == DImode)
- || (GET_MODE (dest) == SImode && GET_MODE (src) == SImode)))
- {
- rtx op;
- rtx clobber;
-
- op = gen_rtx_SET (GET_MODE(src),
- gen_rtx_ZERO_EXTRACT (GET_MODE (dest), dest, op1, op2),
- src);
- clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
- emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clobber)));
-
- return true;
- }
-
- /* We need byte alignment. */
- if (bitsize % BITS_PER_UNIT)
- return false;
-
- if (bitpos == 0
- && memory_operand (dest, VOIDmode)
- && (register_operand (src, word_mode)
- || const_int_operand (src, VOIDmode)))
- {
- /* Emit standard pattern if possible. */
- enum machine_mode mode = smallest_mode_for_size (bitsize, MODE_INT);
- if (GET_MODE_BITSIZE (mode) == bitsize)
- emit_move_insn (adjust_address (dest, mode, 0), gen_lowpart (mode, src));
-
- /* (set (ze (mem)) (const_int)). */
- else if (const_int_operand (src, VOIDmode))
- {
- int size = bitsize / BITS_PER_UNIT;
- rtx src_mem = adjust_address (force_const_mem (word_mode, src), BLKmode,
- GET_MODE_SIZE (word_mode) - size);
-
- dest = adjust_address (dest, BLKmode, 0);
- set_mem_size (dest, size);
- s390_expand_movmem (dest, src_mem, GEN_INT (size));
- }
-
- /* (set (ze (mem)) (reg)). */
- else if (register_operand (src, word_mode))
- {
- if (bitsize <= GET_MODE_BITSIZE (SImode))
- emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, op1,
- const0_rtx), src);
- else
- {
- /* Emit st,stcmh sequence. */
- int stcmh_width = bitsize - GET_MODE_BITSIZE (SImode);
- int size = stcmh_width / BITS_PER_UNIT;
-
- emit_move_insn (adjust_address (dest, SImode, size),
- gen_lowpart (SImode, src));
- set_mem_size (dest, size);
- emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
- (stcmh_width), const0_rtx),
- gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
- (GET_MODE_BITSIZE (SImode))));
- }
- }
- else
- return false;
-
- return true;
- }
-
- /* (set (ze (reg)) (const_int)). */
- if (TARGET_ZARCH
- && register_operand (dest, word_mode)
- && (bitpos % 16) == 0
- && (bitsize % 16) == 0
- && const_int_operand (src, VOIDmode))
- {
- HOST_WIDE_INT val = INTVAL (src);
- int regpos = bitpos + bitsize;
-
- while (regpos > bitpos)
- {
- enum machine_mode putmode;
- int putsize;
-
- if (TARGET_EXTIMM && (regpos % 32 == 0) && (regpos >= bitpos + 32))
- putmode = SImode;
- else
- putmode = HImode;
-
- putsize = GET_MODE_BITSIZE (putmode);
- regpos -= putsize;
- emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest,
- GEN_INT (putsize),
- GEN_INT (regpos)),
- gen_int_mode (val, putmode));
- val >>= putsize;
- }
- gcc_assert (regpos == bitpos);
- return true;
- }
-
- return false;
-}
-
-/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic which returns a
- register that holds VAL of mode MODE shifted by COUNT bits. */
-
-static inline rtx
-s390_expand_mask_and_shift (rtx val, enum machine_mode mode, rtx count)
-{
- val = expand_simple_binop (SImode, AND, val, GEN_INT (GET_MODE_MASK (mode)),
- NULL_RTX, 1, OPTAB_DIRECT);
- return expand_simple_binop (SImode, ASHIFT, val, count,
- NULL_RTX, 1, OPTAB_DIRECT);
-}
-
-/* Structure to hold the initial parameters for a compare_and_swap operation
- in HImode and QImode. */
-
-struct alignment_context
-{
- rtx memsi; /* SI aligned memory location. */
- rtx shift; /* Bit offset with regard to lsb. */
- rtx modemask; /* Mask of the HQImode shifted by SHIFT bits. */
- rtx modemaski; /* ~modemask */
- bool aligned; /* True if memory is aligned, false else. */
-};
-
-/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic to initialize
- structure AC for transparent simplifying, if the memory alignment is known
- to be at least 32bit. MEM is the memory location for the actual operation
- and MODE its mode. */
-
-static void
-init_alignment_context (struct alignment_context *ac, rtx mem,
- enum machine_mode mode)
-{
- ac->shift = GEN_INT (GET_MODE_SIZE (SImode) - GET_MODE_SIZE (mode));
- ac->aligned = (MEM_ALIGN (mem) >= GET_MODE_BITSIZE (SImode));
-
- if (ac->aligned)
- ac->memsi = adjust_address (mem, SImode, 0); /* Memory is aligned. */
- else
- {
- /* Alignment is unknown. */
- rtx byteoffset, addr, align;
-
- /* Force the address into a register. */
- addr = force_reg (Pmode, XEXP (mem, 0));
-
- /* Align it to SImode. */
- align = expand_simple_binop (Pmode, AND, addr,
- GEN_INT (-GET_MODE_SIZE (SImode)),
- NULL_RTX, 1, OPTAB_DIRECT);
- /* Generate MEM. */
- ac->memsi = gen_rtx_MEM (SImode, align);
- MEM_VOLATILE_P (ac->memsi) = MEM_VOLATILE_P (mem);
- set_mem_alias_set (ac->memsi, ALIAS_SET_MEMORY_BARRIER);
- set_mem_align (ac->memsi, GET_MODE_BITSIZE (SImode));
-
- /* Calculate shiftcount. */
- byteoffset = expand_simple_binop (Pmode, AND, addr,
- GEN_INT (GET_MODE_SIZE (SImode) - 1),
- NULL_RTX, 1, OPTAB_DIRECT);
- /* As we already have some offset, evaluate the remaining distance. */
- ac->shift = expand_simple_binop (SImode, MINUS, ac->shift, byteoffset,
- NULL_RTX, 1, OPTAB_DIRECT);
-
- }
- /* Shift is the byte count, but we need the bitcount. */
- ac->shift = expand_simple_binop (SImode, MULT, ac->shift, GEN_INT (BITS_PER_UNIT),
- NULL_RTX, 1, OPTAB_DIRECT);
- /* Calculate masks. */
- ac->modemask = expand_simple_binop (SImode, ASHIFT,
- GEN_INT (GET_MODE_MASK (mode)), ac->shift,
- NULL_RTX, 1, OPTAB_DIRECT);
- ac->modemaski = expand_simple_unop (SImode, NOT, ac->modemask, NULL_RTX, 1);
-}
-
-/* Expand an atomic compare and swap operation for HImode and QImode. MEM is
- the memory location, CMP the old value to compare MEM with and NEW_RTX the value
- to set if CMP == MEM.
- CMP is never in memory for compare_and_swap_cc because
- expand_bool_compare_and_swap puts it into a register for later compare. */
-
-void
-s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx new_rtx)
-{
- struct alignment_context ac;
- rtx cmpv, newv, val, resv, cc;
- rtx res = gen_reg_rtx (SImode);
- rtx csloop = gen_label_rtx ();
- rtx csend = gen_label_rtx ();
-
- gcc_assert (register_operand (target, VOIDmode));
- gcc_assert (MEM_P (mem));
-
- init_alignment_context (&ac, mem, mode);
-
- /* Shift the values to the correct bit positions. */
- if (!(ac.aligned && MEM_P (cmp)))
- cmp = s390_expand_mask_and_shift (cmp, mode, ac.shift);
- if (!(ac.aligned && MEM_P (new_rtx)))
- new_rtx = s390_expand_mask_and_shift (new_rtx, mode, ac.shift);
-
- /* Load full word. Subsequent loads are performed by CS. */
- val = expand_simple_binop (SImode, AND, ac.memsi, ac.modemaski,
- NULL_RTX, 1, OPTAB_DIRECT);
-
- /* Start CS loop. */
- emit_label (csloop);
- /* val = "<mem>00..0<mem>"
- * cmp = "00..0<cmp>00..0"
- * new = "00..0<new>00..0"
- */
-
- /* Patch cmp and new with val at correct position. */
- if (ac.aligned && MEM_P (cmp))
- {
- cmpv = force_reg (SImode, val);
- store_bit_field (cmpv, GET_MODE_BITSIZE (mode), 0,
- 0, 0, SImode, cmp);
- }
- else
- cmpv = force_reg (SImode, expand_simple_binop (SImode, IOR, cmp, val,
- NULL_RTX, 1, OPTAB_DIRECT));
- if (ac.aligned && MEM_P (new_rtx))
- {
- newv = force_reg (SImode, val);
- store_bit_field (newv, GET_MODE_BITSIZE (mode), 0,
- 0, 0, SImode, new_rtx);
- }
- else
- newv = force_reg (SImode, expand_simple_binop (SImode, IOR, new_rtx, val,
- NULL_RTX, 1, OPTAB_DIRECT));
-
- /* Jump to end if we're done (likely?). */
- s390_emit_jump (csend, s390_emit_compare_and_swap (EQ, res, ac.memsi,
- cmpv, newv));
-
- /* Check for changes outside mode. */
- resv = expand_simple_binop (SImode, AND, res, ac.modemaski,
- NULL_RTX, 1, OPTAB_DIRECT);
- cc = s390_emit_compare (NE, resv, val);
- emit_move_insn (val, resv);
- /* Loop internal if so. */
- s390_emit_jump (csloop, cc);
-
- emit_label (csend);
-
- /* Return the correct part of the bitfield. */
- convert_move (target, expand_simple_binop (SImode, LSHIFTRT, res, ac.shift,
- NULL_RTX, 1, OPTAB_DIRECT), 1);
-}
-
-/* Expand an atomic operation CODE of mode MODE. MEM is the memory location
- and VAL the value to play with. If AFTER is true then store the value
- MEM holds after the operation, if AFTER is false then store the value MEM
- holds before the operation. If TARGET is zero then discard that value, else
- store it to TARGET. */
-
-void
-s390_expand_atomic (enum machine_mode mode, enum rtx_code code,
- rtx target, rtx mem, rtx val, bool after)
-{
- struct alignment_context ac;
- rtx cmp;
- rtx new_rtx = gen_reg_rtx (SImode);
- rtx orig = gen_reg_rtx (SImode);
- rtx csloop = gen_label_rtx ();
-
- gcc_assert (!target || register_operand (target, VOIDmode));
- gcc_assert (MEM_P (mem));
-
- init_alignment_context (&ac, mem, mode);
-
- /* Shift val to the correct bit positions.
- Preserve "icm", but prevent "ex icm". */
- if (!(ac.aligned && code == SET && MEM_P (val)))
- val = s390_expand_mask_and_shift (val, mode, ac.shift);
-
- /* Further preparation insns. */
- if (code == PLUS || code == MINUS)
- emit_move_insn (orig, val);
- else if (code == MULT || code == AND) /* val = "11..1<val>11..1" */
- val = expand_simple_binop (SImode, XOR, val, ac.modemaski,
- NULL_RTX, 1, OPTAB_DIRECT);
-
- /* Load full word. Subsequent loads are performed by CS. */
- cmp = force_reg (SImode, ac.memsi);
-
- /* Start CS loop. */
- emit_label (csloop);
- emit_move_insn (new_rtx, cmp);
-
- /* Patch new with val at correct position. */
- switch (code)
- {
- case PLUS:
- case MINUS:
- val = expand_simple_binop (SImode, code, new_rtx, orig,
- NULL_RTX, 1, OPTAB_DIRECT);
- val = expand_simple_binop (SImode, AND, val, ac.modemask,
- NULL_RTX, 1, OPTAB_DIRECT);
- /* FALLTHRU */
- case SET:
- if (ac.aligned && MEM_P (val))
- store_bit_field (new_rtx, GET_MODE_BITSIZE (mode), 0,
- 0, 0, SImode, val);
- else
- {
- new_rtx = expand_simple_binop (SImode, AND, new_rtx, ac.modemaski,
- NULL_RTX, 1, OPTAB_DIRECT);
- new_rtx = expand_simple_binop (SImode, IOR, new_rtx, val,
- NULL_RTX, 1, OPTAB_DIRECT);
- }
- break;
- case AND:
- case IOR:
- case XOR:
- new_rtx = expand_simple_binop (SImode, code, new_rtx, val,
- NULL_RTX, 1, OPTAB_DIRECT);
- break;
- case MULT: /* NAND */
- new_rtx = expand_simple_binop (SImode, AND, new_rtx, val,
- NULL_RTX, 1, OPTAB_DIRECT);
- new_rtx = expand_simple_binop (SImode, XOR, new_rtx, ac.modemask,
- NULL_RTX, 1, OPTAB_DIRECT);
- break;
- default:
- gcc_unreachable ();
- }
-
- s390_emit_jump (csloop, s390_emit_compare_and_swap (NE, cmp,
- ac.memsi, cmp, new_rtx));
-
- /* Return the correct part of the bitfield. */
- if (target)
- convert_move (target, expand_simple_binop (SImode, LSHIFTRT,
- after ? new_rtx : cmp, ac.shift,
- NULL_RTX, 1, OPTAB_DIRECT), 1);
-}
-
-/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
- We need to emit DTP-relative relocations. */
-
-static void s390_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
-
-static void
-s390_output_dwarf_dtprel (FILE *file, int size, rtx x)
-{
- switch (size)
- {
- case 4:
- fputs ("\t.long\t", file);
- break;
- case 8:
- fputs ("\t.quad\t", file);
- break;
- default:
- gcc_unreachable ();
- }
- output_addr_const (file, x);
- fputs ("@DTPOFF", file);
-}
-
-#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-/* Implement TARGET_MANGLE_TYPE. */
-
-static const char *
-s390_mangle_type (const_tree type)
-{
- if (TYPE_MAIN_VARIANT (type) == long_double_type_node
- && TARGET_LONG_DOUBLE_128)
- return "g";
-
- /* For all other types, use normal C++ mangling. */
- return NULL;
-}
-#endif
-
-/* In the name of slightly smaller debug output, and to cater to
- general assembler lossage, recognize various UNSPEC sequences
- and turn them back into a direct symbol reference. */
-
-static rtx
-s390_delegitimize_address (rtx orig_x)
-{
- rtx x, y;
-
- orig_x = delegitimize_mem_from_attrs (orig_x);
- x = orig_x;
-
- /* Extract the symbol ref from:
- (plus:SI (reg:SI 12 %r12)
- (const:SI (unspec:SI [(symbol_ref/f:SI ("*.LC0"))]
- UNSPEC_GOTOFF/PLTOFF)))
- and
- (plus:SI (reg:SI 12 %r12)
- (const:SI (plus:SI (unspec:SI [(symbol_ref:SI ("L"))]
- UNSPEC_GOTOFF/PLTOFF)
- (const_int 4 [0x4])))) */
- if (GET_CODE (x) == PLUS
- && REG_P (XEXP (x, 0))
- && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM
- && GET_CODE (XEXP (x, 1)) == CONST)
- {
- HOST_WIDE_INT offset = 0;
-
- /* The const operand. */
- y = XEXP (XEXP (x, 1), 0);
-
- if (GET_CODE (y) == PLUS
- && GET_CODE (XEXP (y, 1)) == CONST_INT)
- {
- offset = INTVAL (XEXP (y, 1));
- y = XEXP (y, 0);
- }
-
- if (GET_CODE (y) == UNSPEC
- && (XINT (y, 1) == UNSPEC_GOTOFF
- || XINT (y, 1) == UNSPEC_PLTOFF))
- return plus_constant (XVECEXP (y, 0, 0), offset);
- }
-
- if (GET_CODE (x) != MEM)
- return orig_x;
-
- x = XEXP (x, 0);
- if (GET_CODE (x) == PLUS
- && GET_CODE (XEXP (x, 1)) == CONST
- && GET_CODE (XEXP (x, 0)) == REG
- && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
- {
- y = XEXP (XEXP (x, 1), 0);
- if (GET_CODE (y) == UNSPEC
- && XINT (y, 1) == UNSPEC_GOT)
- y = XVECEXP (y, 0, 0);
- else
- return orig_x;
- }
- else if (GET_CODE (x) == CONST)
- {
- /* Extract the symbol ref from:
- (mem:QI (const:DI (unspec:DI [(symbol_ref:DI ("foo"))]
- UNSPEC_PLT/GOTENT))) */
-
- y = XEXP (x, 0);
- if (GET_CODE (y) == UNSPEC
- && (XINT (y, 1) == UNSPEC_GOTENT
- || XINT (y, 1) == UNSPEC_PLT))
- y = XVECEXP (y, 0, 0);
- else
- return orig_x;
- }
- else
- return orig_x;
-
- if (GET_MODE (orig_x) != Pmode)
- {
- if (GET_MODE (orig_x) == BLKmode)
- return orig_x;
- y = lowpart_subreg (GET_MODE (orig_x), y, Pmode);
- if (y == NULL_RTX)
- return orig_x;
- }
- return y;
-}
-
-/* Output operand OP to stdio stream FILE.
- OP is an address (register + offset) which is not used to address data;
- instead the rightmost bits are interpreted as the value. */
-
-static void
-print_shift_count_operand (FILE *file, rtx op)
-{
- HOST_WIDE_INT offset;
- rtx base;
-
- /* Extract base register and offset. */
- if (!s390_decompose_shift_count (op, &base, &offset))
- gcc_unreachable ();
-
- /* Sanity check. */
- if (base)
- {
- gcc_assert (GET_CODE (base) == REG);
- gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
- gcc_assert (REGNO_REG_CLASS (REGNO (base)) == ADDR_REGS);
- }
-
- /* Offsets are constricted to twelve bits. */
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset & ((1 << 12) - 1));
- if (base)
- fprintf (file, "(%s)", reg_names[REGNO (base)]);
-}
-
-/* See 'get_some_local_dynamic_name'. */
-
-static int
-get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
-{
- rtx x = *px;
-
- if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
- {
- x = get_pool_constant (x);
- return for_each_rtx (&x, get_some_local_dynamic_name_1, 0);
- }
-
- if (GET_CODE (x) == SYMBOL_REF
- && tls_symbolic_operand (x) == TLS_MODEL_LOCAL_DYNAMIC)
- {
- cfun->machine->some_ld_name = XSTR (x, 0);
- return 1;
- }
-
- return 0;
-}
-
-/* Locate some local-dynamic symbol still in use by this function
- so that we can print its name in local-dynamic base patterns. */
-
-static const char *
-get_some_local_dynamic_name (void)
-{
- rtx insn;
-
- if (cfun->machine->some_ld_name)
- return cfun->machine->some_ld_name;
-
- for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
- if (INSN_P (insn)
- && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
- return cfun->machine->some_ld_name;
-
- gcc_unreachable ();
-}
-
-/* Output machine-dependent UNSPECs occurring in address constant X
- in assembler syntax to stdio stream FILE. Returns true if the
- constant X could be recognized, false otherwise. */
-
-static bool
-s390_output_addr_const_extra (FILE *file, rtx x)
-{
- if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
- switch (XINT (x, 1))
- {
- case UNSPEC_GOTENT:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOTENT");
- return true;
- case UNSPEC_GOT:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOT");
- return true;
- case UNSPEC_GOTOFF:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOTOFF");
- return true;
- case UNSPEC_PLT:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@PLT");
- return true;
- case UNSPEC_PLTOFF:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@PLTOFF");
- return true;
- case UNSPEC_TLSGD:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@TLSGD");
- return true;
- case UNSPEC_TLSLDM:
- assemble_name (file, get_some_local_dynamic_name ());
- fprintf (file, "@TLSLDM");
- return true;
- case UNSPEC_DTPOFF:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@DTPOFF");
- return true;
- case UNSPEC_NTPOFF:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@NTPOFF");
- return true;
- case UNSPEC_GOTNTPOFF:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOTNTPOFF");
- return true;
- case UNSPEC_INDNTPOFF:
- output_addr_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@INDNTPOFF");
- return true;
- }
-
- if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 2)
- switch (XINT (x, 1))
- {
- case UNSPEC_POOL_OFFSET:
- x = gen_rtx_MINUS (GET_MODE (x), XVECEXP (x, 0, 0), XVECEXP (x, 0, 1));
- output_addr_const (file, x);
- return true;
- }
- return false;
-}
-
-/* Output address operand ADDR in assembler syntax to
- stdio stream FILE. */
-
-void
-print_operand_address (FILE *file, rtx addr)
-{
- struct s390_address ad;
-
- if (s390_symref_operand_p (addr, NULL, NULL))
- {
- if (!TARGET_Z10)
- {
- output_operand_lossage ("symbolic memory references are "
- "only supported on z10 or later");
- return;
- }
- output_addr_const (file, addr);
- return;
- }
-
- if (!s390_decompose_address (addr, &ad)
- || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
- || (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
- output_operand_lossage ("cannot decompose address");
-
- if (ad.disp)
- output_addr_const (file, ad.disp);
- else
- fprintf (file, "0");
-
- if (ad.base && ad.indx)
- fprintf (file, "(%s,%s)", reg_names[REGNO (ad.indx)],
- reg_names[REGNO (ad.base)]);
- else if (ad.base)
- fprintf (file, "(%s)", reg_names[REGNO (ad.base)]);
-}
-
-/* Output operand X in assembler syntax to stdio stream FILE.
- CODE specified the format flag. The following format flags
- are recognized:
-
- 'C': print opcode suffix for branch condition.
- 'D': print opcode suffix for inverse branch condition.
- 'E': print opcode suffix for branch on index instruction.
- 'J': print tls_load/tls_gdcall/tls_ldcall suffix
- 'G': print the size of the operand in bytes.
- 'O': print only the displacement of a memory reference.
- 'R': print only the base register of a memory reference.
- 'S': print S-type memory reference (base+displacement).
- 'N': print the second word of a DImode operand.
- 'M': print the second word of a TImode operand.
- 'Y': print shift count operand.
-
- 'b': print integer X as if it's an unsigned byte.
- 'c': print integer X as if it's an signed byte.
- 'x': print integer X as if it's an unsigned halfword.
- 'h': print integer X as if it's a signed halfword.
- 'i': print the first nonzero HImode part of X.
- 'j': print the first HImode part unequal to -1 of X.
- 'k': print the first nonzero SImode part of X.
- 'm': print the first SImode part unequal to -1 of X.
- 'o': print integer X as if it's an unsigned 32bit word. */
-
-void
-print_operand (FILE *file, rtx x, int code)
-{
- switch (code)
- {
- case 'C':
- fprintf (file, s390_branch_condition_mnemonic (x, FALSE));
- return;
-
- case 'D':
- fprintf (file, s390_branch_condition_mnemonic (x, TRUE));
- return;
-
- case 'E':
- if (GET_CODE (x) == LE)
- fprintf (file, "l");
- else if (GET_CODE (x) == GT)
- fprintf (file, "h");
- else
- output_operand_lossage ("invalid comparison operator "
- "for 'E' output modifier");
- return;
-
- case 'J':
- if (GET_CODE (x) == SYMBOL_REF)
- {
- fprintf (file, "%s", ":tls_load:");
- output_addr_const (file, x);
- }
- else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSGD)
- {
- fprintf (file, "%s", ":tls_gdcall:");
- output_addr_const (file, XVECEXP (x, 0, 0));
- }
- else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLSLDM)
- {
- fprintf (file, "%s", ":tls_ldcall:");
- assemble_name (file, get_some_local_dynamic_name ());
- }
- else
- output_operand_lossage ("invalid reference for 'J' output modifier");
- return;
-
- case 'G':
- fprintf (file, "%u", GET_MODE_SIZE (GET_MODE (x)));
- return;
-
- case 'O':
- {
- struct s390_address ad;
- int ret;
-
- if (!MEM_P (x))
- {
- output_operand_lossage ("memory reference expected for "
- "'O' output modifier");
- return;
- }
-
- ret = s390_decompose_address (XEXP (x, 0), &ad);
-
- if (!ret
- || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
- || ad.indx)
- {
- output_operand_lossage ("invalid address for 'O' output modifier");
- return;
- }
-
- if (ad.disp)
- output_addr_const (file, ad.disp);
- else
- fprintf (file, "0");
- }
- return;
-
- case 'R':
- {
- struct s390_address ad;
- int ret;
-
- if (!MEM_P (x))
- {
- output_operand_lossage ("memory reference expected for "
- "'R' output modifier");
- return;
- }
-
- ret = s390_decompose_address (XEXP (x, 0), &ad);
-
- if (!ret
- || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
- || ad.indx)
- {
- output_operand_lossage ("invalid address for 'R' output modifier");
- return;
- }
-
- if (ad.base)
- fprintf (file, "%s", reg_names[REGNO (ad.base)]);
- else
- fprintf (file, "0");
- }
- return;
-
- case 'S':
- {
- struct s390_address ad;
- int ret;
-
- if (!MEM_P (x))
- {
- output_operand_lossage ("memory reference expected for "
- "'S' output modifier");
- return;
- }
- ret = s390_decompose_address (XEXP (x, 0), &ad);
-
- if (!ret
- || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
- || ad.indx)
- {
- output_operand_lossage ("invalid address for 'S' output modifier");
- return;
- }
-
- if (ad.disp)
- output_addr_const (file, ad.disp);
- else
- fprintf (file, "0");
-
- if (ad.base)
- fprintf (file, "(%s)", reg_names[REGNO (ad.base)]);
- }
- return;
-
- case 'N':
- if (GET_CODE (x) == REG)
- x = gen_rtx_REG (GET_MODE (x), REGNO (x) + 1);
- else if (GET_CODE (x) == MEM)
- x = change_address (x, VOIDmode, plus_constant (XEXP (x, 0), 4));
- else
- output_operand_lossage ("register or memory expression expected "
- "for 'N' output modifier");
- break;
-
- case 'M':
- if (GET_CODE (x) == REG)
- x = gen_rtx_REG (GET_MODE (x), REGNO (x) + 1);
- else if (GET_CODE (x) == MEM)
- x = change_address (x, VOIDmode, plus_constant (XEXP (x, 0), 8));
- else
- output_operand_lossage ("register or memory expression expected "
- "for 'M' output modifier");
- break;
-
- case 'Y':
- print_shift_count_operand (file, x);
- return;
- }
-
- switch (GET_CODE (x))
- {
- case REG:
- fprintf (file, "%s", reg_names[REGNO (x)]);
- break;
-
- case MEM:
- output_address (XEXP (x, 0));
- break;
-
- case CONST:
- case CODE_LABEL:
- case LABEL_REF:
- case SYMBOL_REF:
- output_addr_const (file, x);
- break;
-
- case CONST_INT:
- if (code == 'b')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
- else if (code == 'c')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xff) ^ 0x80) - 0x80);
- 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 if (code == 'i')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, HImode, 0));
- else if (code == 'j')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, HImode, -1));
- else if (code == 'k')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, SImode, 0));
- else if (code == 'm')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, SImode, -1));
- else if (code == 'o')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffffffff);
- else
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
- break;
-
- case CONST_DOUBLE:
- gcc_assert (GET_MODE (x) == VOIDmode);
- if (code == 'b')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xff);
- else if (code == 'x')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xffff);
- else if (code == 'h')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- ((CONST_DOUBLE_LOW (x) & 0xffff) ^ 0x8000) - 0x8000);
- else
- {
- if (code == 0)
- output_operand_lossage ("invalid constant - try using "
- "an output modifier");
- else
- output_operand_lossage ("invalid constant for output modifier '%c'",
- code);
- }
- break;
-
- default:
- if (code == 0)
- output_operand_lossage ("invalid expression - try using "
- "an output modifier");
- else
- output_operand_lossage ("invalid expression for output "
- "modifier '%c'", code);
- break;
- }
-}
-
-/* Target hook for assembling integer objects. We need to define it
- here to work a round a bug in some versions of GAS, which couldn't
- handle values smaller than INT_MIN when printed in decimal. */
-
-static bool
-s390_assemble_integer (rtx x, unsigned int size, int aligned_p)
-{
- if (size == 8 && aligned_p
- && GET_CODE (x) == CONST_INT && INTVAL (x) < INT_MIN)
- {
- fprintf (asm_out_file, "\t.quad\t" HOST_WIDE_INT_PRINT_HEX "\n",
- INTVAL (x));
- return true;
- }
- return default_assemble_integer (x, size, aligned_p);
-}
-
-/* Returns true if register REGNO is used for forming
- a memory address in expression X. */
-
-static bool
-reg_used_in_mem_p (int regno, rtx x)
-{
- enum rtx_code code = GET_CODE (x);
- int i, j;
- const char *fmt;
-
- if (code == MEM)
- {
- if (refers_to_regno_p (regno, regno+1,
- XEXP (x, 0), 0))
- return true;
- }
- else if (code == SET
- && GET_CODE (SET_DEST (x)) == PC)
- {
- if (refers_to_regno_p (regno, regno+1,
- SET_SRC (x), 0))
- return true;
- }
-
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e'
- && reg_used_in_mem_p (regno, XEXP (x, i)))
- return true;
-
- else if (fmt[i] == 'E')
- for (j = 0; j < XVECLEN (x, i); j++)
- if (reg_used_in_mem_p (regno, XVECEXP (x, i, j)))
- return true;
- }
- return false;
-}
-
-/* Returns true if expression DEP_RTX sets an address register
- used by instruction INSN to address memory. */
-
-static bool
-addr_generation_dependency_p (rtx dep_rtx, rtx insn)
-{
- rtx target, pat;
-
- if (GET_CODE (dep_rtx) == INSN)
- dep_rtx = PATTERN (dep_rtx);
-
- if (GET_CODE (dep_rtx) == SET)
- {
- target = SET_DEST (dep_rtx);
- if (GET_CODE (target) == STRICT_LOW_PART)
- target = XEXP (target, 0);
- while (GET_CODE (target) == SUBREG)
- target = SUBREG_REG (target);
-
- if (GET_CODE (target) == REG)
- {
- int regno = REGNO (target);
-
- if (s390_safe_attr_type (insn) == TYPE_LA)
- {
- pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL)
- {
- gcc_assert (XVECLEN (pat, 0) == 2);
- pat = XVECEXP (pat, 0, 0);
- }
- gcc_assert (GET_CODE (pat) == SET);
- return refers_to_regno_p (regno, regno+1, SET_SRC (pat), 0);
- }
- else if (get_attr_atype (insn) == ATYPE_AGEN)
- return reg_used_in_mem_p (regno, PATTERN (insn));
- }
- }
- return false;
-}
-
-/* Return 1, if dep_insn sets register used in insn in the agen unit. */
-
-int
-s390_agen_dep_p (rtx dep_insn, rtx insn)
-{
- rtx dep_rtx = PATTERN (dep_insn);
- int i;
-
- if (GET_CODE (dep_rtx) == SET
- && addr_generation_dependency_p (dep_rtx, insn))
- return 1;
- else if (GET_CODE (dep_rtx) == PARALLEL)
- {
- for (i = 0; i < XVECLEN (dep_rtx, 0); i++)
- {
- if (addr_generation_dependency_p (XVECEXP (dep_rtx, 0, i), insn))
- return 1;
- }
- }
- return 0;
-}
-
-
-/* A C statement (sans semicolon) to update the integer scheduling priority
- INSN_PRIORITY (INSN). Increase the priority to execute the INSN earlier,
- reduce the priority to execute INSN later. Do not define this macro if
- you do not need to adjust the scheduling priorities of insns.
-
- A STD instruction should be scheduled earlier,
- in order to use the bypass. */
-static int
-s390_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
-{
- if (! INSN_P (insn))
- return priority;
-
- if (s390_tune != PROCESSOR_2084_Z990
- && s390_tune != PROCESSOR_2094_Z9_109
- && s390_tune != PROCESSOR_2097_Z10
- && s390_tune != PROCESSOR_2817_Z196)
- return priority;
-
- switch (s390_safe_attr_type (insn))
- {
- case TYPE_FSTOREDF:
- case TYPE_FSTORESF:
- priority = priority << 3;
- break;
- case TYPE_STORE:
- case TYPE_STM:
- priority = priority << 1;
- break;
- default:
- break;
- }
- return priority;
-}
-
-
-/* The number of instructions that can be issued per cycle. */
-
-static int
-s390_issue_rate (void)
-{
- switch (s390_tune)
- {
- case PROCESSOR_2084_Z990:
- case PROCESSOR_2094_Z9_109:
- case PROCESSOR_2817_Z196:
- return 3;
- case PROCESSOR_2097_Z10:
- return 2;
- default:
- return 1;
- }
-}
-
-static int
-s390_first_cycle_multipass_dfa_lookahead (void)
-{
- return 4;
-}
-
-/* Annotate every literal pool reference in X by an UNSPEC_LTREF expression.
- Fix up MEMs as required. */
-
-static void
-annotate_constant_pool_refs (rtx *x)
-{
- int i, j;
- const char *fmt;
-
- gcc_assert (GET_CODE (*x) != SYMBOL_REF
- || !CONSTANT_POOL_ADDRESS_P (*x));
-
- /* Literal pool references can only occur inside a MEM ... */
- if (GET_CODE (*x) == MEM)
- {
- rtx memref = XEXP (*x, 0);
-
- if (GET_CODE (memref) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (memref))
- {
- rtx base = cfun->machine->base_reg;
- rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, memref, base),
- UNSPEC_LTREF);
-
- *x = replace_equiv_address (*x, addr);
- return;
- }
-
- if (GET_CODE (memref) == CONST
- && GET_CODE (XEXP (memref, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
- && GET_CODE (XEXP (XEXP (memref, 0), 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (memref, 0), 0)))
- {
- HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
- rtx sym = XEXP (XEXP (memref, 0), 0);
- rtx base = cfun->machine->base_reg;
- rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
- UNSPEC_LTREF);
-
- *x = replace_equiv_address (*x, plus_constant (addr, off));
- return;
- }
- }
-
- /* ... or a load-address type pattern. */
- if (GET_CODE (*x) == SET)
- {
- rtx addrref = SET_SRC (*x);
-
- if (GET_CODE (addrref) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (addrref))
- {
- rtx base = cfun->machine->base_reg;
- rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, addrref, base),
- UNSPEC_LTREF);
-
- SET_SRC (*x) = addr;
- return;
- }
-
- if (GET_CODE (addrref) == CONST
- && GET_CODE (XEXP (addrref, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
- && GET_CODE (XEXP (XEXP (addrref, 0), 0)) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (addrref, 0), 0)))
- {
- HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
- rtx sym = XEXP (XEXP (addrref, 0), 0);
- rtx base = cfun->machine->base_reg;
- rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
- UNSPEC_LTREF);
-
- SET_SRC (*x) = plus_constant (addr, off);
- return;
- }
- }
-
- /* Annotate LTREL_BASE as well. */
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_LTREL_BASE)
- {
- rtx base = cfun->machine->base_reg;
- *x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XVECEXP (*x, 0, 0), base),
- UNSPEC_LTREL_BASE);
- return;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (*x));
- for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- annotate_constant_pool_refs (&XEXP (*x, i));
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (*x, i); j++)
- annotate_constant_pool_refs (&XVECEXP (*x, i, j));
- }
- }
-}
-
-/* Split all branches that exceed the maximum distance.
- Returns true if this created a new literal pool entry. */
-
-static int
-s390_split_branches (void)
-{
- rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
- int new_literal = 0, ret;
- rtx insn, pat, tmp, target;
- rtx *label;
-
- /* We need correct insn addresses. */
-
- shorten_branches (get_insns ());
-
- /* Find all branches that exceed 64KB, and split them. */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) != JUMP_INSN)
- continue;
-
- pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
- pat = XVECEXP (pat, 0, 0);
- if (GET_CODE (pat) != SET || SET_DEST (pat) != pc_rtx)
- continue;
-
- if (GET_CODE (SET_SRC (pat)) == LABEL_REF)
- {
- label = &SET_SRC (pat);
- }
- else if (GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE)
- {
- if (GET_CODE (XEXP (SET_SRC (pat), 1)) == LABEL_REF)
- label = &XEXP (SET_SRC (pat), 1);
- else if (GET_CODE (XEXP (SET_SRC (pat), 2)) == LABEL_REF)
- label = &XEXP (SET_SRC (pat), 2);
- else
- continue;
- }
- else
- continue;
-
- if (get_attr_length (insn) <= 4)
- continue;
-
- /* We are going to use the return register as scratch register,
- make sure it will be saved/restored by the prologue/epilogue. */
- cfun_frame_layout.save_return_addr_p = 1;
-
- if (!flag_pic)
- {
- new_literal = 1;
- tmp = force_const_mem (Pmode, *label);
- tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
- INSN_ADDRESSES_NEW (tmp, -1);
- annotate_constant_pool_refs (&PATTERN (tmp));
-
- target = temp_reg;
- }
- else
- {
- new_literal = 1;
- target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, *label),
- UNSPEC_LTREL_OFFSET);
- target = gen_rtx_CONST (Pmode, target);
- target = force_const_mem (Pmode, target);
- tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
- INSN_ADDRESSES_NEW (tmp, -1);
- annotate_constant_pool_refs (&PATTERN (tmp));
-
- target = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XEXP (target, 0),
- cfun->machine->base_reg),
- UNSPEC_LTREL_BASE);
- target = gen_rtx_PLUS (Pmode, temp_reg, target);
- }
-
- ret = validate_change (insn, label, target, 0);
- gcc_assert (ret);
- }
-
- return new_literal;
-}
-
-
-/* Find an annotated literal pool symbol referenced in RTX X,
- and store it at REF. Will abort if X contains references to
- more than one such pool symbol; multiple references to the same
- symbol are allowed, however.
-
- The rtx pointed to by REF must be initialized to NULL_RTX
- by the caller before calling this routine. */
-
-static void
-find_constant_pool_ref (rtx x, rtx *ref)
-{
- int i, j;
- const char *fmt;
-
- /* Ignore LTREL_BASE references. */
- if (GET_CODE (x) == UNSPEC
- && XINT (x, 1) == UNSPEC_LTREL_BASE)
- return;
- /* Likewise POOL_ENTRY insns. */
- if (GET_CODE (x) == UNSPEC_VOLATILE
- && XINT (x, 1) == UNSPECV_POOL_ENTRY)
- return;
-
- gcc_assert (GET_CODE (x) != SYMBOL_REF
- || !CONSTANT_POOL_ADDRESS_P (x));
-
- if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_LTREF)
- {
- rtx sym = XVECEXP (x, 0, 0);
- gcc_assert (GET_CODE (sym) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (sym));
-
- if (*ref == NULL_RTX)
- *ref = sym;
- else
- gcc_assert (*ref == sym);
-
- return;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- find_constant_pool_ref (XEXP (x, i), ref);
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (x, i); j++)
- find_constant_pool_ref (XVECEXP (x, i, j), ref);
- }
- }
-}
-
-/* Replace every reference to the annotated literal pool
- symbol REF in X by its base plus OFFSET. */
-
-static void
-replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
-{
- int i, j;
- const char *fmt;
-
- gcc_assert (*x != ref);
-
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_LTREF
- && XVECEXP (*x, 0, 0) == ref)
- {
- *x = gen_rtx_PLUS (Pmode, XVECEXP (*x, 0, 1), offset);
- return;
- }
-
- if (GET_CODE (*x) == PLUS
- && GET_CODE (XEXP (*x, 1)) == CONST_INT
- && GET_CODE (XEXP (*x, 0)) == UNSPEC
- && XINT (XEXP (*x, 0), 1) == UNSPEC_LTREF
- && XVECEXP (XEXP (*x, 0), 0, 0) == ref)
- {
- rtx addr = gen_rtx_PLUS (Pmode, XVECEXP (XEXP (*x, 0), 0, 1), offset);
- *x = plus_constant (addr, INTVAL (XEXP (*x, 1)));
- return;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (*x));
- for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- replace_constant_pool_ref (&XEXP (*x, i), ref, offset);
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (*x, i); j++)
- replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
- }
- }
-}
-
-/* Check whether X contains an UNSPEC_LTREL_BASE.
- Return its constant pool symbol if found, NULL_RTX otherwise. */
-
-static rtx
-find_ltrel_base (rtx x)
-{
- int i, j;
- const char *fmt;
-
- if (GET_CODE (x) == UNSPEC
- && XINT (x, 1) == UNSPEC_LTREL_BASE)
- return XVECEXP (x, 0, 0);
-
- fmt = GET_RTX_FORMAT (GET_CODE (x));
- for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- rtx fnd = find_ltrel_base (XEXP (x, i));
- if (fnd)
- return fnd;
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (x, i); j++)
- {
- rtx fnd = find_ltrel_base (XVECEXP (x, i, j));
- if (fnd)
- return fnd;
- }
- }
- }
-
- return NULL_RTX;
-}
-
-/* Replace any occurrence of UNSPEC_LTREL_BASE in X with its base. */
-
-static void
-replace_ltrel_base (rtx *x)
-{
- int i, j;
- const char *fmt;
-
- if (GET_CODE (*x) == UNSPEC
- && XINT (*x, 1) == UNSPEC_LTREL_BASE)
- {
- *x = XVECEXP (*x, 0, 1);
- return;
- }
-
- fmt = GET_RTX_FORMAT (GET_CODE (*x));
- for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- replace_ltrel_base (&XEXP (*x, i));
- }
- else if (fmt[i] == 'E')
- {
- for (j = 0; j < XVECLEN (*x, i); j++)
- replace_ltrel_base (&XVECEXP (*x, i, j));
- }
- }
-}
-
-
-/* We keep a list of constants which we have to add to internal
- constant tables in the middle of large functions. */
-
-#define NR_C_MODES 11
-enum machine_mode constant_modes[NR_C_MODES] =
-{
- TFmode, TImode, TDmode,
- DFmode, DImode, DDmode,
- SFmode, SImode, SDmode,
- HImode,
- QImode
-};
-
-struct constant
-{
- struct constant *next;
- rtx value;
- rtx label;
-};
-
-struct constant_pool
-{
- struct constant_pool *next;
- rtx first_insn;
- rtx pool_insn;
- bitmap insns;
- rtx emit_pool_after;
-
- struct constant *constants[NR_C_MODES];
- struct constant *execute;
- rtx label;
- int size;
-};
-
-/* Allocate new constant_pool structure. */
-
-static struct constant_pool *
-s390_alloc_pool (void)
-{
- struct constant_pool *pool;
- int i;
-
- pool = (struct constant_pool *) xmalloc (sizeof *pool);
- pool->next = NULL;
- 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;
- pool->insns = BITMAP_ALLOC (NULL);
- pool->size = 0;
- pool->emit_pool_after = NULL_RTX;
-
- return pool;
-}
-
-/* Create new constant pool covering instructions starting at INSN
- and chain it to the end of POOL_LIST. */
-
-static struct constant_pool *
-s390_start_pool (struct constant_pool **pool_list, rtx insn)
-{
- struct constant_pool *pool, **prev;
-
- pool = s390_alloc_pool ();
- pool->first_insn = insn;
-
- for (prev = pool_list; *prev; prev = &(*prev)->next)
- ;
- *prev = pool;
-
- return pool;
-}
-
-/* End range of instructions covered by POOL at INSN and emit
- placeholder insn representing the pool. */
-
-static void
-s390_end_pool (struct constant_pool *pool, rtx insn)
-{
- rtx pool_size = GEN_INT (pool->size + 8 /* alignment slop */);
-
- if (!insn)
- insn = get_last_insn ();
-
- pool->pool_insn = emit_insn_after (gen_pool (pool_size), insn);
- INSN_ADDRESSES_NEW (pool->pool_insn, -1);
-}
-
-/* Add INSN to the list of insns covered by POOL. */
-
-static void
-s390_add_pool_insn (struct constant_pool *pool, rtx insn)
-{
- bitmap_set_bit (pool->insns, INSN_UID (insn));
-}
-
-/* Return pool out of POOL_LIST that covers INSN. */
-
-static struct constant_pool *
-s390_find_pool (struct constant_pool *pool_list, rtx insn)
-{
- struct constant_pool *pool;
-
- for (pool = pool_list; pool; pool = pool->next)
- if (bitmap_bit_p (pool->insns, INSN_UID (insn)))
- break;
-
- return pool;
-}
-
-/* Add constant VAL of mode MODE to the constant pool POOL. */
-
-static void
-s390_add_constant (struct constant_pool *pool, rtx val, enum machine_mode mode)
-{
- struct constant *c;
- int i;
-
- for (i = 0; i < NR_C_MODES; i++)
- if (constant_modes[i] == mode)
- break;
- gcc_assert (i != NR_C_MODES);
-
- for (c = pool->constants[i]; c != NULL; c = c->next)
- if (rtx_equal_p (val, c->value))
- break;
-
- if (c == NULL)
- {
- c = (struct constant *) xmalloc (sizeof *c);
- c->value = val;
- c->label = gen_label_rtx ();
- c->next = pool->constants[i];
- pool->constants[i] = c;
- pool->size += GET_MODE_SIZE (mode);
- }
-}
-
-/* Return an rtx that represents the offset of X from the start of
- pool POOL. */
-
-static rtx
-s390_pool_offset (struct constant_pool *pool, rtx x)
-{
- rtx label;
-
- label = gen_rtx_LABEL_REF (GET_MODE (x), pool->label);
- x = gen_rtx_UNSPEC (GET_MODE (x), gen_rtvec (2, x, label),
- UNSPEC_POOL_OFFSET);
- return gen_rtx_CONST (GET_MODE (x), x);
-}
-
-/* Find constant VAL of mode MODE in the constant pool POOL.
- Return an RTX describing the distance from the start of
- the pool to the location of the new constant. */
-
-static rtx
-s390_find_constant (struct constant_pool *pool, rtx val,
- enum machine_mode mode)
-{
- struct constant *c;
- int i;
-
- for (i = 0; i < NR_C_MODES; i++)
- if (constant_modes[i] == mode)
- break;
- gcc_assert (i != NR_C_MODES);
-
- for (c = pool->constants[i]; c != NULL; c = c->next)
- if (rtx_equal_p (val, c->value))
- break;
-
- gcc_assert (c);
-
- return s390_pool_offset (pool, gen_rtx_LABEL_REF (Pmode, c->label));
-}
-
-/* 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;
-}
-
-/* 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)
- {
- c = (struct constant *) xmalloc (sizeof *c);
- c->value = insn;
- c->label = gen_label_rtx ();
- c->next = pool->execute;
- pool->execute = c;
- pool->size += 6;
- }
-}
-
-/* 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;
-
- for (c = pool->execute; c != NULL; c = c->next)
- if (INSN_UID (insn) == INSN_UID (c->value))
- break;
-
- gcc_assert (c);
-
- return s390_pool_offset (pool, gen_rtx_LABEL_REF (Pmode, c->label));
-}
-
-/* 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 void
-s390_dump_pool (struct constant_pool *pool, bool remote_label)
-{
- struct constant *c;
- rtx insn = pool->pool_insn;
- int i;
-
- /* Switch to rodata section. */
- if (TARGET_CPU_ZARCH)
- {
- 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_align (GEN_INT (4)), insn);
- INSN_ADDRESSES_NEW (insn, -1);
-
- /* Emit pool base label. */
- if (!remote_label)
- {
- insn = emit_label_after (pool->label, insn);
- INSN_ADDRESSES_NEW (insn, -1);
- }
-
- /* Dump constants in descending alignment requirement order,
- ensuring proper alignment for every constant. */
- for (i = 0; i < NR_C_MODES; i++)
- for (c = pool->constants[i]; c; c = c->next)
- {
- /* Convert UNSPEC_LTREL_OFFSET unspecs to pool-relative references. */
- rtx value = copy_rtx (c->value);
- if (GET_CODE (value) == CONST
- && GET_CODE (XEXP (value, 0)) == UNSPEC
- && XINT (XEXP (value, 0), 1) == UNSPEC_LTREL_OFFSET
- && XVECLEN (XEXP (value, 0), 0) == 1)
- value = s390_pool_offset (pool, XVECEXP (XEXP (value, 0), 0, 0));
-
- insn = emit_label_after (c->label, insn);
- INSN_ADDRESSES_NEW (insn, -1);
-
- value = gen_rtx_UNSPEC_VOLATILE (constant_modes[i],
- gen_rtvec (1, value),
- UNSPECV_POOL_ENTRY);
- insn = emit_insn_after (value, insn);
- INSN_ADDRESSES_NEW (insn, -1);
- }
-
- /* 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)
- {
- 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);
-}
-
-/* Free all memory used by POOL. */
-
-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)
- {
- next = c->next;
- free (c);
- }
-
- BITMAP_FREE (pool->insns);
- free (pool);
-}
-
-
-/* Collect main literal pool. Return NULL on overflow. */
-
-static struct constant_pool *
-s390_mainpool_start (void)
-{
- struct constant_pool *pool;
- rtx insn;
-
- pool = s390_alloc_pool ();
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE
- && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL)
- {
- gcc_assert (!pool->pool_insn);
- pool->pool_insn = insn;
- }
-
- if (!TARGET_CPU_ZARCH && 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);
- if (pool_ref)
- {
- rtx constant = get_pool_constant (pool_ref);
- enum machine_mode mode = get_pool_mode (pool_ref);
- s390_add_constant (pool, constant, mode);
- }
- }
-
- /* If hot/cold partitioning is enabled we have to make sure that
- the literal pool is emitted in the same section where the
- initialization of the literal pool base pointer takes place.
- emit_pool_after is only used in the non-overflow case on non
- Z cpus where we can emit the literal pool at the end of the
- function body within the text section. */
- if (NOTE_P (insn)
- && NOTE_KIND (insn) == NOTE_INSN_SWITCH_TEXT_SECTIONS
- && !pool->emit_pool_after)
- pool->emit_pool_after = PREV_INSN (insn);
- }
-
- gcc_assert (pool->pool_insn || pool->size == 0);
-
- if (pool->size >= 4096)
- {
- /* We're going to chunkify the pool, so remove the main
- pool placeholder insn. */
- remove_insn (pool->pool_insn);
-
- s390_free_pool (pool);
- pool = NULL;
- }
-
- /* If the functions ends with the section where the literal pool
- should be emitted set the marker to its end. */
- if (pool && !pool->emit_pool_after)
- pool->emit_pool_after = get_last_insn ();
-
- return pool;
-}
-
-/* POOL holds the main literal pool as collected by s390_mainpool_start.
- Modify the current function to output the pool constants as well as
- the pool register setup instruction. */
-
-static void
-s390_mainpool_finish (struct constant_pool *pool)
-{
- rtx base_reg = cfun->machine->base_reg;
- rtx insn;
-
- /* If the pool is empty, we're done. */
- if (pool->size == 0)
- {
- /* We don't actually need a base register after all. */
- cfun->machine->base_reg = NULL_RTX;
-
- if (pool->pool_insn)
- remove_insn (pool->pool_insn);
- s390_free_pool (pool);
- return;
- }
-
- /* We need correct insn addresses. */
- shorten_branches (get_insns ());
-
- /* On zSeries, we use a LARL to load the pool register. The pool is
- located in the .rodata section, so we emit it after the function. */
- if (TARGET_CPU_ZARCH)
- {
- insn = gen_main_base_64 (base_reg, pool->label);
- insn = emit_insn_after (insn, pool->pool_insn);
- INSN_ADDRESSES_NEW (insn, -1);
- remove_insn (pool->pool_insn);
-
- insn = get_last_insn ();
- pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
- INSN_ADDRESSES_NEW (pool->pool_insn, -1);
-
- s390_dump_pool (pool, 0);
- }
-
- /* On S/390, if the total size of the function's code plus literal pool
- does not exceed 4096 bytes, we use BASR to set up a function base
- pointer, and emit the literal pool at the end of the function. */
- else if (INSN_ADDRESSES (INSN_UID (pool->emit_pool_after))
- + pool->size + 8 /* alignment slop */ < 4096)
- {
- insn = gen_main_base_31_small (base_reg, pool->label);
- insn = emit_insn_after (insn, pool->pool_insn);
- INSN_ADDRESSES_NEW (insn, -1);
- remove_insn (pool->pool_insn);
-
- insn = emit_label_after (pool->label, insn);
- INSN_ADDRESSES_NEW (insn, -1);
-
- /* emit_pool_after will be set by s390_mainpool_start to the
- last insn of the section where the literal pool should be
- emitted. */
- insn = pool->emit_pool_after;
-
- pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
- INSN_ADDRESSES_NEW (pool->pool_insn, -1);
-
- s390_dump_pool (pool, 1);
- }
-
- /* Otherwise, we emit an inline literal pool and use BASR to branch
- over it, setting up the pool register at the same time. */
- else
- {
- rtx pool_end = gen_label_rtx ();
-
- insn = gen_main_base_31_large (base_reg, pool->label, pool_end);
- insn = emit_jump_insn_after (insn, pool->pool_insn);
- JUMP_LABEL (insn) = pool_end;
- INSN_ADDRESSES_NEW (insn, -1);
- remove_insn (pool->pool_insn);
-
- insn = emit_label_after (pool->label, insn);
- INSN_ADDRESSES_NEW (insn, -1);
-
- pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
- INSN_ADDRESSES_NEW (pool->pool_insn, -1);
-
- insn = emit_label_after (pool_end, pool->pool_insn);
- INSN_ADDRESSES_NEW (insn, -1);
-
- s390_dump_pool (pool, 1);
- }
-
-
- /* Replace all literal pool references. */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn));
-
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
- {
- rtx addr, pool_ref = NULL_RTX;
- find_constant_pool_ref (PATTERN (insn), &pool_ref);
- if (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;
- }
- }
- }
-
-
- /* Free the pool. */
- s390_free_pool (pool);
-}
-
-/* POOL holds the main literal pool as collected by s390_mainpool_start.
- We have decided we cannot use this pool, so revert all changes
- to the current function that were done by s390_mainpool_start. */
-static void
-s390_mainpool_cancel (struct constant_pool *pool)
-{
- /* We didn't actually change the instruction stream, so simply
- free the pool memory. */
- s390_free_pool (pool);
-}
-
-
-/* Chunkify the literal pool. */
-
-#define S390_POOL_CHUNK_MIN 0xc00
-#define S390_POOL_CHUNK_MAX 0xe00
-
-static struct constant_pool *
-s390_chunkify_start (void)
-{
- struct constant_pool *curr_pool = NULL, *pool_list = NULL;
- int extra_size = 0;
- bitmap far_labels;
- rtx pending_ltrel = NULL_RTX;
- rtx insn;
-
- rtx (*gen_reload_base) (rtx, rtx) =
- TARGET_CPU_ZARCH? gen_reload_base_64 : gen_reload_base_31;
-
-
- /* We need correct insn addresses. */
-
- shorten_branches (get_insns ());
-
- /* Scan all insns and move literals to pool chunks. */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- bool section_switch_p = false;
-
- /* Check for pending LTREL_BASE. */
- if (INSN_P (insn))
- {
- rtx ltrel_base = find_ltrel_base (PATTERN (insn));
- if (ltrel_base)
- {
- gcc_assert (ltrel_base == pending_ltrel);
- pending_ltrel = NULL_RTX;
- }
- }
-
- if (!TARGET_CPU_ZARCH && 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 || CALL_P (insn))
- {
- rtx pool_ref = NULL_RTX;
- find_constant_pool_ref (PATTERN (insn), &pool_ref);
- if (pool_ref)
- {
- rtx constant = get_pool_constant (pool_ref);
- enum machine_mode mode = get_pool_mode (pool_ref);
-
- if (!curr_pool)
- curr_pool = s390_start_pool (&pool_list, insn);
-
- s390_add_constant (curr_pool, constant, mode);
- s390_add_pool_insn (curr_pool, insn);
-
- /* Don't split the pool chunk between a LTREL_OFFSET load
- and the corresponding LTREL_BASE. */
- if (GET_CODE (constant) == CONST
- && GET_CODE (XEXP (constant, 0)) == UNSPEC
- && XINT (XEXP (constant, 0), 1) == UNSPEC_LTREL_OFFSET)
- {
- gcc_assert (!pending_ltrel);
- pending_ltrel = pool_ref;
- }
- }
- }
-
- if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CODE_LABEL)
- {
- if (curr_pool)
- s390_add_pool_insn (curr_pool, insn);
- /* An LTREL_BASE must follow within the same basic block. */
- gcc_assert (!pending_ltrel);
- }
-
- if (NOTE_P (insn))
- switch (NOTE_KIND (insn))
- {
- case NOTE_INSN_SWITCH_TEXT_SECTIONS:
- section_switch_p = true;
- break;
- case NOTE_INSN_VAR_LOCATION:
- case NOTE_INSN_CALL_ARG_LOCATION:
- continue;
- default:
- break;
- }
-
- if (!curr_pool
- || INSN_ADDRESSES_SIZE () <= (size_t) INSN_UID (insn)
- || INSN_ADDRESSES (INSN_UID (insn)) == -1)
- continue;
-
- if (TARGET_CPU_ZARCH)
- {
- if (curr_pool->size < S390_POOL_CHUNK_MAX)
- continue;
-
- s390_end_pool (curr_pool, NULL_RTX);
- curr_pool = NULL;
- }
- else
- {
- int chunk_size = INSN_ADDRESSES (INSN_UID (insn))
- - INSN_ADDRESSES (INSN_UID (curr_pool->first_insn))
- + extra_size;
-
- /* We will later have to insert base register reload insns.
- Those will have an effect on code size, which we need to
- consider here. This calculation makes rather pessimistic
- worst-case assumptions. */
- if (GET_CODE (insn) == CODE_LABEL)
- extra_size += 6;
-
- if (chunk_size < S390_POOL_CHUNK_MIN
- && curr_pool->size < S390_POOL_CHUNK_MIN
- && !section_switch_p)
- continue;
-
- /* Pool chunks can only be inserted after BARRIERs ... */
- if (GET_CODE (insn) == BARRIER)
- {
- s390_end_pool (curr_pool, insn);
- curr_pool = NULL;
- extra_size = 0;
- }
-
- /* ... so if we don't find one in time, create one. */
- else if (chunk_size > S390_POOL_CHUNK_MAX
- || curr_pool->size > S390_POOL_CHUNK_MAX
- || section_switch_p)
- {
- rtx label, jump, barrier, next, prev;
-
- if (!section_switch_p)
- {
- /* We can insert the barrier only after a 'real' insn. */
- if (GET_CODE (insn) != INSN && GET_CODE (insn) != CALL_INSN)
- continue;
- if (get_attr_length (insn) == 0)
- continue;
- /* Don't separate LTREL_BASE from the corresponding
- LTREL_OFFSET load. */
- if (pending_ltrel)
- continue;
- next = insn;
- do
- {
- insn = next;
- next = NEXT_INSN (insn);
- }
- while (next
- && NOTE_P (next)
- && (NOTE_KIND (next) == NOTE_INSN_VAR_LOCATION
- || NOTE_KIND (next) == NOTE_INSN_CALL_ARG_LOCATION));
- }
- else
- {
- gcc_assert (!pending_ltrel);
-
- /* The old pool has to end before the section switch
- note in order to make it part of the current
- section. */
- insn = PREV_INSN (insn);
- }
-
- label = gen_label_rtx ();
- prev = insn;
- if (prev && NOTE_P (prev))
- prev = prev_nonnote_insn (prev);
- if (prev)
- jump = emit_jump_insn_after_setloc (gen_jump (label), insn,
- INSN_LOCATOR (prev));
- else
- jump = emit_jump_insn_after_noloc (gen_jump (label), insn);
- barrier = emit_barrier_after (jump);
- insn = emit_label_after (label, barrier);
- JUMP_LABEL (jump) = label;
- LABEL_NUSES (label) = 1;
-
- INSN_ADDRESSES_NEW (jump, -1);
- INSN_ADDRESSES_NEW (barrier, -1);
- INSN_ADDRESSES_NEW (insn, -1);
-
- s390_end_pool (curr_pool, barrier);
- curr_pool = NULL;
- extra_size = 0;
- }
- }
- }
-
- if (curr_pool)
- s390_end_pool (curr_pool, NULL_RTX);
- gcc_assert (!pending_ltrel);
-
- /* Find all labels that are branched into
- from an insn belonging to a different chunk. */
-
- far_labels = BITMAP_ALLOC (NULL);
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- /* Labels marked with LABEL_PRESERVE_P can be target
- of non-local jumps, so we have to mark them.
- The same holds for named labels.
-
- Don't do that, however, if it is the label before
- a jump table. */
-
- if (GET_CODE (insn) == CODE_LABEL
- && (LABEL_PRESERVE_P (insn) || LABEL_NAME (insn)))
- {
- rtx vec_insn = next_real_insn (insn);
- rtx vec_pat = vec_insn && GET_CODE (vec_insn) == JUMP_INSN ?
- PATTERN (vec_insn) : NULL_RTX;
- if (!vec_pat
- || !(GET_CODE (vec_pat) == ADDR_VEC
- || GET_CODE (vec_pat) == ADDR_DIFF_VEC))
- bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (insn));
- }
-
- /* If we have a direct jump (conditional or unconditional)
- or a casesi jump, check all potential targets. */
- else if (GET_CODE (insn) == JUMP_INSN)
- {
- rtx pat = PATTERN (insn);
- if (GET_CODE (pat) == PARALLEL && XVECLEN (pat, 0) > 2)
- pat = XVECEXP (pat, 0, 0);
-
- if (GET_CODE (pat) == SET)
- {
- rtx label = JUMP_LABEL (insn);
- if (label)
- {
- if (s390_find_pool (pool_list, label)
- != s390_find_pool (pool_list, insn))
- bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
- }
- }
- else if (GET_CODE (pat) == PARALLEL
- && XVECLEN (pat, 0) == 2
- && GET_CODE (XVECEXP (pat, 0, 0)) == SET
- && GET_CODE (XVECEXP (pat, 0, 1)) == USE
- && GET_CODE (XEXP (XVECEXP (pat, 0, 1), 0)) == LABEL_REF)
- {
- /* Find the jump table used by this casesi jump. */
- rtx vec_label = XEXP (XEXP (XVECEXP (pat, 0, 1), 0), 0);
- rtx vec_insn = next_real_insn (vec_label);
- rtx vec_pat = vec_insn && GET_CODE (vec_insn) == JUMP_INSN ?
- PATTERN (vec_insn) : NULL_RTX;
- if (vec_pat
- && (GET_CODE (vec_pat) == ADDR_VEC
- || GET_CODE (vec_pat) == ADDR_DIFF_VEC))
- {
- int i, diff_p = GET_CODE (vec_pat) == ADDR_DIFF_VEC;
-
- for (i = 0; i < XVECLEN (vec_pat, diff_p); i++)
- {
- rtx label = XEXP (XVECEXP (vec_pat, diff_p, i), 0);
-
- if (s390_find_pool (pool_list, label)
- != s390_find_pool (pool_list, insn))
- bitmap_set_bit (far_labels, CODE_LABEL_NUMBER (label));
- }
- }
- }
- }
- }
-
- /* Insert base register reload insns before every pool. */
-
- for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
- {
- rtx new_insn = gen_reload_base (cfun->machine->base_reg,
- curr_pool->label);
- rtx insn = curr_pool->first_insn;
- INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
- }
-
- /* Insert base register reload insns at every far label. */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (GET_CODE (insn) == CODE_LABEL
- && bitmap_bit_p (far_labels, CODE_LABEL_NUMBER (insn)))
- {
- struct constant_pool *pool = s390_find_pool (pool_list, insn);
- if (pool)
- {
- rtx new_insn = gen_reload_base (cfun->machine->base_reg,
- pool->label);
- INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
- }
- }
-
-
- BITMAP_FREE (far_labels);
-
-
- /* Recompute insn addresses. */
-
- init_insn_lengths ();
- shorten_branches (get_insns ());
-
- return pool_list;
-}
-
-/* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
- After we have decided to use this list, finish implementing
- all changes to the current function as required. */
-
-static void
-s390_chunkify_finish (struct constant_pool *pool_list)
-{
- struct constant_pool *curr_pool = NULL;
- rtx insn;
-
-
- /* Replace all literal pool references. */
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn));
-
- curr_pool = s390_find_pool (pool_list, insn);
- if (!curr_pool)
- continue;
-
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
- {
- rtx addr, pool_ref = NULL_RTX;
- find_constant_pool_ref (PATTERN (insn), &pool_ref);
- if (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;
- }
- }
- }
-
- /* Dump out all literal pools. */
-
- for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
- s390_dump_pool (curr_pool, 0);
-
- /* Free pool list. */
-
- while (pool_list)
- {
- struct constant_pool *next = pool_list->next;
- s390_free_pool (pool_list);
- pool_list = next;
- }
-}
-
-/* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
- We have decided we cannot use this list, so revert all changes
- to the current function that were done by s390_chunkify_start. */
-
-static void
-s390_chunkify_cancel (struct constant_pool *pool_list)
-{
- struct constant_pool *curr_pool = NULL;
- rtx insn;
-
- /* Remove all pool placeholder insns. */
-
- for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
- {
- /* Did we insert an extra barrier? Remove it. */
- rtx barrier = PREV_INSN (curr_pool->pool_insn);
- rtx jump = barrier? PREV_INSN (barrier) : NULL_RTX;
- rtx label = NEXT_INSN (curr_pool->pool_insn);
-
- if (jump && GET_CODE (jump) == JUMP_INSN
- && barrier && GET_CODE (barrier) == BARRIER
- && label && GET_CODE (label) == CODE_LABEL
- && GET_CODE (PATTERN (jump)) == SET
- && SET_DEST (PATTERN (jump)) == pc_rtx
- && GET_CODE (SET_SRC (PATTERN (jump))) == LABEL_REF
- && XEXP (SET_SRC (PATTERN (jump)), 0) == label)
- {
- remove_insn (jump);
- remove_insn (barrier);
- remove_insn (label);
- }
-
- remove_insn (curr_pool->pool_insn);
- }
-
- /* Remove all base register reload insns. */
-
- for (insn = get_insns (); insn; )
- {
- rtx next_insn = NEXT_INSN (insn);
-
- if (GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
- && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPEC_RELOAD_BASE)
- remove_insn (insn);
-
- insn = next_insn;
- }
-
- /* Free pool list. */
-
- while (pool_list)
- {
- struct constant_pool *next = pool_list->next;
- s390_free_pool (pool_list);
- pool_list = next;
- }
-}
-
-/* Output the constant pool entry EXP in mode MODE with alignment ALIGN. */
-
-void
-s390_output_pool_entry (rtx exp, enum machine_mode mode, unsigned int align)
-{
- REAL_VALUE_TYPE r;
-
- switch (GET_MODE_CLASS (mode))
- {
- case MODE_FLOAT:
- case MODE_DECIMAL_FLOAT:
- gcc_assert (GET_CODE (exp) == CONST_DOUBLE);
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, exp);
- assemble_real (r, mode, align);
- break;
-
- case MODE_INT:
- assemble_integer (exp, GET_MODE_SIZE (mode), align, 1);
- mark_symbol_refs_as_used (exp);
- break;
-
- default:
- gcc_unreachable ();
- }
-}
-
-
-/* Return an RTL expression representing the value of the return address
- for the frame COUNT steps up from the current frame. FRAME is the
- frame pointer of that frame. */
-
-rtx
-s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
-{
- int offset;
- rtx addr;
-
- /* Without backchain, we fail for all but the current frame. */
-
- if (!TARGET_BACKCHAIN && count > 0)
- return NULL_RTX;
-
- /* For the current frame, we need to make sure the initial
- value of RETURN_REGNUM is actually saved. */
-
- if (count == 0)
- {
- /* On non-z architectures branch splitting could overwrite r14. */
- if (TARGET_CPU_ZARCH)
- return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
- else
- {
- cfun_frame_layout.save_return_addr_p = true;
- return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
- }
- }
-
- if (TARGET_PACKED_STACK)
- offset = -2 * UNITS_PER_LONG;
- else
- offset = RETURN_REGNUM * UNITS_PER_LONG;
-
- addr = plus_constant (frame, offset);
- addr = memory_address (Pmode, addr);
- return gen_rtx_MEM (Pmode, addr);
-}
-
-/* Return an RTL expression representing the back chain stored in
- the current stack frame. */
-
-rtx
-s390_back_chain_rtx (void)
-{
- rtx chain;
-
- gcc_assert (TARGET_BACKCHAIN);
-
- if (TARGET_PACKED_STACK)
- chain = plus_constant (stack_pointer_rtx,
- STACK_POINTER_OFFSET - UNITS_PER_LONG);
- else
- chain = stack_pointer_rtx;
-
- chain = gen_rtx_MEM (Pmode, chain);
- return chain;
-}
-
-/* Find first call clobbered register unused in a function.
- This could be used as base register in a leaf function
- or for holding the return address before epilogue. */
-
-static int
-find_unused_clobbered_reg (void)
-{
- int i;
- for (i = 0; i < 6; i++)
- if (!df_regs_ever_live_p (i))
- return i;
- return 0;
-}
-
-
-/* Helper function for s390_regs_ever_clobbered. Sets the fields in DATA for all
- clobbered hard regs in SETREG. */
-
-static void
-s390_reg_clobbered_rtx (rtx setreg, const_rtx set_insn ATTRIBUTE_UNUSED, void *data)
-{
- int *regs_ever_clobbered = (int *)data;
- unsigned int i, regno;
- enum machine_mode mode = GET_MODE (setreg);
-
- if (GET_CODE (setreg) == SUBREG)
- {
- rtx inner = SUBREG_REG (setreg);
- if (!GENERAL_REG_P (inner))
- return;
- regno = subreg_regno (setreg);
- }
- else if (GENERAL_REG_P (setreg))
- regno = REGNO (setreg);
- else
- return;
-
- for (i = regno;
- i < regno + HARD_REGNO_NREGS (regno, mode);
- i++)
- regs_ever_clobbered[i] = 1;
-}
-
-/* Walks through all basic blocks of the current function looking
- for clobbered hard regs using s390_reg_clobbered_rtx. The fields
- of the passed integer array REGS_EVER_CLOBBERED are set to one for
- each of those regs. */
-
-static void
-s390_regs_ever_clobbered (int *regs_ever_clobbered)
-{
- basic_block cur_bb;
- rtx cur_insn;
- unsigned int i;
-
- memset (regs_ever_clobbered, 0, 16 * sizeof (int));
-
- /* For non-leaf functions we have to consider all call clobbered regs to be
- clobbered. */
- if (!current_function_is_leaf)
- {
- for (i = 0; i < 16; i++)
- regs_ever_clobbered[i] = call_really_used_regs[i];
- }
-
- /* Make the "magic" eh_return registers live if necessary. For regs_ever_live
- this work is done by liveness analysis (mark_regs_live_at_end).
- Special care is needed for functions containing landing pads. Landing pads
- may use the eh registers, but the code which sets these registers is not
- contained in that function. Hence s390_regs_ever_clobbered is not able to
- deal with this automatically. */
- if (crtl->calls_eh_return || cfun->machine->has_landing_pad_p)
- for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM ; i++)
- if (crtl->calls_eh_return
- || (cfun->machine->has_landing_pad_p
- && df_regs_ever_live_p (EH_RETURN_DATA_REGNO (i))))
- regs_ever_clobbered[EH_RETURN_DATA_REGNO (i)] = 1;
-
- /* For nonlocal gotos all call-saved registers have to be saved.
- This flag is also set for the unwinding code in libgcc.
- See expand_builtin_unwind_init. For regs_ever_live this is done by
- reload. */
- if (cfun->has_nonlocal_label)
- for (i = 0; i < 16; i++)
- if (!call_really_used_regs[i])
- regs_ever_clobbered[i] = 1;
-
- FOR_EACH_BB (cur_bb)
- {
- FOR_BB_INSNS (cur_bb, cur_insn)
- {
- if (INSN_P (cur_insn))
- note_stores (PATTERN (cur_insn),
- s390_reg_clobbered_rtx,
- regs_ever_clobbered);
- }
- }
-}
-
-/* Determine the frame area which actually has to be accessed
- in the function epilogue. The values are stored at the
- given pointers AREA_BOTTOM (address of the lowest used stack
- address) and AREA_TOP (address of the first item which does
- not belong to the stack frame). */
-
-static void
-s390_frame_area (int *area_bottom, int *area_top)
-{
- int b, t;
- int i;
-
- b = INT_MAX;
- t = INT_MIN;
-
- if (cfun_frame_layout.first_restore_gpr != -1)
- {
- b = (cfun_frame_layout.gprs_offset
- + cfun_frame_layout.first_restore_gpr * UNITS_PER_LONG);
- t = b + (cfun_frame_layout.last_restore_gpr
- - cfun_frame_layout.first_restore_gpr + 1) * UNITS_PER_LONG;
- }
-
- if (TARGET_64BIT && cfun_save_high_fprs_p)
- {
- b = MIN (b, cfun_frame_layout.f8_offset);
- t = MAX (t, (cfun_frame_layout.f8_offset
- + cfun_frame_layout.high_fprs * 8));
- }
-
- if (!TARGET_64BIT)
- for (i = 2; i < 4; i++)
- if (cfun_fpr_bit_p (i))
- {
- b = MIN (b, cfun_frame_layout.f4_offset + (i - 2) * 8);
- t = MAX (t, cfun_frame_layout.f4_offset + (i - 1) * 8);
- }
-
- *area_bottom = b;
- *area_top = t;
-}
-
-/* Fill cfun->machine with info about register usage of current function.
- Return in CLOBBERED_REGS which GPRs are currently considered set. */
-
-static void
-s390_register_info (int clobbered_regs[])
-{
- int i, j;
-
- /* fprs 8 - 15 are call saved for 64 Bit ABI. */
- cfun_frame_layout.fpr_bitmap = 0;
- cfun_frame_layout.high_fprs = 0;
- if (TARGET_64BIT)
- for (i = 24; i < 32; i++)
- if (df_regs_ever_live_p (i) && !global_regs[i])
- {
- cfun_set_fpr_bit (i - 16);
- cfun_frame_layout.high_fprs++;
- }
-
- /* Find first and last gpr to be saved. We trust regs_ever_live
- data, except that we don't save and restore global registers.
-
- Also, all registers with special meaning to the compiler need
- to be handled extra. */
-
- s390_regs_ever_clobbered (clobbered_regs);
-
- for (i = 0; i < 16; i++)
- clobbered_regs[i] = clobbered_regs[i] && !global_regs[i] && !fixed_regs[i];
-
- if (frame_pointer_needed)
- clobbered_regs[HARD_FRAME_POINTER_REGNUM] = 1;
-
- if (flag_pic)
- clobbered_regs[PIC_OFFSET_TABLE_REGNUM]
- |= df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM);
-
- clobbered_regs[BASE_REGNUM]
- |= (cfun->machine->base_reg
- && REGNO (cfun->machine->base_reg) == BASE_REGNUM);
-
- clobbered_regs[RETURN_REGNUM]
- |= (!current_function_is_leaf
- || TARGET_TPF_PROFILING
- || cfun->machine->split_branches_pending_p
- || cfun_frame_layout.save_return_addr_p
- || crtl->calls_eh_return
- || cfun->stdarg);
-
- clobbered_regs[STACK_POINTER_REGNUM]
- |= (!current_function_is_leaf
- || TARGET_TPF_PROFILING
- || cfun_save_high_fprs_p
- || get_frame_size () > 0
- || cfun->calls_alloca
- || cfun->stdarg);
-
- for (i = 6; i < 16; i++)
- if (df_regs_ever_live_p (i) || clobbered_regs[i])
- break;
- for (j = 15; j > i; j--)
- if (df_regs_ever_live_p (j) || clobbered_regs[j])
- break;
-
- if (i == 16)
- {
- /* Nothing to save/restore. */
- cfun_frame_layout.first_save_gpr_slot = -1;
- cfun_frame_layout.last_save_gpr_slot = -1;
- cfun_frame_layout.first_save_gpr = -1;
- cfun_frame_layout.first_restore_gpr = -1;
- cfun_frame_layout.last_save_gpr = -1;
- cfun_frame_layout.last_restore_gpr = -1;
- }
- else
- {
- /* Save slots for gprs from i to j. */
- cfun_frame_layout.first_save_gpr_slot = i;
- cfun_frame_layout.last_save_gpr_slot = j;
-
- for (i = cfun_frame_layout.first_save_gpr_slot;
- i < cfun_frame_layout.last_save_gpr_slot + 1;
- i++)
- if (clobbered_regs[i])
- break;
-
- for (j = cfun_frame_layout.last_save_gpr_slot; j > i; j--)
- if (clobbered_regs[j])
- break;
-
- if (i == cfun_frame_layout.last_save_gpr_slot + 1)
- {
- /* Nothing to save/restore. */
- cfun_frame_layout.first_save_gpr = -1;
- cfun_frame_layout.first_restore_gpr = -1;
- cfun_frame_layout.last_save_gpr = -1;
- cfun_frame_layout.last_restore_gpr = -1;
- }
- else
- {
- /* Save / Restore from gpr i to j. */
- cfun_frame_layout.first_save_gpr = i;
- cfun_frame_layout.first_restore_gpr = i;
- cfun_frame_layout.last_save_gpr = j;
- cfun_frame_layout.last_restore_gpr = j;
- }
- }
-
- if (cfun->stdarg)
- {
- /* Varargs functions need to save gprs 2 to 6. */
- if (cfun->va_list_gpr_size
- && crtl->args.info.gprs < GP_ARG_NUM_REG)
- {
- int min_gpr = crtl->args.info.gprs;
- int max_gpr = min_gpr + cfun->va_list_gpr_size;
- if (max_gpr > GP_ARG_NUM_REG)
- max_gpr = GP_ARG_NUM_REG;
-
- if (cfun_frame_layout.first_save_gpr == -1
- || cfun_frame_layout.first_save_gpr > 2 + min_gpr)
- {
- cfun_frame_layout.first_save_gpr = 2 + min_gpr;
- cfun_frame_layout.first_save_gpr_slot = 2 + min_gpr;
- }
-
- if (cfun_frame_layout.last_save_gpr == -1
- || cfun_frame_layout.last_save_gpr < 2 + max_gpr - 1)
- {
- cfun_frame_layout.last_save_gpr = 2 + max_gpr - 1;
- cfun_frame_layout.last_save_gpr_slot = 2 + max_gpr - 1;
- }
- }
-
- /* Mark f0, f2 for 31 bit and f0-f4 for 64 bit to be saved. */
- if (TARGET_HARD_FLOAT && cfun->va_list_fpr_size
- && crtl->args.info.fprs < FP_ARG_NUM_REG)
- {
- int min_fpr = crtl->args.info.fprs;
- int max_fpr = min_fpr + cfun->va_list_fpr_size;
- if (max_fpr > FP_ARG_NUM_REG)
- max_fpr = FP_ARG_NUM_REG;
-
- /* ??? This is currently required to ensure proper location
- of the fpr save slots within the va_list save area. */
- if (TARGET_PACKED_STACK)
- min_fpr = 0;
-
- for (i = min_fpr; i < max_fpr; i++)
- cfun_set_fpr_bit (i);
- }
- }
-
- if (!TARGET_64BIT)
- for (i = 2; i < 4; i++)
- if (df_regs_ever_live_p (i + 16) && !global_regs[i + 16])
- cfun_set_fpr_bit (i);
-}
-
-/* Fill cfun->machine with info about frame of current function. */
-
-static void
-s390_frame_info (void)
-{
- int i;
-
- cfun_frame_layout.frame_size = get_frame_size ();
- if (!TARGET_64BIT && cfun_frame_layout.frame_size > 0x7fff0000)
- fatal_error ("total size of local variables exceeds architecture limit");
-
- if (!TARGET_PACKED_STACK)
- {
- cfun_frame_layout.backchain_offset = 0;
- cfun_frame_layout.f0_offset = 16 * UNITS_PER_LONG;
- cfun_frame_layout.f4_offset = cfun_frame_layout.f0_offset + 2 * 8;
- cfun_frame_layout.f8_offset = -cfun_frame_layout.high_fprs * 8;
- cfun_frame_layout.gprs_offset = (cfun_frame_layout.first_save_gpr_slot
- * UNITS_PER_LONG);
- }
- else if (TARGET_BACKCHAIN) /* kernel stack layout */
- {
- cfun_frame_layout.backchain_offset = (STACK_POINTER_OFFSET
- - UNITS_PER_LONG);
- cfun_frame_layout.gprs_offset
- = (cfun_frame_layout.backchain_offset
- - (STACK_POINTER_REGNUM - cfun_frame_layout.first_save_gpr_slot + 1)
- * UNITS_PER_LONG);
-
- if (TARGET_64BIT)
- {
- cfun_frame_layout.f4_offset
- = (cfun_frame_layout.gprs_offset
- - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
-
- cfun_frame_layout.f0_offset
- = (cfun_frame_layout.f4_offset
- - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
- }
- else
- {
- /* On 31 bit we have to care about alignment of the
- floating point regs to provide fastest access. */
- cfun_frame_layout.f0_offset
- = ((cfun_frame_layout.gprs_offset
- & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1))
- - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
-
- cfun_frame_layout.f4_offset
- = (cfun_frame_layout.f0_offset
- - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
- }
- }
- else /* no backchain */
- {
- cfun_frame_layout.f4_offset
- = (STACK_POINTER_OFFSET
- - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
-
- cfun_frame_layout.f0_offset
- = (cfun_frame_layout.f4_offset
- - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
-
- cfun_frame_layout.gprs_offset
- = cfun_frame_layout.f0_offset - cfun_gprs_save_area_size;
- }
-
- if (current_function_is_leaf
- && !TARGET_TPF_PROFILING
- && cfun_frame_layout.frame_size == 0
- && !cfun_save_high_fprs_p
- && !cfun->calls_alloca
- && !cfun->stdarg)
- return;
-
- if (!TARGET_PACKED_STACK)
- cfun_frame_layout.frame_size += (STACK_POINTER_OFFSET
- + crtl->outgoing_args_size
- + cfun_frame_layout.high_fprs * 8);
- else
- {
- if (TARGET_BACKCHAIN)
- cfun_frame_layout.frame_size += UNITS_PER_LONG;
-
- /* No alignment trouble here because f8-f15 are only saved under
- 64 bit. */
- cfun_frame_layout.f8_offset = (MIN (MIN (cfun_frame_layout.f0_offset,
- cfun_frame_layout.f4_offset),
- cfun_frame_layout.gprs_offset)
- - cfun_frame_layout.high_fprs * 8);
-
- cfun_frame_layout.frame_size += cfun_frame_layout.high_fprs * 8;
-
- for (i = 0; i < 8; i++)
- if (cfun_fpr_bit_p (i))
- cfun_frame_layout.frame_size += 8;
-
- cfun_frame_layout.frame_size += cfun_gprs_save_area_size;
-
- /* If under 31 bit an odd number of gprs has to be saved we have to adjust
- the frame size to sustain 8 byte alignment of stack frames. */
- cfun_frame_layout.frame_size = ((cfun_frame_layout.frame_size +
- STACK_BOUNDARY / BITS_PER_UNIT - 1)
- & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
-
- cfun_frame_layout.frame_size += crtl->outgoing_args_size;
- }
-}
-
-/* Generate frame layout. Fills in register and frame data for the current
- function in cfun->machine. This routine can be called multiple times;
- it will re-do the complete frame layout every time. */
-
-static void
-s390_init_frame_layout (void)
-{
- HOST_WIDE_INT frame_size;
- int base_used;
- int clobbered_regs[16];
-
- /* On S/390 machines, we may need to perform branch splitting, which
- will require both base and return address register. We have no
- choice but to assume we're going to need them until right at the
- end of the machine dependent reorg phase. */
- if (!TARGET_CPU_ZARCH)
- cfun->machine->split_branches_pending_p = true;
-
- do
- {
- frame_size = cfun_frame_layout.frame_size;
-
- /* Try to predict whether we'll need the base register. */
- base_used = cfun->machine->split_branches_pending_p
- || crtl->uses_const_pool
- || (!DISP_IN_RANGE (frame_size)
- && !CONST_OK_FOR_K (frame_size));
-
- /* Decide which register to use as literal pool base. In small
- leaf functions, try to use an unused call-clobbered register
- as base register to avoid save/restore overhead. */
- if (!base_used)
- cfun->machine->base_reg = NULL_RTX;
- else if (current_function_is_leaf && !df_regs_ever_live_p (5))
- cfun->machine->base_reg = gen_rtx_REG (Pmode, 5);
- else
- cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM);
-
- s390_register_info (clobbered_regs);
- s390_frame_info ();
- }
- while (frame_size != cfun_frame_layout.frame_size);
-}
-
-/* Update frame layout. Recompute actual register save data based on
- current info and update regs_ever_live for the special registers.
- May be called multiple times, but may never cause *more* registers
- to be saved than s390_init_frame_layout allocated room for. */
-
-static void
-s390_update_frame_layout (void)
-{
- int clobbered_regs[16];
-
- s390_register_info (clobbered_regs);
-
- df_set_regs_ever_live (BASE_REGNUM,
- clobbered_regs[BASE_REGNUM] ? true : false);
- df_set_regs_ever_live (RETURN_REGNUM,
- clobbered_regs[RETURN_REGNUM] ? true : false);
- df_set_regs_ever_live (STACK_POINTER_REGNUM,
- clobbered_regs[STACK_POINTER_REGNUM] ? true : false);
-
- if (cfun->machine->base_reg)
- df_set_regs_ever_live (REGNO (cfun->machine->base_reg), true);
-}
-
-/* Return true if it is legal to put a value with MODE into REGNO. */
-
-bool
-s390_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
-{
- switch (REGNO_REG_CLASS (regno))
- {
- case FP_REGS:
- if (REGNO_PAIR_OK (regno, mode))
- {
- if (mode == SImode || mode == DImode)
- return true;
-
- if (FLOAT_MODE_P (mode) && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT)
- return true;
- }
- break;
- case ADDR_REGS:
- if (FRAME_REGNO_P (regno) && mode == Pmode)
- return true;
-
- /* fallthrough */
- case GENERAL_REGS:
- if (REGNO_PAIR_OK (regno, mode))
- {
- if (TARGET_ZARCH
- || (mode != TFmode && mode != TCmode && mode != TDmode))
- return true;
- }
- break;
- case CC_REGS:
- if (GET_MODE_CLASS (mode) == MODE_CC)
- return true;
- break;
- case ACCESS_REGS:
- if (REGNO_PAIR_OK (regno, mode))
- {
- if (mode == SImode || mode == Pmode)
- return true;
- }
- break;
- default:
- return false;
- }
-
- return false;
-}
-
-/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
-
-bool
-s390_hard_regno_rename_ok (unsigned int old_reg, unsigned int new_reg)
-{
- /* Once we've decided upon a register to use as base register, it must
- no longer be used for any other purpose. */
- if (cfun->machine->base_reg)
- if (REGNO (cfun->machine->base_reg) == old_reg
- || REGNO (cfun->machine->base_reg) == new_reg)
- return false;
-
- return true;
-}
-
-/* Maximum number of registers to represent a value of mode MODE
- in a register of class RCLASS. */
-
-int
-s390_class_max_nregs (enum reg_class rclass, enum machine_mode mode)
-{
- switch (rclass)
- {
- case FP_REGS:
- if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
- return 2 * ((GET_MODE_SIZE (mode) / 2 + 8 - 1) / 8);
- else
- return (GET_MODE_SIZE (mode) + 8 - 1) / 8;
- case ACCESS_REGS:
- return (GET_MODE_SIZE (mode) + 4 - 1) / 4;
- default:
- break;
- }
- return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-}
-
-/* Return true if register FROM can be eliminated via register TO. */
-
-static bool
-s390_can_eliminate (const int from, const int to)
-{
- /* On zSeries machines, we have not marked the base register as fixed.
- Instead, we have an elimination rule BASE_REGNUM -> BASE_REGNUM.
- If a function requires the base register, we say here that this
- elimination cannot be performed. This will cause reload to free
- up the base register (as if it were fixed). On the other hand,
- if the current function does *not* require the base register, we
- say here the elimination succeeds, which in turn allows reload
- to allocate the base register for any other purpose. */
- if (from == BASE_REGNUM && to == BASE_REGNUM)
- {
- if (TARGET_CPU_ZARCH)
- {
- s390_init_frame_layout ();
- return cfun->machine->base_reg == NULL_RTX;
- }
-
- return false;
- }
-
- /* Everything else must point into the stack frame. */
- gcc_assert (to == STACK_POINTER_REGNUM
- || to == HARD_FRAME_POINTER_REGNUM);
-
- gcc_assert (from == FRAME_POINTER_REGNUM
- || from == ARG_POINTER_REGNUM
- || from == RETURN_ADDRESS_POINTER_REGNUM);
-
- /* Make sure we actually saved the return address. */
- if (from == RETURN_ADDRESS_POINTER_REGNUM)
- if (!crtl->calls_eh_return
- && !cfun->stdarg
- && !cfun_frame_layout.save_return_addr_p)
- return false;
-
- return true;
-}
-
-/* Return offset between register FROM and TO initially after prolog. */
-
-HOST_WIDE_INT
-s390_initial_elimination_offset (int from, int to)
-{
- HOST_WIDE_INT offset;
- int index;
-
- /* ??? Why are we called for non-eliminable pairs? */
- if (!s390_can_eliminate (from, to))
- return 0;
-
- switch (from)
- {
- case FRAME_POINTER_REGNUM:
- offset = (get_frame_size()
- + STACK_POINTER_OFFSET
- + crtl->outgoing_args_size);
- break;
-
- case ARG_POINTER_REGNUM:
- s390_init_frame_layout ();
- offset = cfun_frame_layout.frame_size + STACK_POINTER_OFFSET;
- break;
-
- case RETURN_ADDRESS_POINTER_REGNUM:
- s390_init_frame_layout ();
- index = RETURN_REGNUM - cfun_frame_layout.first_save_gpr_slot;
- gcc_assert (index >= 0);
- offset = cfun_frame_layout.frame_size + cfun_frame_layout.gprs_offset;
- offset += index * UNITS_PER_LONG;
- break;
-
- case BASE_REGNUM:
- offset = 0;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- return offset;
-}
-
-/* Emit insn to save fpr REGNUM at offset OFFSET relative
- to register BASE. Return generated insn. */
-
-static rtx
-save_fpr (rtx base, int offset, int regnum)
-{
- rtx addr;
- addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
-
- if (regnum >= 16 && regnum <= (16 + FP_ARG_NUM_REG))
- set_mem_alias_set (addr, get_varargs_alias_set ());
- else
- set_mem_alias_set (addr, get_frame_alias_set ());
-
- return emit_move_insn (addr, gen_rtx_REG (DFmode, regnum));
-}
-
-/* Emit insn to restore fpr REGNUM from offset OFFSET relative
- to register BASE. Return generated insn. */
-
-static rtx
-restore_fpr (rtx base, int offset, int regnum)
-{
- rtx addr;
- addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
- set_mem_alias_set (addr, get_frame_alias_set ());
-
- return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
-}
-
-/* Return true if REGNO is a global register, but not one
- of the special ones that need to be saved/restored in anyway. */
-
-static inline bool
-global_not_special_regno_p (int regno)
-{
- return (global_regs[regno]
- /* These registers are special and need to be
- restored in any case. */
- && !(regno == STACK_POINTER_REGNUM
- || regno == RETURN_REGNUM
- || regno == BASE_REGNUM
- || (flag_pic && regno == (int)PIC_OFFSET_TABLE_REGNUM)));
-}
-
-/* Generate insn to save registers FIRST to LAST into
- the register save area located at offset OFFSET
- relative to register BASE. */
-
-static rtx
-save_gprs (rtx base, int offset, int first, int last)
-{
- rtx addr, insn, note;
- int i;
-
- addr = plus_constant (base, offset);
- addr = gen_rtx_MEM (Pmode, addr);
-
- set_mem_alias_set (addr, get_frame_alias_set ());
-
- /* Special-case single register. */
- if (first == last)
- {
- if (TARGET_64BIT)
- insn = gen_movdi (addr, gen_rtx_REG (Pmode, first));
- else
- insn = gen_movsi (addr, gen_rtx_REG (Pmode, first));
-
- if (!global_not_special_regno_p (first))
- RTX_FRAME_RELATED_P (insn) = 1;
- return insn;
- }
-
-
- insn = gen_store_multiple (addr,
- gen_rtx_REG (Pmode, first),
- GEN_INT (last - first + 1));
-
- if (first <= 6 && cfun->stdarg)
- for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
- {
- rtx mem = XEXP (XVECEXP (PATTERN (insn), 0, i), 0);
-
- if (first + i <= 6)
- set_mem_alias_set (mem, get_varargs_alias_set ());
- }
-
- /* We need to set the FRAME_RELATED flag on all SETs
- inside the store-multiple pattern.
-
- However, we must not emit DWARF records for registers 2..5
- if they are stored for use by variable arguments ...
-
- ??? Unfortunately, it is not enough to simply not the
- FRAME_RELATED flags for those SETs, because the first SET
- of the PARALLEL is always treated as if it had the flag
- set, even if it does not. Therefore we emit a new pattern
- without those registers as REG_FRAME_RELATED_EXPR note. */
-
- if (first >= 6 && !global_not_special_regno_p (first))
- {
- rtx pat = PATTERN (insn);
-
- for (i = 0; i < XVECLEN (pat, 0); i++)
- if (GET_CODE (XVECEXP (pat, 0, i)) == SET
- && !global_not_special_regno_p (REGNO (SET_SRC (XVECEXP (pat,
- 0, i)))))
- RTX_FRAME_RELATED_P (XVECEXP (pat, 0, i)) = 1;
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- else if (last >= 6)
- {
- int start;
-
- for (start = first >= 6 ? first : 6; start <= last; start++)
- if (!global_not_special_regno_p (start))
- break;
-
- if (start > last)
- return insn;
-
- addr = plus_constant (base, offset + (start - first) * UNITS_PER_LONG);
- note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
- gen_rtx_REG (Pmode, start),
- GEN_INT (last - start + 1));
- note = PATTERN (note);
-
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, note);
-
- for (i = 0; i < XVECLEN (note, 0); i++)
- if (GET_CODE (XVECEXP (note, 0, i)) == SET
- && !global_not_special_regno_p (REGNO (SET_SRC (XVECEXP (note,
- 0, i)))))
- RTX_FRAME_RELATED_P (XVECEXP (note, 0, i)) = 1;
-
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- return insn;
-}
-
-/* Generate insn to restore registers FIRST to LAST from
- the register save area located at offset OFFSET
- relative to register BASE. */
-
-static rtx
-restore_gprs (rtx base, int offset, int first, int last)
-{
- rtx addr, insn;
-
- addr = plus_constant (base, offset);
- addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, get_frame_alias_set ());
-
- /* Special-case single register. */
- if (first == last)
- {
- if (TARGET_64BIT)
- insn = gen_movdi (gen_rtx_REG (Pmode, first), addr);
- else
- insn = gen_movsi (gen_rtx_REG (Pmode, first), addr);
-
- return insn;
- }
-
- insn = gen_load_multiple (gen_rtx_REG (Pmode, first),
- addr,
- GEN_INT (last - first + 1));
- return insn;
-}
-
-/* Return insn sequence to load the GOT register. */
-
-static GTY(()) rtx got_symbol;
-rtx
-s390_load_got (void)
-{
- rtx insns;
-
- /* We cannot use pic_offset_table_rtx here since we use this
- function also for non-pic if __tls_get_offset is called and in
- that case PIC_OFFSET_TABLE_REGNUM as well as pic_offset_table_rtx
- aren't usable. */
- rtx got_rtx = gen_rtx_REG (Pmode, 12);
-
- if (!got_symbol)
- {
- got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
- }
-
- start_sequence ();
-
- if (TARGET_CPU_ZARCH)
- {
- emit_move_insn (got_rtx, got_symbol);
- }
- else
- {
- rtx offset;
-
- offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
- UNSPEC_LTREL_OFFSET);
- offset = gen_rtx_CONST (Pmode, offset);
- offset = force_const_mem (Pmode, offset);
-
- emit_move_insn (got_rtx, offset);
-
- offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)),
- UNSPEC_LTREL_BASE);
- offset = gen_rtx_PLUS (Pmode, got_rtx, offset);
-
- emit_move_insn (got_rtx, offset);
- }
-
- insns = get_insns ();
- end_sequence ();
- return insns;
-}
-
-/* This ties together stack memory (MEM with an alias set of frame_alias_set)
- and the change to the stack pointer. */
-
-static void
-s390_emit_stack_tie (void)
-{
- rtx mem = gen_frame_mem (BLKmode,
- gen_rtx_REG (Pmode, STACK_POINTER_REGNUM));
-
- emit_insn (gen_stack_tie (mem));
-}
-
-/* Expand the prologue into a bunch of separate insns. */
-
-void
-s390_emit_prologue (void)
-{
- rtx insn, addr;
- rtx temp_reg;
- int i;
- int offset;
- int next_fpr = 0;
-
- /* Complete frame layout. */
-
- s390_update_frame_layout ();
-
- /* Annotate all constant pool references to let the scheduler know
- they implicitly use the base register. */
-
- push_topmost_sequence ();
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn))
- {
- annotate_constant_pool_refs (&PATTERN (insn));
- df_insn_rescan (insn);
- }
-
- pop_topmost_sequence ();
-
- /* Choose best register to use for temp use within prologue.
- See below for why TPF must use the register 1. */
-
- if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
- && !current_function_is_leaf
- && !TARGET_TPF_PROFILING)
- temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
- else
- temp_reg = gen_rtx_REG (Pmode, 1);
-
- /* Save call saved gprs. */
- if (cfun_frame_layout.first_save_gpr != -1)
- {
- insn = save_gprs (stack_pointer_rtx,
- cfun_frame_layout.gprs_offset +
- UNITS_PER_LONG * (cfun_frame_layout.first_save_gpr
- - cfun_frame_layout.first_save_gpr_slot),
- cfun_frame_layout.first_save_gpr,
- cfun_frame_layout.last_save_gpr);
- emit_insn (insn);
- }
-
- /* Dummy insn to mark literal pool slot. */
-
- if (cfun->machine->base_reg)
- emit_insn (gen_main_pool (cfun->machine->base_reg));
-
- offset = cfun_frame_layout.f0_offset;
-
- /* Save f0 and f2. */
- for (i = 0; i < 2; i++)
- {
- if (cfun_fpr_bit_p (i))
- {
- save_fpr (stack_pointer_rtx, offset, i + 16);
- offset += 8;
- }
- else if (!TARGET_PACKED_STACK)
- offset += 8;
- }
-
- /* Save f4 and f6. */
- offset = cfun_frame_layout.f4_offset;
- for (i = 2; i < 4; i++)
- {
- if (cfun_fpr_bit_p (i))
- {
- insn = save_fpr (stack_pointer_rtx, offset, i + 16);
- offset += 8;
-
- /* If f4 and f6 are call clobbered they are saved due to stdargs and
- therefore are not frame related. */
- if (!call_really_used_regs[i + 16])
- RTX_FRAME_RELATED_P (insn) = 1;
- }
- else if (!TARGET_PACKED_STACK)
- offset += 8;
- }
-
- if (TARGET_PACKED_STACK
- && cfun_save_high_fprs_p
- && cfun_frame_layout.f8_offset + cfun_frame_layout.high_fprs * 8 > 0)
- {
- offset = (cfun_frame_layout.f8_offset
- + (cfun_frame_layout.high_fprs - 1) * 8);
-
- for (i = 15; i > 7 && offset >= 0; i--)
- if (cfun_fpr_bit_p (i))
- {
- insn = save_fpr (stack_pointer_rtx, offset, i + 16);
-
- RTX_FRAME_RELATED_P (insn) = 1;
- offset -= 8;
- }
- if (offset >= cfun_frame_layout.f8_offset)
- next_fpr = i + 16;
- }
-
- if (!TARGET_PACKED_STACK)
- next_fpr = cfun_save_high_fprs_p ? 31 : 0;
-
- if (flag_stack_usage_info)
- current_function_static_stack_size = cfun_frame_layout.frame_size;
-
- /* Decrement stack pointer. */
-
- if (cfun_frame_layout.frame_size > 0)
- {
- rtx frame_off = GEN_INT (-cfun_frame_layout.frame_size);
- rtx real_frame_off;
-
- if (s390_stack_size)
- {
- HOST_WIDE_INT stack_guard;
-
- if (s390_stack_guard)
- stack_guard = s390_stack_guard;
- else
- {
- /* If no value for stack guard is provided the smallest power of 2
- larger than the current frame size is chosen. */
- stack_guard = 1;
- while (stack_guard < cfun_frame_layout.frame_size)
- stack_guard <<= 1;
- }
-
- if (cfun_frame_layout.frame_size >= s390_stack_size)
- {
- warning (0, "frame size of function %qs is %wd"
- " bytes exceeding user provided stack limit of "
- "%d bytes. "
- "An unconditional trap is added.",
- current_function_name(), cfun_frame_layout.frame_size,
- s390_stack_size);
- emit_insn (gen_trap ());
- }
- else
- {
- /* stack_guard has to be smaller than s390_stack_size.
- Otherwise we would emit an AND with zero which would
- not match the test under mask pattern. */
- if (stack_guard >= s390_stack_size)
- {
- warning (0, "frame size of function %qs is %wd"
- " bytes which is more than half the stack size. "
- "The dynamic check would not be reliable. "
- "No check emitted for this function.",
- current_function_name(),
- cfun_frame_layout.frame_size);
- }
- else
- {
- HOST_WIDE_INT stack_check_mask = ((s390_stack_size - 1)
- & ~(stack_guard - 1));
-
- rtx t = gen_rtx_AND (Pmode, stack_pointer_rtx,
- GEN_INT (stack_check_mask));
- if (TARGET_64BIT)
- emit_insn (gen_ctrapdi4 (gen_rtx_EQ (VOIDmode,
- t, const0_rtx),
- t, const0_rtx, const0_rtx));
- else
- emit_insn (gen_ctrapsi4 (gen_rtx_EQ (VOIDmode,
- t, const0_rtx),
- t, const0_rtx, const0_rtx));
- }
- }
- }
-
- if (s390_warn_framesize > 0
- && cfun_frame_layout.frame_size >= s390_warn_framesize)
- warning (0, "frame size of %qs is %wd bytes",
- current_function_name (), cfun_frame_layout.frame_size);
-
- if (s390_warn_dynamicstack_p && cfun->calls_alloca)
- warning (0, "%qs uses dynamic stack allocation", current_function_name ());
-
- /* Save incoming stack pointer into temp reg. */
- if (TARGET_BACKCHAIN || next_fpr)
- insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
-
- /* Subtract frame size from stack pointer. */
-
- if (DISP_IN_RANGE (INTVAL (frame_off)))
- {
- insn = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- frame_off));
- insn = emit_insn (insn);
- }
- else
- {
- if (!CONST_OK_FOR_K (INTVAL (frame_off)))
- frame_off = force_const_mem (Pmode, frame_off);
-
- insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
- annotate_constant_pool_refs (&PATTERN (insn));
- }
-
- RTX_FRAME_RELATED_P (insn) = 1;
- real_frame_off = GEN_INT (-cfun_frame_layout.frame_size);
- add_reg_note (insn, REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- real_frame_off)));
-
- /* Set backchain. */
-
- if (TARGET_BACKCHAIN)
- {
- if (cfun_frame_layout.backchain_offset)
- addr = gen_rtx_MEM (Pmode,
- plus_constant (stack_pointer_rtx,
- cfun_frame_layout.backchain_offset));
- else
- addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
- set_mem_alias_set (addr, get_frame_alias_set ());
- insn = emit_insn (gen_move_insn (addr, temp_reg));
- }
-
- /* If we support non-call exceptions (e.g. for Java),
- we need to make sure the backchain pointer is set up
- before any possibly trapping memory access. */
- if (TARGET_BACKCHAIN && cfun->can_throw_non_call_exceptions)
- {
- addr = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (VOIDmode));
- emit_clobber (addr);
- }
- }
-
- /* Save fprs 8 - 15 (64 bit ABI). */
-
- if (cfun_save_high_fprs_p && next_fpr)
- {
- /* If the stack might be accessed through a different register
- we have to make sure that the stack pointer decrement is not
- moved below the use of the stack slots. */
- s390_emit_stack_tie ();
-
- insn = emit_insn (gen_add2_insn (temp_reg,
- GEN_INT (cfun_frame_layout.f8_offset)));
-
- offset = 0;
-
- for (i = 24; i <= next_fpr; i++)
- if (cfun_fpr_bit_p (i - 16))
- {
- rtx addr = plus_constant (stack_pointer_rtx,
- cfun_frame_layout.frame_size
- + cfun_frame_layout.f8_offset
- + offset);
-
- insn = save_fpr (temp_reg, offset, i);
- offset += 8;
- RTX_FRAME_RELATED_P (insn) = 1;
- add_reg_note (insn, REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (DFmode, addr),
- gen_rtx_REG (DFmode, i)));
- }
- }
-
- /* Set frame pointer, if needed. */
-
- if (frame_pointer_needed)
- {
- insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* Set up got pointer, if needed. */
-
- if (flag_pic && df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM))
- {
- rtx insns = s390_load_got ();
-
- for (insn = insns; insn; insn = NEXT_INSN (insn))
- annotate_constant_pool_refs (&PATTERN (insn));
-
- emit_insn (insns);
- }
-
- if (TARGET_TPF_PROFILING)
- {
- /* Generate a BAS instruction to serve as a function
- entry intercept to facilitate the use of tracing
- algorithms located at the branch target. */
- emit_insn (gen_prologue_tpf ());
-
- /* Emit a blockage here so that all code
- lies between the profiling mechanisms. */
- emit_insn (gen_blockage ());
- }
-}
-
-/* Expand the epilogue into a bunch of separate insns. */
-
-void
-s390_emit_epilogue (bool sibcall)
-{
- rtx frame_pointer, return_reg, cfa_restores = NULL_RTX;
- int area_bottom, area_top, offset = 0;
- int next_offset;
- rtvec p;
- int i;
-
- if (TARGET_TPF_PROFILING)
- {
-
- /* Generate a BAS instruction to serve as a function
- entry intercept to facilitate the use of tracing
- algorithms located at the branch target. */
-
- /* Emit a blockage here so that all code
- lies between the profiling mechanisms. */
- emit_insn (gen_blockage ());
-
- emit_insn (gen_epilogue_tpf ());
- }
-
- /* Check whether to use frame or stack pointer for restore. */
-
- frame_pointer = (frame_pointer_needed
- ? hard_frame_pointer_rtx : stack_pointer_rtx);
-
- s390_frame_area (&area_bottom, &area_top);
-
- /* Check whether we can access the register save area.
- If not, increment the frame pointer as required. */
-
- if (area_top <= area_bottom)
- {
- /* Nothing to restore. */
- }
- else if (DISP_IN_RANGE (cfun_frame_layout.frame_size + area_bottom)
- && DISP_IN_RANGE (cfun_frame_layout.frame_size + area_top - 1))
- {
- /* Area is in range. */
- offset = cfun_frame_layout.frame_size;
- }
- else
- {
- rtx insn, frame_off, cfa;
-
- offset = area_bottom < 0 ? -area_bottom : 0;
- frame_off = GEN_INT (cfun_frame_layout.frame_size - offset);
-
- cfa = gen_rtx_SET (VOIDmode, frame_pointer,
- gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
- if (DISP_IN_RANGE (INTVAL (frame_off)))
- {
- insn = gen_rtx_SET (VOIDmode, frame_pointer,
- gen_rtx_PLUS (Pmode, frame_pointer, frame_off));
- insn = emit_insn (insn);
- }
- else
- {
- if (!CONST_OK_FOR_K (INTVAL (frame_off)))
- frame_off = force_const_mem (Pmode, frame_off);
-
- insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
- annotate_constant_pool_refs (&PATTERN (insn));
- }
- add_reg_note (insn, REG_CFA_ADJUST_CFA, cfa);
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- /* Restore call saved fprs. */
-
- if (TARGET_64BIT)
- {
- if (cfun_save_high_fprs_p)
- {
- next_offset = cfun_frame_layout.f8_offset;
- for (i = 24; i < 32; i++)
- {
- if (cfun_fpr_bit_p (i - 16))
- {
- restore_fpr (frame_pointer,
- offset + next_offset, i);
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (DFmode, i), cfa_restores);
- next_offset += 8;
- }
- }
- }
-
- }
- else
- {
- next_offset = cfun_frame_layout.f4_offset;
- for (i = 18; i < 20; i++)
- {
- if (cfun_fpr_bit_p (i - 16))
- {
- restore_fpr (frame_pointer,
- offset + next_offset, i);
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (DFmode, i), cfa_restores);
- next_offset += 8;
- }
- else if (!TARGET_PACKED_STACK)
- next_offset += 8;
- }
-
- }
-
- /* Return register. */
-
- return_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
-
- /* Restore call saved gprs. */
-
- if (cfun_frame_layout.first_restore_gpr != -1)
- {
- rtx insn, addr;
- int i;
-
- /* Check for global register and save them
- to stack location from where they get restored. */
-
- for (i = cfun_frame_layout.first_restore_gpr;
- i <= cfun_frame_layout.last_restore_gpr;
- i++)
- {
- if (global_not_special_regno_p (i))
- {
- addr = plus_constant (frame_pointer,
- offset + cfun_frame_layout.gprs_offset
- + (i - cfun_frame_layout.first_save_gpr_slot)
- * UNITS_PER_LONG);
- addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, get_frame_alias_set ());
- emit_move_insn (addr, gen_rtx_REG (Pmode, i));
- }
- else
- cfa_restores
- = alloc_reg_note (REG_CFA_RESTORE,
- gen_rtx_REG (Pmode, i), cfa_restores);
- }
-
- if (! sibcall)
- {
- /* Fetch return address from stack before load multiple,
- this will do good for scheduling. */
-
- if (cfun_frame_layout.save_return_addr_p
- || (cfun_frame_layout.first_restore_gpr < BASE_REGNUM
- && cfun_frame_layout.last_restore_gpr > RETURN_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 + cfun_frame_layout.gprs_offset
- + (RETURN_REGNUM
- - cfun_frame_layout.first_save_gpr_slot)
- * UNITS_PER_LONG);
- addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, get_frame_alias_set ());
- emit_move_insn (return_reg, addr);
- }
- }
-
- insn = restore_gprs (frame_pointer,
- offset + cfun_frame_layout.gprs_offset
- + (cfun_frame_layout.first_restore_gpr
- - cfun_frame_layout.first_save_gpr_slot)
- * UNITS_PER_LONG,
- cfun_frame_layout.first_restore_gpr,
- cfun_frame_layout.last_restore_gpr);
- insn = emit_insn (insn);
- REG_NOTES (insn) = cfa_restores;
- add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (stack_pointer_rtx, STACK_POINTER_OFFSET));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
-
- if (! sibcall)
- {
-
- /* Return to caller. */
-
- p = rtvec_alloc (2);
-
- RTVEC_ELT (p, 0) = ret_rtx;
- RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
- }
-}
-
-
-/* Return the size in bytes of a function argument of
- type TYPE and/or mode MODE. At least one of TYPE or
- MODE must be specified. */
-
-static int
-s390_function_arg_size (enum machine_mode mode, const_tree type)
-{
- if (type)
- return int_size_in_bytes (type);
-
- /* No type info available for some library calls ... */
- if (mode != BLKmode)
- return GET_MODE_SIZE (mode);
-
- /* If we have neither type nor mode, abort */
- gcc_unreachable ();
-}
-
-/* Return true if a function argument of type TYPE and mode MODE
- is to be passed in a floating-point register, if available. */
-
-static bool
-s390_function_arg_float (enum machine_mode mode, const_tree type)
-{
- int size = s390_function_arg_size (mode, type);
- if (size > 8)
- return false;
-
- /* Soft-float changes the ABI: no floating-point registers are used. */
- if (TARGET_SOFT_FLOAT)
- return false;
-
- /* No type info available for some library calls ... */
- if (!type)
- return mode == SFmode || mode == DFmode || mode == SDmode || mode == DDmode;
-
- /* The ABI says that record types with a single member are treated
- just like that member would be. */
- while (TREE_CODE (type) == RECORD_TYPE)
- {
- tree field, single = NULL_TREE;
-
- for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
- {
- if (TREE_CODE (field) != FIELD_DECL)
- continue;
-
- if (single == NULL_TREE)
- single = TREE_TYPE (field);
- else
- return false;
- }
-
- if (single == NULL_TREE)
- return false;
- else
- type = single;
- }
-
- return TREE_CODE (type) == REAL_TYPE;
-}
-
-/* Return true if a function argument of type TYPE and mode MODE
- is to be passed in an integer register, or a pair of integer
- registers, if available. */
-
-static bool
-s390_function_arg_integer (enum machine_mode mode, const_tree type)
-{
- int size = s390_function_arg_size (mode, type);
- if (size > 8)
- return false;
-
- /* No type info available for some library calls ... */
- if (!type)
- return GET_MODE_CLASS (mode) == MODE_INT
- || (TARGET_SOFT_FLOAT && SCALAR_FLOAT_MODE_P (mode));
-
- /* We accept small integral (and similar) types. */
- if (INTEGRAL_TYPE_P (type)
- || POINTER_TYPE_P (type)
- || TREE_CODE (type) == NULLPTR_TYPE
- || TREE_CODE (type) == OFFSET_TYPE
- || (TARGET_SOFT_FLOAT && TREE_CODE (type) == REAL_TYPE))
- return true;
-
- /* We also accept structs of size 1, 2, 4, 8 that are not
- passed in floating-point registers. */
- if (AGGREGATE_TYPE_P (type)
- && exact_log2 (size) >= 0
- && !s390_function_arg_float (mode, type))
- return true;
-
- return false;
-}
-
-/* Return 1 if a function argument of type TYPE and mode MODE
- is to be passed by reference. The ABI specifies that only
- structures of size 1, 2, 4, or 8 bytes are passed by value,
- all other structures (and complex numbers) are passed by
- reference. */
-
-static bool
-s390_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED,
- enum machine_mode mode, const_tree type,
- bool named ATTRIBUTE_UNUSED)
-{
- int size = s390_function_arg_size (mode, type);
- if (size > 8)
- return true;
-
- if (type)
- {
- if (AGGREGATE_TYPE_P (type) && exact_log2 (size) < 0)
- return 1;
-
- if (TREE_CODE (type) == COMPLEX_TYPE
- || TREE_CODE (type) == VECTOR_TYPE)
- return 1;
- }
-
- return 0;
-}
-
-/* Update the data in CUM to advance over an argument of mode MODE and
- data type TYPE. (TYPE is null for libcalls where that information
- may not be available.). The boolean NAMED specifies whether the
- argument is a named argument (as opposed to an unnamed argument
- matching an ellipsis). */
-
-static void
-s390_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-
- if (s390_function_arg_float (mode, type))
- {
- cum->fprs += 1;
- }
- else if (s390_function_arg_integer (mode, type))
- {
- int size = s390_function_arg_size (mode, type);
- cum->gprs += ((size + UNITS_PER_LONG - 1) / UNITS_PER_LONG);
- }
- else
- gcc_unreachable ();
-}
-
-/* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis).
-
- On S/390, we use general purpose registers 2 through 6 to
- pass integer, pointer, and certain structure arguments, and
- floating point registers 0 and 2 (0, 2, 4, and 6 on 64-bit)
- to pass floating point arguments. All remaining arguments
- are pushed to the stack. */
-
-static rtx
-s390_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
- const_tree type, bool named ATTRIBUTE_UNUSED)
-{
- CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
-
- if (s390_function_arg_float (mode, type))
- {
- if (cum->fprs + 1 > FP_ARG_NUM_REG)
- return 0;
- else
- return gen_rtx_REG (mode, cum->fprs + 16);
- }
- else if (s390_function_arg_integer (mode, type))
- {
- int size = s390_function_arg_size (mode, type);
- int n_gprs = (size + UNITS_PER_LONG - 1) / UNITS_PER_LONG;
-
- if (cum->gprs + n_gprs > GP_ARG_NUM_REG)
- return 0;
- else if (n_gprs == 1 || UNITS_PER_WORD == UNITS_PER_LONG)
- return gen_rtx_REG (mode, cum->gprs + 2);
- else if (n_gprs == 2)
- {
- rtvec p = rtvec_alloc (2);
-
- RTVEC_ELT (p, 0)
- = gen_rtx_EXPR_LIST (SImode, gen_rtx_REG (SImode, cum->gprs + 2),
- const0_rtx);
- RTVEC_ELT (p, 1)
- = gen_rtx_EXPR_LIST (SImode, gen_rtx_REG (SImode, cum->gprs + 3),
- GEN_INT (4));
-
- return gen_rtx_PARALLEL (mode, p);
- }
- }
-
- /* After the real arguments, expand_call calls us once again
- with a void_type_node type. Whatever we return here is
- passed as operand 2 to the call expanders.
-
- We don't need this feature ... */
- else if (type == void_type_node)
- return const0_rtx;
-
- gcc_unreachable ();
-}
-
-/* Return true if return values of type TYPE should be returned
- in a memory buffer whose address is passed by the caller as
- hidden first argument. */
-
-static bool
-s390_return_in_memory (const_tree type, const_tree fundecl ATTRIBUTE_UNUSED)
-{
- /* We accept small integral (and similar) types. */
- if (INTEGRAL_TYPE_P (type)
- || POINTER_TYPE_P (type)
- || TREE_CODE (type) == OFFSET_TYPE
- || TREE_CODE (type) == REAL_TYPE)
- return int_size_in_bytes (type) > 8;
-
- /* Aggregates and similar constructs are always returned
- in memory. */
- if (AGGREGATE_TYPE_P (type)
- || TREE_CODE (type) == COMPLEX_TYPE
- || TREE_CODE (type) == VECTOR_TYPE)
- return true;
-
- /* ??? We get called on all sorts of random stuff from
- aggregate_value_p. We can't abort, but it's not clear
- what's safe to return. Pretend it's a struct I guess. */
- return true;
-}
-
-/* Function arguments and return values are promoted to word size. */
-
-static enum machine_mode
-s390_promote_function_mode (const_tree type, enum machine_mode mode,
- int *punsignedp,
- const_tree fntype ATTRIBUTE_UNUSED,
- int for_return ATTRIBUTE_UNUSED)
-{
- if (INTEGRAL_MODE_P (mode)
- && GET_MODE_SIZE (mode) < UNITS_PER_LONG)
- {
- if (type != NULL_TREE && POINTER_TYPE_P (type))
- *punsignedp = POINTERS_EXTEND_UNSIGNED;
- return Pmode;
- }
-
- return mode;
-}
-
-/* Define where to return a (scalar) value of type RET_TYPE.
- If RET_TYPE is null, define where to return a (scalar)
- value of mode MODE from a libcall. */
-
-static rtx
-s390_function_and_libcall_value (enum machine_mode mode,
- const_tree ret_type,
- const_tree fntype_or_decl,
- bool outgoing ATTRIBUTE_UNUSED)
-{
- /* For normal functions perform the promotion as
- promote_function_mode would do. */
- if (ret_type)
- {
- int unsignedp = TYPE_UNSIGNED (ret_type);
- mode = promote_function_mode (ret_type, mode, &unsignedp,
- fntype_or_decl, 1);
- }
-
- gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || SCALAR_FLOAT_MODE_P (mode));
- gcc_assert (GET_MODE_SIZE (mode) <= 8);
-
- if (TARGET_HARD_FLOAT && SCALAR_FLOAT_MODE_P (mode))
- return gen_rtx_REG (mode, 16);
- else if (GET_MODE_SIZE (mode) <= UNITS_PER_LONG
- || UNITS_PER_LONG == UNITS_PER_WORD)
- return gen_rtx_REG (mode, 2);
- else if (GET_MODE_SIZE (mode) == 2 * UNITS_PER_LONG)
- {
- /* This case is triggered when returning a 64 bit value with
- -m31 -mzarch. Although the value would fit into a single
- register it has to be forced into a 32 bit register pair in
- order to match the ABI. */
- rtvec p = rtvec_alloc (2);
-
- RTVEC_ELT (p, 0)
- = gen_rtx_EXPR_LIST (SImode, gen_rtx_REG (SImode, 2), const0_rtx);
- RTVEC_ELT (p, 1)
- = gen_rtx_EXPR_LIST (SImode, gen_rtx_REG (SImode, 3), GEN_INT (4));
-
- return gen_rtx_PARALLEL (mode, p);
- }
-
- gcc_unreachable ();
-}
-
-/* Define where to return a scalar return value of type RET_TYPE. */
-
-static rtx
-s390_function_value (const_tree ret_type, const_tree fn_decl_or_type,
- bool outgoing)
-{
- return s390_function_and_libcall_value (TYPE_MODE (ret_type), ret_type,
- fn_decl_or_type, outgoing);
-}
-
-/* Define where to return a scalar libcall return value of mode
- MODE. */
-
-static rtx
-s390_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
-{
- return s390_function_and_libcall_value (mode, NULL_TREE,
- NULL_TREE, true);
-}
-
-
-/* Create and return the va_list datatype.
-
- On S/390, va_list is an array type equivalent to
-
- typedef struct __va_list_tag
- {
- long __gpr;
- long __fpr;
- void *__overflow_arg_area;
- void *__reg_save_area;
- } va_list[1];
-
- where __gpr and __fpr hold the number of general purpose
- or floating point arguments used up to now, respectively,
- __overflow_arg_area points to the stack location of the
- next argument passed on the stack, and __reg_save_area
- always points to the start of the register area in the
- call frame of the current function. The function prologue
- saves all registers used for argument passing into this
- area if the function uses variable arguments. */
-
-static tree
-s390_build_builtin_va_list (void)
-{
- tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
-
- record = lang_hooks.types.make_type (RECORD_TYPE);
-
- type_decl =
- build_decl (BUILTINS_LOCATION,
- TYPE_DECL, get_identifier ("__va_list_tag"), record);
-
- f_gpr = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, get_identifier ("__gpr"),
- long_integer_type_node);
- f_fpr = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, get_identifier ("__fpr"),
- long_integer_type_node);
- f_ovf = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, get_identifier ("__overflow_arg_area"),
- ptr_type_node);
- f_sav = build_decl (BUILTINS_LOCATION,
- FIELD_DECL, get_identifier ("__reg_save_area"),
- ptr_type_node);
-
- va_list_gpr_counter_field = f_gpr;
- va_list_fpr_counter_field = f_fpr;
-
- DECL_FIELD_CONTEXT (f_gpr) = record;
- DECL_FIELD_CONTEXT (f_fpr) = record;
- DECL_FIELD_CONTEXT (f_ovf) = record;
- DECL_FIELD_CONTEXT (f_sav) = record;
-
- TYPE_STUB_DECL (record) = type_decl;
- TYPE_NAME (record) = type_decl;
- TYPE_FIELDS (record) = f_gpr;
- DECL_CHAIN (f_gpr) = f_fpr;
- DECL_CHAIN (f_fpr) = f_ovf;
- DECL_CHAIN (f_ovf) = f_sav;
-
- layout_type (record);
-
- /* The correct type is an array type of one element. */
- return build_array_type (record, build_index_type (size_zero_node));
-}
-
-/* Implement va_start by filling the va_list structure VALIST.
- STDARG_P is always true, and ignored.
- NEXTARG points to the first anonymous stack argument.
-
- The following global variables are used to initialize
- the va_list structure:
-
- crtl->args.info:
- holds number of gprs and fprs used for named arguments.
- crtl->args.arg_offset_rtx:
- holds the offset of the first anonymous stack argument
- (relative to the virtual arg pointer). */
-
-static void
-s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT n_gpr, n_fpr;
- int off;
- tree f_gpr, f_fpr, f_ovf, f_sav;
- tree gpr, fpr, ovf, sav, t;
-
- f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
- f_fpr = DECL_CHAIN (f_gpr);
- f_ovf = DECL_CHAIN (f_fpr);
- f_sav = DECL_CHAIN (f_ovf);
-
- valist = build_simple_mem_ref (valist);
- gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
- fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
- ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
- sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
-
- /* Count number of gp and fp argument registers used. */
-
- n_gpr = crtl->args.info.gprs;
- n_fpr = crtl->args.info.fprs;
-
- if (cfun->va_list_gpr_size)
- {
- t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
- build_int_cst (NULL_TREE, n_gpr));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
-
- if (cfun->va_list_fpr_size)
- {
- t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
- build_int_cst (NULL_TREE, n_fpr));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
-
- /* Find the overflow area. */
- if (n_gpr + cfun->va_list_gpr_size > GP_ARG_NUM_REG
- || n_fpr + cfun->va_list_fpr_size > FP_ARG_NUM_REG)
- {
- t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
-
- off = INTVAL (crtl->args.arg_offset_rtx);
- off = off < 0 ? 0 : off;
- if (TARGET_DEBUG_ARG)
- fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
- (int)n_gpr, (int)n_fpr, off);
-
- t = fold_build_pointer_plus_hwi (t, off);
-
- t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
-
- /* Find the register save area. */
- if ((cfun->va_list_gpr_size && n_gpr < GP_ARG_NUM_REG)
- || (cfun->va_list_fpr_size && n_fpr < FP_ARG_NUM_REG))
- {
- t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
- t = fold_build_pointer_plus_hwi (t, -RETURN_REGNUM * UNITS_PER_LONG);
-
- t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
- }
-}
-
-/* Implement va_arg by updating the va_list structure
- VALIST as required to retrieve an argument of type
- TYPE, and returning that argument.
-
- Generates code equivalent to:
-
- if (integral value) {
- if (size <= 4 && args.gpr < 5 ||
- size > 4 && args.gpr < 4 )
- ret = args.reg_save_area[args.gpr+8]
- else
- ret = *args.overflow_arg_area++;
- } else if (float value) {
- if (args.fgpr < 2)
- ret = args.reg_save_area[args.fpr+64]
- else
- ret = *args.overflow_arg_area++;
- } else if (aggregate value) {
- if (args.gpr < 5)
- ret = *args.reg_save_area[args.gpr]
- else
- ret = **args.overflow_arg_area++;
- } */
-
-static tree
-s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
- gimple_seq *post_p ATTRIBUTE_UNUSED)
-{
- tree f_gpr, f_fpr, f_ovf, f_sav;
- tree gpr, fpr, ovf, sav, reg, t, u;
- int indirect_p, size, n_reg, sav_ofs, sav_scale, max_reg;
- tree lab_false, lab_over, addr;
-
- f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
- f_fpr = DECL_CHAIN (f_gpr);
- f_ovf = DECL_CHAIN (f_fpr);
- f_sav = DECL_CHAIN (f_ovf);
-
- valist = build_va_arg_indirect_ref (valist);
- gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
- fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
- sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
-
- /* The tree for args* cannot be shared between gpr/fpr and ovf since
- both appear on a lhs. */
- valist = unshare_expr (valist);
- ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
-
- size = int_size_in_bytes (type);
-
- if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
- {
- if (TARGET_DEBUG_ARG)
- {
- fprintf (stderr, "va_arg: aggregate type");
- debug_tree (type);
- }
-
- /* Aggregates are passed by reference. */
- indirect_p = 1;
- reg = gpr;
- n_reg = 1;
-
- /* kernel stack layout on 31 bit: It is assumed here that no padding
- will be added by s390_frame_info because for va_args always an even
- number of gprs has to be saved r15-r2 = 14 regs. */
- sav_ofs = 2 * UNITS_PER_LONG;
- sav_scale = UNITS_PER_LONG;
- size = UNITS_PER_LONG;
- max_reg = GP_ARG_NUM_REG - n_reg;
- }
- else if (s390_function_arg_float (TYPE_MODE (type), type))
- {
- if (TARGET_DEBUG_ARG)
- {
- fprintf (stderr, "va_arg: float type");
- debug_tree (type);
- }
-
- /* FP args go in FP registers, if present. */
- indirect_p = 0;
- reg = fpr;
- n_reg = 1;
- sav_ofs = 16 * UNITS_PER_LONG;
- sav_scale = 8;
- max_reg = FP_ARG_NUM_REG - n_reg;
- }
- else
- {
- if (TARGET_DEBUG_ARG)
- {
- fprintf (stderr, "va_arg: other type");
- debug_tree (type);
- }
-
- /* Otherwise into GP registers. */
- indirect_p = 0;
- reg = gpr;
- n_reg = (size + UNITS_PER_LONG - 1) / UNITS_PER_LONG;
-
- /* kernel stack layout on 31 bit: It is assumed here that no padding
- will be added by s390_frame_info because for va_args always an even
- number of gprs has to be saved r15-r2 = 14 regs. */
- sav_ofs = 2 * UNITS_PER_LONG;
-
- if (size < UNITS_PER_LONG)
- sav_ofs += UNITS_PER_LONG - size;
-
- sav_scale = UNITS_PER_LONG;
- max_reg = GP_ARG_NUM_REG - n_reg;
- }
-
- /* Pull the value out of the saved registers ... */
-
- lab_false = create_artificial_label (UNKNOWN_LOCATION);
- lab_over = create_artificial_label (UNKNOWN_LOCATION);
- addr = create_tmp_var (ptr_type_node, "addr");
-
- t = fold_convert (TREE_TYPE (reg), size_int (max_reg));
- t = build2 (GT_EXPR, boolean_type_node, reg, t);
- u = build1 (GOTO_EXPR, void_type_node, lab_false);
- t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
- gimplify_and_add (t, pre_p);
-
- t = fold_build_pointer_plus_hwi (sav, sav_ofs);
- u = build2 (MULT_EXPR, TREE_TYPE (reg), reg,
- fold_convert (TREE_TYPE (reg), size_int (sav_scale)));
- t = fold_build_pointer_plus (t, u);
-
- gimplify_assign (addr, t, pre_p);
-
- gimple_seq_add_stmt (pre_p, gimple_build_goto (lab_over));
-
- gimple_seq_add_stmt (pre_p, gimple_build_label (lab_false));
-
-
- /* ... Otherwise out of the overflow area. */
-
- t = ovf;
- if (size < UNITS_PER_LONG)
- t = fold_build_pointer_plus_hwi (t, UNITS_PER_LONG - size);
-
- gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
-
- gimplify_assign (addr, t, pre_p);
-
- t = fold_build_pointer_plus_hwi (t, size);
- gimplify_assign (ovf, t, pre_p);
-
- gimple_seq_add_stmt (pre_p, gimple_build_label (lab_over));
-
-
- /* Increment register save count. */
-
- u = build2 (PREINCREMENT_EXPR, TREE_TYPE (reg), reg,
- fold_convert (TREE_TYPE (reg), size_int (n_reg)));
- gimplify_and_add (u, pre_p);
-
- if (indirect_p)
- {
- t = build_pointer_type_for_mode (build_pointer_type (type),
- ptr_mode, true);
- addr = fold_convert (t, addr);
- addr = build_va_arg_indirect_ref (addr);
- }
- else
- {
- t = build_pointer_type_for_mode (type, ptr_mode, true);
- addr = fold_convert (t, addr);
- }
-
- return build_va_arg_indirect_ref (addr);
-}
-
-
-/* Builtins. */
-
-enum s390_builtin
-{
- S390_BUILTIN_THREAD_POINTER,
- S390_BUILTIN_SET_THREAD_POINTER,
-
- S390_BUILTIN_max
-};
-
-static enum insn_code const code_for_builtin_64[S390_BUILTIN_max] = {
- CODE_FOR_get_tp_64,
- CODE_FOR_set_tp_64
-};
-
-static enum insn_code const code_for_builtin_31[S390_BUILTIN_max] = {
- CODE_FOR_get_tp_31,
- CODE_FOR_set_tp_31
-};
-
-static void
-s390_init_builtins (void)
-{
- tree ftype;
-
- ftype = build_function_type_list (ptr_type_node, NULL_TREE);
- add_builtin_function ("__builtin_thread_pointer", ftype,
- S390_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
- NULL, NULL_TREE);
-
- ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
- add_builtin_function ("__builtin_set_thread_pointer", ftype,
- S390_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
- NULL, NULL_TREE);
-}
-
-/* Expand an expression EXP that calls a built-in function,
- with result going to TARGET if that's convenient
- (and in mode MODE if that's convenient).
- SUBTARGET may be used as the target for computing one of EXP's operands.
- IGNORE is nonzero if the value is to be ignored. */
-
-static rtx
-s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- int ignore ATTRIBUTE_UNUSED)
-{
-#define MAX_ARGS 2
-
- enum insn_code const *code_for_builtin =
- TARGET_64BIT ? code_for_builtin_64 : code_for_builtin_31;
-
- tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
- unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- enum insn_code icode;
- rtx op[MAX_ARGS], pat;
- int arity;
- bool nonvoid;
- tree arg;
- call_expr_arg_iterator iter;
-
- if (fcode >= S390_BUILTIN_max)
- internal_error ("bad builtin fcode");
- icode = code_for_builtin[fcode];
- if (icode == 0)
- internal_error ("bad builtin fcode");
-
- nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node;
-
- arity = 0;
- FOR_EACH_CALL_EXPR_ARG (arg, iter, exp)
- {
- const struct insn_operand_data *insn_op;
-
- if (arg == error_mark_node)
- return NULL_RTX;
- if (arity > MAX_ARGS)
- return NULL_RTX;
-
- insn_op = &insn_data[icode].operand[arity + nonvoid];
-
- op[arity] = expand_expr (arg, NULL_RTX, insn_op->mode, EXPAND_NORMAL);
-
- if (!(*insn_op->predicate) (op[arity], insn_op->mode))
- op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
- arity++;
- }
-
- if (nonvoid)
- {
- enum machine_mode tmode = insn_data[icode].operand[0].mode;
- if (!target
- || GET_MODE (target) != tmode
- || !(*insn_data[icode].operand[0].predicate) (target, tmode))
- target = gen_reg_rtx (tmode);
- }
-
- switch (arity)
- {
- case 0:
- pat = GEN_FCN (icode) (target);
- break;
- case 1:
- if (nonvoid)
- pat = GEN_FCN (icode) (target, op[0]);
- else
- pat = GEN_FCN (icode) (op[0]);
- break;
- case 2:
- pat = GEN_FCN (icode) (target, op[0], op[1]);
- break;
- default:
- gcc_unreachable ();
- }
- if (!pat)
- return NULL_RTX;
- emit_insn (pat);
-
- if (nonvoid)
- return target;
- else
- return const0_rtx;
-}
-
-
-/* Output assembly code for the trampoline template to
- stdio stream FILE.
-
- On S/390, we use gpr 1 internally in the trampoline code;
- gpr 0 is used to hold the static chain. */
-
-static void
-s390_asm_trampoline_template (FILE *file)
-{
- rtx op[2];
- op[0] = gen_rtx_REG (Pmode, 0);
- op[1] = gen_rtx_REG (Pmode, 1);
-
- if (TARGET_64BIT)
- {
- output_asm_insn ("basr\t%1,0", op); /* 2 byte */
- output_asm_insn ("lmg\t%0,%1,14(%1)", op); /* 6 byte */
- output_asm_insn ("br\t%1", op); /* 2 byte */
- ASM_OUTPUT_SKIP (file, (HOST_WIDE_INT)(TRAMPOLINE_SIZE - 10));
- }
- else
- {
- output_asm_insn ("basr\t%1,0", op); /* 2 byte */
- output_asm_insn ("lm\t%0,%1,6(%1)", op); /* 4 byte */
- output_asm_insn ("br\t%1", op); /* 2 byte */
- ASM_OUTPUT_SKIP (file, (HOST_WIDE_INT)(TRAMPOLINE_SIZE - 8));
- }
-}
-
-/* Emit RTL insns to initialize the variable parts of a trampoline.
- FNADDR is an RTX for the address of the function's pure code.
- CXT is an RTX for the static chain value for the function. */
-
-static void
-s390_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
-{
- rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
- rtx mem;
-
- emit_block_move (m_tramp, assemble_trampoline_template (),
- GEN_INT (2 * UNITS_PER_LONG), BLOCK_OP_NORMAL);
-
- mem = adjust_address (m_tramp, Pmode, 2 * UNITS_PER_LONG);
- emit_move_insn (mem, cxt);
- mem = adjust_address (m_tramp, Pmode, 3 * UNITS_PER_LONG);
- emit_move_insn (mem, fnaddr);
-}
-
-/* Output assembler code to FILE to increment profiler label # LABELNO
- for profiling a function entry. */
-
-void
-s390_function_profiler (FILE *file, int labelno)
-{
- rtx op[7];
-
- char label[128];
- ASM_GENERATE_INTERNAL_LABEL (label, "LP", 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_LONG));
-
- op[2] = gen_rtx_REG (Pmode, 1);
- op[3] = gen_rtx_SYMBOL_REF (Pmode, label);
- SYMBOL_REF_FLAGS (op[3]) = SYMBOL_FLAG_LOCAL;
-
- op[4] = gen_rtx_SYMBOL_REF (Pmode, "_mcount");
- if (flag_pic)
- {
- op[4] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[4]), UNSPEC_PLT);
- 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%4", op);
- output_asm_insn (".long\t%3", op);
- targetm.asm_out.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);
- targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[5]));
- output_asm_insn (".long\t%4-%l5", op);
- output_asm_insn (".long\t%3-%l5", op);
- targetm.asm_out.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);
- }
-}
-
-/* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
- into its SYMBOL_REF_FLAGS. */
-
-static void
-s390_encode_section_info (tree decl, rtx rtl, int first)
-{
- default_encode_section_info (decl, rtl, first);
-
- if (TREE_CODE (decl) == VAR_DECL)
- {
- /* If a variable has a forced alignment to < 2 bytes, mark it
- with SYMBOL_FLAG_ALIGN1 to prevent it from being used as LARL
- operand. */
- if (DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 16)
- SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
- if (!DECL_SIZE (decl)
- || !DECL_ALIGN (decl)
- || !host_integerp (DECL_SIZE (decl), 0)
- || (DECL_ALIGN (decl) <= 64
- && DECL_ALIGN (decl) != tree_low_cst (DECL_SIZE (decl), 0)))
- SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED;
- }
-
- /* Literal pool references don't have a decl so they are handled
- differently here. We rely on the information in the MEM_ALIGN
- entry to decide upon natural alignment. */
- if (MEM_P (rtl)
- && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
- && TREE_CONSTANT_POOL_ADDRESS_P (XEXP (rtl, 0))
- && (MEM_ALIGN (rtl) == 0
- || GET_MODE_BITSIZE (GET_MODE (rtl)) == 0
- || MEM_ALIGN (rtl) < GET_MODE_BITSIZE (GET_MODE (rtl))))
- SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_NOT_NATURALLY_ALIGNED;
-}
-
-/* Output thunk to FILE that implements a C++ virtual function call (with
- multiple inheritance) to FUNCTION. The thunk adjusts the this pointer
- by DELTA, and unless VCALL_OFFSET is zero, applies an additional adjustment
- stored at VCALL_OFFSET in the vtable whose address is located at offset 0
- relative to the resulting this pointer. */
-
-static void
-s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
- HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
- tree function)
-{
- rtx op[10];
- int nonlocal = 0;
-
- /* Make sure unwind info is emitted for the thunk if needed. */
- final_start_function (emit_barrier (), file, 1);
-
- /* Operand 0 is the target function. */
- op[0] = XEXP (DECL_RTL (function), 0);
- if (flag_pic && !SYMBOL_REF_LOCAL_P (op[0]))
- {
- nonlocal = 1;
- op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]),
- TARGET_64BIT ? UNSPEC_PLT : UNSPEC_GOT);
- op[0] = gen_rtx_CONST (Pmode, op[0]);
- }
-
- /* Operand 1 is the 'this' pointer. */
- if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
- op[1] = gen_rtx_REG (Pmode, 3);
- else
- op[1] = gen_rtx_REG (Pmode, 2);
-
- /* Operand 2 is the delta. */
- op[2] = GEN_INT (delta);
-
- /* Operand 3 is the vcall_offset. */
- op[3] = GEN_INT (vcall_offset);
-
- /* Operand 4 is the temporary register. */
- op[4] = gen_rtx_REG (Pmode, 1);
-
- /* Operands 5 to 8 can be used as labels. */
- op[5] = NULL_RTX;
- op[6] = NULL_RTX;
- op[7] = NULL_RTX;
- op[8] = NULL_RTX;
-
- /* Operand 9 can be used for temporary register. */
- op[9] = NULL_RTX;
-
- /* Generate code. */
- if (TARGET_64BIT)
- {
- /* Setup literal pool pointer if required. */
- if ((!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_K (delta)
- && !CONST_OK_FOR_Os (delta))
- || (!DISP_IN_RANGE (vcall_offset)
- && !CONST_OK_FOR_K (vcall_offset)
- && !CONST_OK_FOR_Os (vcall_offset)))
- {
- op[5] = gen_label_rtx ();
- output_asm_insn ("larl\t%4,%5", op);
- }
-
- /* Add DELTA to this pointer. */
- if (delta)
- {
- if (CONST_OK_FOR_J (delta))
- output_asm_insn ("la\t%1,%2(%1)", op);
- else if (DISP_IN_RANGE (delta))
- output_asm_insn ("lay\t%1,%2(%1)", op);
- else if (CONST_OK_FOR_K (delta))
- output_asm_insn ("aghi\t%1,%2", op);
- else if (CONST_OK_FOR_Os (delta))
- output_asm_insn ("agfi\t%1,%2", op);
- else
- {
- op[6] = gen_label_rtx ();
- output_asm_insn ("agf\t%1,%6-%5(%4)", op);
- }
- }
-
- /* Perform vcall adjustment. */
- if (vcall_offset)
- {
- if (DISP_IN_RANGE (vcall_offset))
- {
- output_asm_insn ("lg\t%4,0(%1)", op);
- output_asm_insn ("ag\t%1,%3(%4)", op);
- }
- else if (CONST_OK_FOR_K (vcall_offset))
- {
- output_asm_insn ("lghi\t%4,%3", op);
- output_asm_insn ("ag\t%4,0(%1)", op);
- output_asm_insn ("ag\t%1,0(%4)", op);
- }
- else if (CONST_OK_FOR_Os (vcall_offset))
- {
- output_asm_insn ("lgfi\t%4,%3", op);
- output_asm_insn ("ag\t%4,0(%1)", op);
- output_asm_insn ("ag\t%1,0(%4)", op);
- }
- else
- {
- op[7] = gen_label_rtx ();
- output_asm_insn ("llgf\t%4,%7-%5(%4)", op);
- output_asm_insn ("ag\t%4,0(%1)", op);
- output_asm_insn ("ag\t%1,0(%4)", op);
- }
- }
-
- /* Jump to target. */
- output_asm_insn ("jg\t%0", op);
-
- /* Output literal pool if required. */
- if (op[5])
- {
- output_asm_insn (".align\t4", op);
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[5]));
- }
- if (op[6])
- {
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[6]));
- output_asm_insn (".long\t%2", op);
- }
- if (op[7])
- {
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[7]));
- output_asm_insn (".long\t%3", op);
- }
- }
- else
- {
- /* Setup base pointer if required. */
- if (!vcall_offset
- || (!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_K (delta)
- && !CONST_OK_FOR_Os (delta))
- || (!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_K (vcall_offset)
- && !CONST_OK_FOR_Os (vcall_offset)))
- {
- op[5] = gen_label_rtx ();
- output_asm_insn ("basr\t%4,0", op);
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[5]));
- }
-
- /* Add DELTA to this pointer. */
- if (delta)
- {
- if (CONST_OK_FOR_J (delta))
- output_asm_insn ("la\t%1,%2(%1)", op);
- else if (DISP_IN_RANGE (delta))
- output_asm_insn ("lay\t%1,%2(%1)", op);
- else if (CONST_OK_FOR_K (delta))
- output_asm_insn ("ahi\t%1,%2", op);
- else if (CONST_OK_FOR_Os (delta))
- output_asm_insn ("afi\t%1,%2", op);
- else
- {
- op[6] = gen_label_rtx ();
- output_asm_insn ("a\t%1,%6-%5(%4)", op);
- }
- }
-
- /* Perform vcall adjustment. */
- if (vcall_offset)
- {
- if (CONST_OK_FOR_J (vcall_offset))
- {
- output_asm_insn ("l\t%4,0(%1)", op);
- output_asm_insn ("a\t%1,%3(%4)", op);
- }
- else if (DISP_IN_RANGE (vcall_offset))
- {
- output_asm_insn ("l\t%4,0(%1)", op);
- output_asm_insn ("ay\t%1,%3(%4)", op);
- }
- else if (CONST_OK_FOR_K (vcall_offset))
- {
- output_asm_insn ("lhi\t%4,%3", op);
- output_asm_insn ("a\t%4,0(%1)", op);
- output_asm_insn ("a\t%1,0(%4)", op);
- }
- else if (CONST_OK_FOR_Os (vcall_offset))
- {
- output_asm_insn ("iilf\t%4,%3", op);
- output_asm_insn ("a\t%4,0(%1)", op);
- output_asm_insn ("a\t%1,0(%4)", op);
- }
- else
- {
- op[7] = gen_label_rtx ();
- output_asm_insn ("l\t%4,%7-%5(%4)", op);
- output_asm_insn ("a\t%4,0(%1)", op);
- output_asm_insn ("a\t%1,0(%4)", op);
- }
-
- /* We had to clobber the base pointer register.
- Re-setup the base pointer (with a different base). */
- op[5] = gen_label_rtx ();
- output_asm_insn ("basr\t%4,0", op);
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[5]));
- }
-
- /* Jump to target. */
- op[8] = gen_label_rtx ();
-
- if (!flag_pic)
- output_asm_insn ("l\t%4,%8-%5(%4)", op);
- else if (!nonlocal)
- output_asm_insn ("a\t%4,%8-%5(%4)", op);
- /* We cannot call through .plt, since .plt requires %r12 loaded. */
- else if (flag_pic == 1)
- {
- output_asm_insn ("a\t%4,%8-%5(%4)", op);
- output_asm_insn ("l\t%4,%0(%4)", op);
- }
- else if (flag_pic == 2)
- {
- op[9] = gen_rtx_REG (Pmode, 0);
- output_asm_insn ("l\t%9,%8-4-%5(%4)", op);
- output_asm_insn ("a\t%4,%8-%5(%4)", op);
- output_asm_insn ("ar\t%4,%9", op);
- output_asm_insn ("l\t%4,0(%4)", op);
- }
-
- output_asm_insn ("br\t%4", op);
-
- /* Output literal pool. */
- output_asm_insn (".align\t4", op);
-
- if (nonlocal && flag_pic == 2)
- output_asm_insn (".long\t%0", op);
- if (nonlocal)
- {
- op[0] = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- SYMBOL_REF_FLAGS (op[0]) = SYMBOL_FLAG_LOCAL;
- }
-
- targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (op[8]));
- if (!flag_pic)
- output_asm_insn (".long\t%0", op);
- else
- output_asm_insn (".long\t%0-%5", op);
-
- if (op[6])
- {
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[6]));
- output_asm_insn (".long\t%2", op);
- }
- if (op[7])
- {
- targetm.asm_out.internal_label (file, "L",
- CODE_LABEL_NUMBER (op[7]));
- output_asm_insn (".long\t%3", op);
- }
- }
- final_end_function ();
-}
-
-static bool
-s390_valid_pointer_mode (enum machine_mode mode)
-{
- return (mode == SImode || (TARGET_64BIT && mode == DImode));
-}
-
-/* Checks whether the given CALL_EXPR would use a caller
- saved register. This is used to decide whether sibling call
- optimization could be performed on the respective function
- call. */
-
-static bool
-s390_call_saved_register_used (tree call_expr)
-{
- CUMULATIVE_ARGS cum_v;
- cumulative_args_t cum;
- tree parameter;
- enum machine_mode mode;
- tree type;
- rtx parm_rtx;
- int reg, i;
-
- INIT_CUMULATIVE_ARGS (cum_v, NULL, NULL, 0, 0);
- cum = pack_cumulative_args (&cum_v);
-
- for (i = 0; i < call_expr_nargs (call_expr); i++)
- {
- parameter = CALL_EXPR_ARG (call_expr, i);
- gcc_assert (parameter);
-
- /* For an undeclared variable passed as parameter we will get
- an ERROR_MARK node here. */
- if (TREE_CODE (parameter) == ERROR_MARK)
- return true;
-
- type = TREE_TYPE (parameter);
- gcc_assert (type);
-
- mode = TYPE_MODE (type);
- gcc_assert (mode);
-
- if (pass_by_reference (&cum_v, mode, type, true))
- {
- mode = Pmode;
- type = build_pointer_type (type);
- }
-
- parm_rtx = s390_function_arg (cum, mode, type, 0);
-
- s390_function_arg_advance (cum, mode, type, 0);
-
- if (!parm_rtx)
- continue;
-
- if (REG_P (parm_rtx))
- {
- for (reg = 0;
- reg < HARD_REGNO_NREGS (REGNO (parm_rtx), GET_MODE (parm_rtx));
- reg++)
- if (!call_used_regs[reg + REGNO (parm_rtx)])
- return true;
- }
-
- if (GET_CODE (parm_rtx) == PARALLEL)
- {
- int i;
-
- for (i = 0; i < XVECLEN (parm_rtx, 0); i++)
- {
- rtx r = XEXP (XVECEXP (parm_rtx, 0, i), 0);
-
- gcc_assert (REG_P (r));
-
- for (reg = 0;
- reg < HARD_REGNO_NREGS (REGNO (r), GET_MODE (r));
- reg++)
- if (!call_used_regs[reg + REGNO (r)])
- return true;
- }
- }
-
- }
- return false;
-}
-
-/* Return true if the given call expression can be
- turned into a sibling call.
- DECL holds the declaration of the function to be called whereas
- EXP is the call expression itself. */
-
-static bool
-s390_function_ok_for_sibcall (tree decl, tree exp)
-{
- /* The TPF epilogue uses register 1. */
- if (TARGET_TPF_PROFILING)
- return false;
-
- /* The 31 bit PLT code uses register 12 (GOT pointer - caller saved)
- which would have to be restored before the sibcall. */
- if (!TARGET_64BIT && flag_pic && decl && !targetm.binds_local_p (decl))
- return false;
-
- /* Register 6 on s390 is available as an argument register but unfortunately
- "caller saved". This makes functions needing this register for arguments
- not suitable for sibcalls. */
- return !s390_call_saved_register_used (exp);
-}
-
-/* Return the fixed registers used for condition codes. */
-
-static bool
-s390_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
-{
- *p1 = CC_REGNUM;
- *p2 = INVALID_REGNUM;
-
- return true;
-}
-
-/* This function is used by the call expanders of the machine description.
- It emits the call insn itself together with the necessary operations
- to adjust the target address and returns the emitted insn.
- ADDR_LOCATION is the target address rtx
- TLS_CALL the location of the thread-local symbol
- RESULT_REG the register where the result of the call should be stored
- RETADDR_REG the register where the return address should be stored
- If this parameter is NULL_RTX the call is considered
- to be a sibling call. */
-
-rtx
-s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
- rtx retaddr_reg)
-{
- bool plt_call = false;
- rtx insn;
- rtx call;
- rtx clobber;
- rtvec vec;
-
- /* Direct function calls need special treatment. */
- if (GET_CODE (addr_location) == SYMBOL_REF)
- {
- /* When calling a global routine in PIC mode, we must
- replace the symbol itself with the PLT stub. */
- if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location))
- {
- if (retaddr_reg != NULL_RTX)
- {
- addr_location = gen_rtx_UNSPEC (Pmode,
- gen_rtvec (1, addr_location),
- UNSPEC_PLT);
- addr_location = gen_rtx_CONST (Pmode, addr_location);
- plt_call = true;
- }
- else
- /* For -fpic code the PLT entries might use r12 which is
- call-saved. Therefore we cannot do a sibcall when
- calling directly using a symbol ref. When reaching
- this point we decided (in s390_function_ok_for_sibcall)
- to do a sibcall for a function pointer but one of the
- optimizers was able to get rid of the function pointer
- by propagating the symbol ref into the call. This
- optimization is illegal for S/390 so we turn the direct
- call into a indirect call again. */
- addr_location = force_reg (Pmode, addr_location);
- }
-
- /* Unless we can use the bras(l) insn, force the
- routine address into a register. */
- if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
- {
- if (flag_pic)
- addr_location = legitimize_pic_address (addr_location, 0);
- else
- addr_location = force_reg (Pmode, addr_location);
- }
- }
-
- /* If it is already an indirect call or the code above moved the
- SYMBOL_REF to somewhere else make sure the address can be found in
- register 1. */
- if (retaddr_reg == NULL_RTX
- && GET_CODE (addr_location) != SYMBOL_REF
- && !plt_call)
- {
- emit_move_insn (gen_rtx_REG (Pmode, SIBCALL_REGNUM), addr_location);
- addr_location = gen_rtx_REG (Pmode, SIBCALL_REGNUM);
- }
-
- addr_location = gen_rtx_MEM (QImode, addr_location);
- call = gen_rtx_CALL (VOIDmode, addr_location, const0_rtx);
-
- if (result_reg != NULL_RTX)
- call = gen_rtx_SET (VOIDmode, result_reg, call);
-
- if (retaddr_reg != NULL_RTX)
- {
- clobber = gen_rtx_CLOBBER (VOIDmode, retaddr_reg);
-
- if (tls_call != NULL_RTX)
- vec = gen_rtvec (3, call, clobber,
- gen_rtx_USE (VOIDmode, tls_call));
- else
- vec = gen_rtvec (2, call, clobber);
-
- call = gen_rtx_PARALLEL (VOIDmode, vec);
- }
-
- insn = emit_call_insn (call);
-
- /* 31-bit PLT stubs and tls calls use the GOT register implicitly. */
- if ((!TARGET_64BIT && plt_call) || tls_call != NULL_RTX)
- {
- /* s390_function_ok_for_sibcall should
- have denied sibcalls in this case. */
- gcc_assert (retaddr_reg != NULL_RTX);
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), gen_rtx_REG (Pmode, 12));
- }
- return insn;
-}
-
-/* Implement TARGET_CONDITIONAL_REGISTER_USAGE. */
-
-static void
-s390_conditional_register_usage (void)
-{
- int i;
-
- if (flag_pic)
- {
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
- call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
- }
- if (TARGET_CPU_ZARCH)
- {
- fixed_regs[BASE_REGNUM] = 0;
- call_used_regs[BASE_REGNUM] = 0;
- fixed_regs[RETURN_REGNUM] = 0;
- call_used_regs[RETURN_REGNUM] = 0;
- }
- if (TARGET_64BIT)
- {
- for (i = 24; i < 32; i++)
- call_used_regs[i] = call_really_used_regs[i] = 0;
- }
- else
- {
- for (i = 18; i < 20; i++)
- call_used_regs[i] = call_really_used_regs[i] = 0;
- }
-
- if (TARGET_SOFT_FLOAT)
- {
- for (i = 16; i < 32; i++)
- call_used_regs[i] = fixed_regs[i] = 1;
- }
-}
-
-/* Corresponding function to eh_return expander. */
-
-static GTY(()) rtx s390_tpf_eh_return_symbol;
-void
-s390_emit_tpf_eh_return (rtx target)
-{
- rtx insn, reg;
-
- if (!s390_tpf_eh_return_symbol)
- s390_tpf_eh_return_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tpf_eh_return");
-
- reg = gen_rtx_REG (Pmode, 2);
-
- emit_move_insn (reg, target);
- insn = s390_emit_call (s390_tpf_eh_return_symbol, NULL_RTX, reg,
- gen_rtx_REG (Pmode, RETURN_REGNUM));
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
-
- emit_move_insn (EH_RETURN_HANDLER_RTX, reg);
-}
-
-/* Rework the prologue/epilogue to avoid saving/restoring
- registers unnecessarily. */
-
-static void
-s390_optimize_prologue (void)
-{
- rtx insn, new_insn, next_insn;
-
- /* Do a final recompute of the frame-related data. */
-
- s390_update_frame_layout ();
-
- /* If all special registers are in fact used, there's nothing we
- can do, so no point in walking the insn list. */
-
- if (cfun_frame_layout.first_save_gpr <= BASE_REGNUM
- && cfun_frame_layout.last_save_gpr >= BASE_REGNUM
- && (TARGET_CPU_ZARCH
- || (cfun_frame_layout.first_save_gpr <= RETURN_REGNUM
- && cfun_frame_layout.last_save_gpr >= RETURN_REGNUM)))
- return;
-
- /* Search for prologue/epilogue insns and replace them. */
-
- for (insn = get_insns (); insn; insn = next_insn)
- {
- int first, last, off;
- rtx set, base, offset;
-
- next_insn = NEXT_INSN (insn);
-
- if (GET_CODE (insn) != INSN)
- continue;
-
- if (GET_CODE (PATTERN (insn)) == PARALLEL
- && store_multiple_operation (PATTERN (insn), VOIDmode))
- {
- set = XVECEXP (PATTERN (insn), 0, 0);
- first = REGNO (SET_SRC (set));
- last = first + XVECLEN (PATTERN (insn), 0) - 1;
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
- off = INTVAL (offset);
-
- if (GET_CODE (base) != REG || off < 0)
- continue;
- if (cfun_frame_layout.first_save_gpr != -1
- && (cfun_frame_layout.first_save_gpr < first
- || cfun_frame_layout.last_save_gpr > last))
- continue;
- if (REGNO (base) != STACK_POINTER_REGNUM
- && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
- continue;
- if (first > BASE_REGNUM || last < BASE_REGNUM)
- continue;
-
- if (cfun_frame_layout.first_save_gpr != -1)
- {
- new_insn = save_gprs (base,
- off + (cfun_frame_layout.first_save_gpr
- - first) * UNITS_PER_LONG,
- cfun_frame_layout.first_save_gpr,
- cfun_frame_layout.last_save_gpr);
- new_insn = emit_insn_before (new_insn, insn);
- INSN_ADDRESSES_NEW (new_insn, -1);
- }
-
- remove_insn (insn);
- continue;
- }
-
- if (cfun_frame_layout.first_save_gpr == -1
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- && (REGNO (SET_SRC (PATTERN (insn))) == BASE_REGNUM
- || (!TARGET_CPU_ZARCH
- && REGNO (SET_SRC (PATTERN (insn))) == RETURN_REGNUM))
- && GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
- {
- set = PATTERN (insn);
- first = REGNO (SET_SRC (set));
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
- off = INTVAL (offset);
-
- if (GET_CODE (base) != REG || off < 0)
- continue;
- if (REGNO (base) != STACK_POINTER_REGNUM
- && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
- continue;
-
- remove_insn (insn);
- continue;
- }
-
- if (GET_CODE (PATTERN (insn)) == PARALLEL
- && load_multiple_operation (PATTERN (insn), VOIDmode))
- {
- set = XVECEXP (PATTERN (insn), 0, 0);
- first = REGNO (SET_DEST (set));
- last = first + XVECLEN (PATTERN (insn), 0) - 1;
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
- off = INTVAL (offset);
-
- if (GET_CODE (base) != REG || off < 0)
- continue;
- if (cfun_frame_layout.first_restore_gpr != -1
- && (cfun_frame_layout.first_restore_gpr < first
- || cfun_frame_layout.last_restore_gpr > last))
- continue;
- if (REGNO (base) != STACK_POINTER_REGNUM
- && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
- continue;
- if (first > BASE_REGNUM || last < BASE_REGNUM)
- continue;
-
- if (cfun_frame_layout.first_restore_gpr != -1)
- {
- new_insn = restore_gprs (base,
- off + (cfun_frame_layout.first_restore_gpr
- - first) * UNITS_PER_LONG,
- cfun_frame_layout.first_restore_gpr,
- cfun_frame_layout.last_restore_gpr);
- new_insn = emit_insn_before (new_insn, insn);
- INSN_ADDRESSES_NEW (new_insn, -1);
- }
-
- remove_insn (insn);
- continue;
- }
-
- if (cfun_frame_layout.first_restore_gpr == -1
- && GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- && (REGNO (SET_DEST (PATTERN (insn))) == BASE_REGNUM
- || (!TARGET_CPU_ZARCH
- && REGNO (SET_DEST (PATTERN (insn))) == RETURN_REGNUM))
- && GET_CODE (SET_SRC (PATTERN (insn))) == MEM)
- {
- set = PATTERN (insn);
- first = REGNO (SET_DEST (set));
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
- off = INTVAL (offset);
-
- if (GET_CODE (base) != REG || off < 0)
- continue;
- if (REGNO (base) != STACK_POINTER_REGNUM
- && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
- continue;
-
- remove_insn (insn);
- continue;
- }
- }
-}
-
-/* On z10 and later the dynamic branch prediction must see the
- backward jump within a certain windows. If not it falls back to
- the static prediction. This function rearranges the loop backward
- branch in a way which makes the static prediction always correct.
- The function returns true if it added an instruction. */
-static bool
-s390_fix_long_loop_prediction (rtx insn)
-{
- rtx set = single_set (insn);
- rtx code_label, label_ref, new_label;
- rtx uncond_jump;
- rtx cur_insn;
- rtx tmp;
- int distance;
-
- /* This will exclude branch on count and branch on index patterns
- since these are correctly statically predicted. */
- if (!set
- || SET_DEST (set) != pc_rtx
- || GET_CODE (SET_SRC(set)) != IF_THEN_ELSE)
- return false;
-
- label_ref = (GET_CODE (XEXP (SET_SRC (set), 1)) == LABEL_REF ?
- XEXP (SET_SRC (set), 1) : XEXP (SET_SRC (set), 2));
-
- gcc_assert (GET_CODE (label_ref) == LABEL_REF);
-
- code_label = XEXP (label_ref, 0);
-
- if (INSN_ADDRESSES (INSN_UID (code_label)) == -1
- || INSN_ADDRESSES (INSN_UID (insn)) == -1
- || (INSN_ADDRESSES (INSN_UID (insn))
- - INSN_ADDRESSES (INSN_UID (code_label)) < PREDICT_DISTANCE))
- return false;
-
- for (distance = 0, cur_insn = PREV_INSN (insn);
- distance < PREDICT_DISTANCE - 6;
- distance += get_attr_length (cur_insn), cur_insn = PREV_INSN (cur_insn))
- if (!cur_insn || JUMP_P (cur_insn) || LABEL_P (cur_insn))
- return false;
-
- new_label = gen_label_rtx ();
- uncond_jump = emit_jump_insn_after (
- gen_rtx_SET (VOIDmode, pc_rtx,
- gen_rtx_LABEL_REF (VOIDmode, code_label)),
- insn);
- emit_label_after (new_label, uncond_jump);
-
- tmp = XEXP (SET_SRC (set), 1);
- XEXP (SET_SRC (set), 1) = XEXP (SET_SRC (set), 2);
- XEXP (SET_SRC (set), 2) = tmp;
- INSN_CODE (insn) = -1;
-
- XEXP (label_ref, 0) = new_label;
- JUMP_LABEL (insn) = new_label;
- JUMP_LABEL (uncond_jump) = code_label;
-
- return true;
-}
-
-/* Returns 1 if INSN reads the value of REG for purposes not related
- to addressing of memory, and 0 otherwise. */
-static int
-s390_non_addr_reg_read_p (rtx reg, rtx insn)
-{
- return reg_referenced_p (reg, PATTERN (insn))
- && !reg_used_in_mem_p (REGNO (reg), PATTERN (insn));
-}
-
-/* Starting from INSN find_cond_jump looks downwards in the insn
- stream for a single jump insn which is the last user of the
- condition code set in INSN. */
-static rtx
-find_cond_jump (rtx insn)
-{
- for (; insn; insn = NEXT_INSN (insn))
- {
- rtx ite, cc;
-
- if (LABEL_P (insn))
- break;
-
- if (!JUMP_P (insn))
- {
- if (reg_mentioned_p (gen_rtx_REG (CCmode, CC_REGNUM), insn))
- break;
- continue;
- }
-
- /* This will be triggered by a return. */
- if (GET_CODE (PATTERN (insn)) != SET)
- break;
-
- gcc_assert (SET_DEST (PATTERN (insn)) == pc_rtx);
- ite = SET_SRC (PATTERN (insn));
-
- if (GET_CODE (ite) != IF_THEN_ELSE)
- break;
-
- cc = XEXP (XEXP (ite, 0), 0);
- if (!REG_P (cc) || !CC_REGNO_P (REGNO (cc)))
- break;
-
- if (find_reg_note (insn, REG_DEAD, cc))
- return insn;
- break;
- }
-
- return NULL_RTX;
-}
-
-/* Swap the condition in COND and the operands in OP0 and OP1 so that
- the semantics does not change. If NULL_RTX is passed as COND the
- function tries to find the conditional jump starting with INSN. */
-static void
-s390_swap_cmp (rtx cond, rtx *op0, rtx *op1, rtx insn)
-{
- rtx tmp = *op0;
-
- if (cond == NULL_RTX)
- {
- rtx jump = find_cond_jump (NEXT_INSN (insn));
- jump = jump ? single_set (jump) : NULL_RTX;
-
- if (jump == NULL_RTX)
- return;
-
- cond = XEXP (XEXP (jump, 1), 0);
- }
-
- *op0 = *op1;
- *op1 = tmp;
- PUT_CODE (cond, swap_condition (GET_CODE (cond)));
-}
-
-/* On z10, instructions of the compare-and-branch family have the
- property to access the register occurring as second operand with
- its bits complemented. If such a compare is grouped with a second
- instruction that accesses the same register non-complemented, and
- if that register's value is delivered via a bypass, then the
- pipeline recycles, thereby causing significant performance decline.
- This function locates such situations and exchanges the two
- operands of the compare. The function return true whenever it
- added an insn. */
-static bool
-s390_z10_optimize_cmp (rtx insn)
-{
- rtx prev_insn, next_insn;
- bool insn_added_p = false;
- rtx cond, *op0, *op1;
-
- if (GET_CODE (PATTERN (insn)) == PARALLEL)
- {
- /* Handle compare and branch and branch on count
- instructions. */
- rtx pattern = single_set (insn);
-
- if (!pattern
- || SET_DEST (pattern) != pc_rtx
- || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE)
- return false;
-
- cond = XEXP (SET_SRC (pattern), 0);
- op0 = &XEXP (cond, 0);
- op1 = &XEXP (cond, 1);
- }
- else if (GET_CODE (PATTERN (insn)) == SET)
- {
- rtx src, dest;
-
- /* Handle normal compare instructions. */
- src = SET_SRC (PATTERN (insn));
- dest = SET_DEST (PATTERN (insn));
-
- if (!REG_P (dest)
- || !CC_REGNO_P (REGNO (dest))
- || GET_CODE (src) != COMPARE)
- return false;
-
- /* s390_swap_cmp will try to find the conditional
- jump when passing NULL_RTX as condition. */
- cond = NULL_RTX;
- op0 = &XEXP (src, 0);
- op1 = &XEXP (src, 1);
- }
- else
- return false;
-
- if (!REG_P (*op0) || !REG_P (*op1))
- return false;
-
- if (GET_MODE_CLASS (GET_MODE (*op0)) != MODE_INT)
- return false;
-
- /* Swap the COMPARE arguments and its mask if there is a
- conflicting access in the previous insn. */
- prev_insn = prev_active_insn (insn);
- if (prev_insn != NULL_RTX && INSN_P (prev_insn)
- && reg_referenced_p (*op1, PATTERN (prev_insn)))
- s390_swap_cmp (cond, op0, op1, insn);
-
- /* Check if there is a conflict with the next insn. If there
- was no conflict with the previous insn, then swap the
- COMPARE arguments and its mask. If we already swapped
- the operands, or if swapping them would cause a conflict
- with the previous insn, issue a NOP after the COMPARE in
- order to separate the two instuctions. */
- next_insn = next_active_insn (insn);
- if (next_insn != NULL_RTX && INSN_P (next_insn)
- && s390_non_addr_reg_read_p (*op1, next_insn))
- {
- if (prev_insn != NULL_RTX && INSN_P (prev_insn)
- && s390_non_addr_reg_read_p (*op0, prev_insn))
- {
- if (REGNO (*op1) == 0)
- emit_insn_after (gen_nop1 (), insn);
- else
- emit_insn_after (gen_nop (), insn);
- insn_added_p = true;
- }
- else
- s390_swap_cmp (cond, op0, op1, insn);
- }
- return insn_added_p;
-}
-
-/* Perform machine-dependent processing. */
-
-static void
-s390_reorg (void)
-{
- bool pool_overflow = false;
-
- /* Make sure all splits have been performed; splits after
- machine_dependent_reorg might confuse insn length counts. */
- split_all_insns_noflow ();
-
- /* Install the main literal pool and the associated base
- register load insns.
-
- In addition, there are two problematic situations we need
- to correct:
-
- - the literal pool might be > 4096 bytes in size, so that
- some of its elements cannot be directly accessed
-
- - a branch target might be > 64K away from the branch, so that
- it is not possible to use a PC-relative instruction.
-
- To fix those, we split the single literal pool into multiple
- pool chunks, reloading the pool base register at various
- points throughout the function to ensure it always points to
- the pool chunk the following code expects, and / or replace
- PC-relative branches by absolute branches.
-
- However, the two problems are interdependent: splitting the
- literal pool can move a branch further away from its target,
- causing the 64K limit to overflow, and on the other hand,
- replacing a PC-relative branch by an absolute branch means
- we need to put the branch target address into the literal
- pool, possibly causing it to overflow.
-
- So, we loop trying to fix up both problems until we manage
- to satisfy both conditions at the same time. Note that the
- loop is guaranteed to terminate as every pass of the loop
- strictly decreases the total number of PC-relative branches
- in the function. (This is not completely true as there
- might be branch-over-pool insns introduced by chunkify_start.
- Those never need to be split however.) */
-
- for (;;)
- {
- struct constant_pool *pool = NULL;
-
- /* Collect the literal pool. */
- if (!pool_overflow)
- {
- pool = s390_mainpool_start ();
- if (!pool)
- pool_overflow = true;
- }
-
- /* If literal pool overflowed, start to chunkify it. */
- if (pool_overflow)
- pool = s390_chunkify_start ();
-
- /* Split out-of-range branches. If this has created new
- literal pool entries, cancel current chunk list and
- recompute it. zSeries machines have large branch
- instructions, so we never need to split a branch. */
- if (!TARGET_CPU_ZARCH && s390_split_branches ())
- {
- if (pool_overflow)
- s390_chunkify_cancel (pool);
- else
- s390_mainpool_cancel (pool);
-
- continue;
- }
-
- /* If we made it up to here, both conditions are satisfied.
- Finish up literal pool related changes. */
- if (pool_overflow)
- s390_chunkify_finish (pool);
- else
- s390_mainpool_finish (pool);
-
- /* We're done splitting branches. */
- cfun->machine->split_branches_pending_p = false;
- break;
- }
-
- /* Generate out-of-pool execute target insns. */
- if (TARGET_CPU_ZARCH)
- {
- rtx insn, label, target;
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- label = s390_execute_label (insn);
- if (!label)
- continue;
-
- gcc_assert (label != const0_rtx);
-
- target = emit_label (XEXP (label, 0));
- INSN_ADDRESSES_NEW (target, -1);
-
- target = emit_insn (s390_execute_target (insn));
- INSN_ADDRESSES_NEW (target, -1);
- }
- }
-
- /* Try to optimize prologue and epilogue further. */
- s390_optimize_prologue ();
-
- /* Walk over the insns and do some >=z10 specific changes. */
- if (s390_tune == PROCESSOR_2097_Z10
- || s390_tune == PROCESSOR_2817_Z196)
- {
- rtx insn;
- bool insn_added_p = false;
-
- /* The insn lengths and addresses have to be up to date for the
- following manipulations. */
- shorten_branches (get_insns ());
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (!INSN_P (insn) || INSN_CODE (insn) <= 0)
- continue;
-
- if (JUMP_P (insn))
- insn_added_p |= s390_fix_long_loop_prediction (insn);
-
- if ((GET_CODE (PATTERN (insn)) == PARALLEL
- || GET_CODE (PATTERN (insn)) == SET)
- && s390_tune == PROCESSOR_2097_Z10)
- insn_added_p |= s390_z10_optimize_cmp (insn);
- }
-
- /* Adjust branches if we added new instructions. */
- if (insn_added_p)
- shorten_branches (get_insns ());
- }
-}
-
-/* Return true if INSN is a fp load insn writing register REGNO. */
-static inline bool
-s390_fpload_toreg (rtx insn, unsigned int regno)
-{
- rtx set;
- enum attr_type flag = s390_safe_attr_type (insn);
-
- if (flag != TYPE_FLOADSF && flag != TYPE_FLOADDF)
- return false;
-
- set = single_set (insn);
-
- if (set == NULL_RTX)
- return false;
-
- if (!REG_P (SET_DEST (set)) || !MEM_P (SET_SRC (set)))
- return false;
-
- if (REGNO (SET_DEST (set)) != regno)
- return false;
-
- return true;
-}
-
-/* This value describes the distance to be avoided between an
- aritmetic fp instruction and an fp load writing the same register.
- Z10_EARLYLOAD_DISTANCE - 1 as well as Z10_EARLYLOAD_DISTANCE + 1 is
- fine but the exact value has to be avoided. Otherwise the FP
- pipeline will throw an exception causing a major penalty. */
-#define Z10_EARLYLOAD_DISTANCE 7
-
-/* Rearrange the ready list in order to avoid the situation described
- for Z10_EARLYLOAD_DISTANCE. A problematic load instruction is
- moved to the very end of the ready list. */
-static void
-s390_z10_prevent_earlyload_conflicts (rtx *ready, int *nready_p)
-{
- unsigned int regno;
- int nready = *nready_p;
- rtx tmp;
- int i;
- rtx insn;
- rtx set;
- enum attr_type flag;
- int distance;
-
- /* Skip DISTANCE - 1 active insns. */
- for (insn = last_scheduled_insn, distance = Z10_EARLYLOAD_DISTANCE - 1;
- distance > 0 && insn != NULL_RTX;
- distance--, insn = prev_active_insn (insn))
- if (CALL_P (insn) || JUMP_P (insn))
- return;
-
- if (insn == NULL_RTX)
- return;
-
- set = single_set (insn);
-
- if (set == NULL_RTX || !REG_P (SET_DEST (set))
- || GET_MODE_CLASS (GET_MODE (SET_DEST (set))) != MODE_FLOAT)
- return;
-
- flag = s390_safe_attr_type (insn);
-
- if (flag == TYPE_FLOADSF || flag == TYPE_FLOADDF)
- return;
-
- regno = REGNO (SET_DEST (set));
- i = nready - 1;
-
- while (!s390_fpload_toreg (ready[i], regno) && i > 0)
- i--;
-
- if (!i)
- return;
-
- tmp = ready[i];
- memmove (&ready[1], &ready[0], sizeof (rtx) * i);
- ready[0] = tmp;
-}
-
-/* This function is called via hook TARGET_SCHED_REORDER before
- issueing one insn from list READY which contains *NREADYP entries.
- For target z10 it reorders load instructions to avoid early load
- conflicts in the floating point pipeline */
-static int
-s390_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
- rtx *ready, int *nreadyp, int clock ATTRIBUTE_UNUSED)
-{
- if (s390_tune == PROCESSOR_2097_Z10)
- if (reload_completed && *nreadyp > 1)
- s390_z10_prevent_earlyload_conflicts (ready, nreadyp);
-
- return s390_issue_rate ();
-}
-
-/* This function is called via hook TARGET_SCHED_VARIABLE_ISSUE after
- the scheduler has issued INSN. It stores the last issued insn into
- last_scheduled_insn in order to make it available for
- s390_sched_reorder. */
-static int
-s390_sched_variable_issue (FILE *file ATTRIBUTE_UNUSED,
- int verbose ATTRIBUTE_UNUSED,
- rtx insn, int more)
-{
- last_scheduled_insn = insn;
-
- if (GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER)
- return more - 1;
- else
- return more;
-}
-
-static void
-s390_sched_init (FILE *file ATTRIBUTE_UNUSED,
- int verbose ATTRIBUTE_UNUSED,
- int max_ready ATTRIBUTE_UNUSED)
-{
- last_scheduled_insn = NULL_RTX;
-}
-
-/* This function checks the whole of insn X for memory references. The
- function always returns zero because the framework it is called
- from would stop recursively analyzing the insn upon a return value
- other than zero. The real result of this function is updating
- counter variable MEM_COUNT. */
-static int
-check_dpu (rtx *x, unsigned *mem_count)
-{
- if (*x != NULL_RTX && MEM_P (*x))
- (*mem_count)++;
- return 0;
-}
-
-/* This target hook implementation for TARGET_LOOP_UNROLL_ADJUST calculates
- a new number struct loop *loop should be unrolled if tuned for cpus with
- a built-in stride prefetcher.
- The loop is analyzed for memory accesses by calling check_dpu for
- each rtx of the loop. Depending on the loop_depth and the amount of
- memory accesses a new number <=nunroll is returned to improve the
- behaviour of the hardware prefetch unit. */
-static unsigned
-s390_loop_unroll_adjust (unsigned nunroll, struct loop *loop)
-{
- basic_block *bbs;
- rtx insn;
- unsigned i;
- unsigned mem_count = 0;
-
- if (s390_tune != PROCESSOR_2097_Z10 && s390_tune != PROCESSOR_2817_Z196)
- return nunroll;
-
- /* Count the number of memory references within the loop body. */
- bbs = get_loop_body (loop);
- for (i = 0; i < loop->num_nodes; i++)
- {
- for (insn = BB_HEAD (bbs[i]); insn != BB_END (bbs[i]); insn = NEXT_INSN (insn))
- if (INSN_P (insn) && INSN_CODE (insn) != -1)
- for_each_rtx (&insn, (rtx_function) check_dpu, &mem_count);
- }
- free (bbs);
-
- /* Prevent division by zero, and we do not need to adjust nunroll in this case. */
- if (mem_count == 0)
- return nunroll;
-
- switch (loop_depth(loop))
- {
- case 1:
- return MIN (nunroll, 28 / mem_count);
- case 2:
- return MIN (nunroll, 22 / mem_count);
- default:
- return MIN (nunroll, 16 / mem_count);
- }
-}
-
-/* Initialize GCC target structure. */
-
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
-#undef TARGET_ASM_ALIGNED_DI_OP
-#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
-#undef TARGET_ASM_INTEGER
-#define TARGET_ASM_INTEGER s390_assemble_integer
-
-#undef TARGET_ASM_OPEN_PAREN
-#define TARGET_ASM_OPEN_PAREN ""
-
-#undef TARGET_ASM_CLOSE_PAREN
-#define TARGET_ASM_CLOSE_PAREN ""
-
-#undef TARGET_OPTION_OVERRIDE
-#define TARGET_OPTION_OVERRIDE s390_option_override
-
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO s390_encode_section_info
-
-#undef TARGET_SCALAR_MODE_SUPPORTED_P
-#define TARGET_SCALAR_MODE_SUPPORTED_P s390_scalar_mode_supported_p
-
-#ifdef HAVE_AS_TLS
-#undef TARGET_HAVE_TLS
-#define TARGET_HAVE_TLS true
-#endif
-#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM s390_cannot_force_const_mem
-
-#undef TARGET_DELEGITIMIZE_ADDRESS
-#define TARGET_DELEGITIMIZE_ADDRESS s390_delegitimize_address
-
-#undef TARGET_LEGITIMIZE_ADDRESS
-#define TARGET_LEGITIMIZE_ADDRESS s390_legitimize_address
-
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY s390_return_in_memory
-
-#undef TARGET_INIT_BUILTINS
-#define TARGET_INIT_BUILTINS s390_init_builtins
-#undef TARGET_EXPAND_BUILTIN
-#define TARGET_EXPAND_BUILTIN s390_expand_builtin
-
-#undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA
-#define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA s390_output_addr_const_extra
-
-#undef TARGET_ASM_OUTPUT_MI_THUNK
-#define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
-#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
-#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
-
-#undef TARGET_SCHED_ADJUST_PRIORITY
-#define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
-#undef TARGET_SCHED_ISSUE_RATE
-#define TARGET_SCHED_ISSUE_RATE s390_issue_rate
-#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
-#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD s390_first_cycle_multipass_dfa_lookahead
-
-#undef TARGET_SCHED_VARIABLE_ISSUE
-#define TARGET_SCHED_VARIABLE_ISSUE s390_sched_variable_issue
-#undef TARGET_SCHED_REORDER
-#define TARGET_SCHED_REORDER s390_sched_reorder
-#undef TARGET_SCHED_INIT
-#define TARGET_SCHED_INIT s390_sched_init
-
-#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
-#define TARGET_ADDRESS_COST s390_address_cost
-#undef TARGET_REGISTER_MOVE_COST
-#define TARGET_REGISTER_MOVE_COST s390_register_move_cost
-#undef TARGET_MEMORY_MOVE_COST
-#define TARGET_MEMORY_MOVE_COST s390_memory_move_cost
-
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG s390_reorg
-
-#undef TARGET_VALID_POINTER_MODE
-#define TARGET_VALID_POINTER_MODE s390_valid_pointer_mode
-
-#undef TARGET_BUILD_BUILTIN_VA_LIST
-#define TARGET_BUILD_BUILTIN_VA_LIST s390_build_builtin_va_list
-#undef TARGET_EXPAND_BUILTIN_VA_START
-#define TARGET_EXPAND_BUILTIN_VA_START s390_va_start
-#undef TARGET_GIMPLIFY_VA_ARG_EXPR
-#define TARGET_GIMPLIFY_VA_ARG_EXPR s390_gimplify_va_arg
-
-#undef TARGET_PROMOTE_FUNCTION_MODE
-#define TARGET_PROMOTE_FUNCTION_MODE s390_promote_function_mode
-#undef TARGET_PASS_BY_REFERENCE
-#define TARGET_PASS_BY_REFERENCE s390_pass_by_reference
-
-#undef TARGET_FUNCTION_OK_FOR_SIBCALL
-#define TARGET_FUNCTION_OK_FOR_SIBCALL s390_function_ok_for_sibcall
-#undef TARGET_FUNCTION_ARG
-#define TARGET_FUNCTION_ARG s390_function_arg
-#undef TARGET_FUNCTION_ARG_ADVANCE
-#define TARGET_FUNCTION_ARG_ADVANCE s390_function_arg_advance
-#undef TARGET_FUNCTION_VALUE
-#define TARGET_FUNCTION_VALUE s390_function_value
-#undef TARGET_LIBCALL_VALUE
-#define TARGET_LIBCALL_VALUE s390_libcall_value
-
-#undef TARGET_FIXED_CONDITION_CODE_REGS
-#define TARGET_FIXED_CONDITION_CODE_REGS s390_fixed_condition_code_regs
-
-#undef TARGET_CC_MODES_COMPATIBLE
-#define TARGET_CC_MODES_COMPATIBLE s390_cc_modes_compatible
-
-#undef TARGET_INVALID_WITHIN_DOLOOP
-#define TARGET_INVALID_WITHIN_DOLOOP hook_constcharptr_const_rtx_null
-
-#ifdef HAVE_AS_TLS
-#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
-#define TARGET_ASM_OUTPUT_DWARF_DTPREL s390_output_dwarf_dtprel
-#endif
-
-#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
-#undef TARGET_MANGLE_TYPE
-#define TARGET_MANGLE_TYPE s390_mangle_type
-#endif
-
-#undef TARGET_SCALAR_MODE_SUPPORTED_P
-#define TARGET_SCALAR_MODE_SUPPORTED_P s390_scalar_mode_supported_p
-
-#undef TARGET_PREFERRED_RELOAD_CLASS
-#define TARGET_PREFERRED_RELOAD_CLASS s390_preferred_reload_class
-
-#undef TARGET_SECONDARY_RELOAD
-#define TARGET_SECONDARY_RELOAD s390_secondary_reload
-
-#undef TARGET_LIBGCC_CMP_RETURN_MODE
-#define TARGET_LIBGCC_CMP_RETURN_MODE s390_libgcc_cmp_return_mode
-
-#undef TARGET_LIBGCC_SHIFT_COUNT_MODE
-#define TARGET_LIBGCC_SHIFT_COUNT_MODE s390_libgcc_shift_count_mode
-
-#undef TARGET_LEGITIMATE_ADDRESS_P
-#define TARGET_LEGITIMATE_ADDRESS_P s390_legitimate_address_p
-
-#undef TARGET_LEGITIMATE_CONSTANT_P
-#define TARGET_LEGITIMATE_CONSTANT_P s390_legitimate_constant_p
-
-#undef TARGET_CAN_ELIMINATE
-#define TARGET_CAN_ELIMINATE s390_can_eliminate
-
-#undef TARGET_CONDITIONAL_REGISTER_USAGE
-#define TARGET_CONDITIONAL_REGISTER_USAGE s390_conditional_register_usage
-
-#undef TARGET_LOOP_UNROLL_ADJUST
-#define TARGET_LOOP_UNROLL_ADJUST s390_loop_unroll_adjust
-
-#undef TARGET_ASM_TRAMPOLINE_TEMPLATE
-#define TARGET_ASM_TRAMPOLINE_TEMPLATE s390_asm_trampoline_template
-#undef TARGET_TRAMPOLINE_INIT
-#define TARGET_TRAMPOLINE_INIT s390_trampoline_init
-
-#undef TARGET_UNWIND_WORD_MODE
-#define TARGET_UNWIND_WORD_MODE s390_unwind_word_mode
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-#include "gt-s390.h"
diff --git a/gcc-4.7/gcc/config/s390/s390.h b/gcc-4.7/gcc/config/s390/s390.h
deleted file mode 100644
index edc639978..000000000
--- a/gcc-4.7/gcc/config/s390/s390.h
+++ /dev/null
@@ -1,909 +0,0 @@
-/* Definitions of target machine for GNU compiler, for IBM S/390
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
- Contributed by Hartmut Penner (hpenner@de.ibm.com) and
- Ulrich Weigand (uweigand@de.ibm.com).
- Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef _S390_H
-#define _S390_H
-
-/* Optional architectural facilities supported by the processor. */
-
-enum processor_flags
-{
- PF_IEEE_FLOAT = 1,
- PF_ZARCH = 2,
- PF_LONG_DISPLACEMENT = 4,
- PF_EXTIMM = 8,
- PF_DFP = 16,
- PF_Z10 = 32,
- PF_Z196 = 64
-};
-
-/* This is necessary to avoid a warning about comparing different enum
- types. */
-#define s390_tune_attr ((enum attr_cpu)s390_tune)
-
-/* These flags indicate that the generated code should run on a cpu
- providing the respective hardware facility regardless of the
- current cpu mode (ESA or z/Architecture). */
-
-#define TARGET_CPU_IEEE_FLOAT \
- (s390_arch_flags & PF_IEEE_FLOAT)
-#define TARGET_CPU_ZARCH \
- (s390_arch_flags & PF_ZARCH)
-#define TARGET_CPU_LONG_DISPLACEMENT \
- (s390_arch_flags & PF_LONG_DISPLACEMENT)
-#define TARGET_CPU_EXTIMM \
- (s390_arch_flags & PF_EXTIMM)
-#define TARGET_CPU_DFP \
- (s390_arch_flags & PF_DFP)
-#define TARGET_CPU_Z10 \
- (s390_arch_flags & PF_Z10)
-#define TARGET_CPU_Z196 \
- (s390_arch_flags & PF_Z196)
-
-/* These flags indicate that the generated code should run on a cpu
- providing the respective hardware facility when run in
- z/Architecture mode. */
-
-#define TARGET_LONG_DISPLACEMENT \
- (TARGET_ZARCH && TARGET_CPU_LONG_DISPLACEMENT)
-#define TARGET_EXTIMM \
- (TARGET_ZARCH && TARGET_CPU_EXTIMM)
-#define TARGET_DFP \
- (TARGET_ZARCH && TARGET_CPU_DFP && TARGET_HARD_FLOAT)
-#define TARGET_Z10 \
- (TARGET_ZARCH && TARGET_CPU_Z10)
-#define TARGET_Z196 \
- (TARGET_ZARCH && TARGET_CPU_Z196)
-
-
-#define TARGET_AVOID_CMP_AND_BRANCH (s390_tune == PROCESSOR_2817_Z196)
-
-/* Run-time target specification. */
-
-/* Defaults for option flags defined only on some subtargets. */
-#ifndef TARGET_TPF_PROFILING
-#define TARGET_TPF_PROFILING 0
-#endif
-
-/* This will be overridden by OS headers. */
-#define TARGET_TPF 0
-
-/* Target CPU builtins. */
-#define TARGET_CPU_CPP_BUILTINS() \
- do \
- { \
- builtin_assert ("cpu=s390"); \
- builtin_assert ("machine=s390"); \
- builtin_define ("__s390__"); \
- if (TARGET_ZARCH) \
- builtin_define ("__zarch__"); \
- if (TARGET_64BIT) \
- builtin_define ("__s390x__"); \
- if (TARGET_LONG_DOUBLE_128) \
- builtin_define ("__LONG_DOUBLE_128__"); \
- } \
- while (0)
-
-#ifdef DEFAULT_TARGET_64BIT
-#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_DFP)
-#else
-#define TARGET_DEFAULT 0
-#endif
-
-/* Support for configure-time defaults. */
-#define OPTION_DEFAULT_SPECS \
- { "mode", "%{!mesa:%{!mzarch:-m%(VALUE)}}" }, \
- { "arch", "%{!march=*:-march=%(VALUE)}" }, \
- { "tune", "%{!mtune=*:-mtune=%(VALUE)}" }
-
-/* Defaulting rules. */
-#ifdef DEFAULT_TARGET_64BIT
-#define DRIVER_SELF_SPECS \
- "%{!m31:%{!m64:-m64}}", \
- "%{!mesa:%{!mzarch:%{m31:-mesa}%{m64:-mzarch}}}", \
- "%{!march=*:%{mesa:-march=g5}%{mzarch:-march=z900}}"
-#else
-#define DRIVER_SELF_SPECS \
- "%{!m31:%{!m64:-m31}}", \
- "%{!mesa:%{!mzarch:%{m31:-mesa}%{m64:-mzarch}}}", \
- "%{!march=*:%{mesa:-march=g5}%{mzarch:-march=z900}}"
-#endif
-
-/* Constants needed to control the TEST DATA CLASS (TDC) instruction. */
-#define S390_TDC_POSITIVE_ZERO (1 << 11)
-#define S390_TDC_NEGATIVE_ZERO (1 << 10)
-#define S390_TDC_POSITIVE_NORMALIZED_BFP_NUMBER (1 << 9)
-#define S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER (1 << 8)
-#define S390_TDC_POSITIVE_DENORMALIZED_BFP_NUMBER (1 << 7)
-#define S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER (1 << 6)
-#define S390_TDC_POSITIVE_INFINITY (1 << 5)
-#define S390_TDC_NEGATIVE_INFINITY (1 << 4)
-#define S390_TDC_POSITIVE_QUIET_NAN (1 << 3)
-#define S390_TDC_NEGATIVE_QUIET_NAN (1 << 2)
-#define S390_TDC_POSITIVE_SIGNALING_NAN (1 << 1)
-#define S390_TDC_NEGATIVE_SIGNALING_NAN (1 << 0)
-
-/* The following values are different for DFP. */
-#define S390_TDC_POSITIVE_DENORMALIZED_DFP_NUMBER (1 << 9)
-#define S390_TDC_NEGATIVE_DENORMALIZED_DFP_NUMBER (1 << 8)
-#define S390_TDC_POSITIVE_NORMALIZED_DFP_NUMBER (1 << 7)
-#define S390_TDC_NEGATIVE_NORMALIZED_DFP_NUMBER (1 << 6)
-
-/* For signbit, the BFP-DFP-difference makes no difference. */
-#define S390_TDC_SIGNBIT_SET (S390_TDC_NEGATIVE_ZERO \
- | S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER \
- | S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER\
- | S390_TDC_NEGATIVE_INFINITY \
- | S390_TDC_NEGATIVE_QUIET_NAN \
- | S390_TDC_NEGATIVE_SIGNALING_NAN )
-
-#define S390_TDC_INFINITY (S390_TDC_POSITIVE_INFINITY \
- | S390_TDC_NEGATIVE_INFINITY )
-
-/* Target machine storage layout. */
-
-/* Everything is big-endian. */
-#define BITS_BIG_ENDIAN 1
-#define BYTES_BIG_ENDIAN 1
-#define WORDS_BIG_ENDIAN 1
-
-#define STACK_SIZE_MODE (Pmode)
-
-#ifndef IN_LIBGCC2
-
-/* Width of a word, in units (bytes). */
- #define UNITS_PER_WORD (TARGET_ZARCH ? 8 : 4)
-
-/* Width of a pointer. To be used instead of UNITS_PER_WORD in
- ABI-relevant contexts. This always matches
- GET_MODE_SIZE (Pmode). */
- #define UNITS_PER_LONG (TARGET_64BIT ? 8 : 4)
- #define MIN_UNITS_PER_WORD 4
- #define MAX_BITS_PER_WORD 64
-#else
-
- /* In libgcc, UNITS_PER_WORD has ABI-relevant effects, e.g. whether
- the library should export TImode functions or not. Thus, we have
- to redefine UNITS_PER_WORD depending on __s390x__ for libgcc. */
- #ifdef __s390x__
- #define UNITS_PER_WORD 8
- #else
- #define UNITS_PER_WORD 4
- #endif
-#endif
-
-/* Width of a pointer, in bits. */
-#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
-
-/* Allocation boundary (in *bits*) for storing arguments in argument list. */
-#define PARM_BOUNDARY (TARGET_64BIT ? 64 : 32)
-
-/* Boundary (in *bits*) on which stack pointer should be aligned. */
-#define STACK_BOUNDARY 64
-
-/* Allocation boundary (in *bits*) for the code of a function. */
-#define FUNCTION_BOUNDARY 32
-
-/* There is no point aligning anything to a rounder boundary than this. */
-#define BIGGEST_ALIGNMENT 64
-
-/* Alignment of field after `int : 0' in a structure. */
-#define EMPTY_FIELD_BOUNDARY 32
-
-/* Alignment on even addresses for LARL instruction. */
-#define CONSTANT_ALIGNMENT(EXP, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN)
-#define DATA_ALIGNMENT(TYPE, ALIGN) (ALIGN) < 16 ? 16 : (ALIGN)
-
-/* Alignment is not required by the hardware. */
-#define STRICT_ALIGNMENT 0
-
-/* Mode of stack savearea.
- FUNCTION is VOIDmode because calling convention maintains SP.
- BLOCK needs Pmode for SP.
- NONLOCAL needs twice Pmode to maintain both backchain and SP. */
-#define STACK_SAVEAREA_MODE(LEVEL) \
- (LEVEL == SAVE_FUNCTION ? VOIDmode \
- : LEVEL == SAVE_NONLOCAL ? (TARGET_64BIT ? OImode : TImode) : Pmode)
-
-
-/* Type layout. */
-
-/* Sizes in bits of the source language data types. */
-#define SHORT_TYPE_SIZE 16
-#define INT_TYPE_SIZE 32
-#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
-#define LONG_LONG_TYPE_SIZE 64
-#define FLOAT_TYPE_SIZE 32
-#define DOUBLE_TYPE_SIZE 64
-#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
-
-/* Define this to set long double type size to use in libgcc2.c, which can
- not depend on target_flags. */
-#ifdef __LONG_DOUBLE_128__
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
-#else
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
-#endif
-
-/* Work around target_flags dependency in ada/targtyps.c. */
-#define WIDEST_HARDWARE_FP_SIZE 64
-
-/* We use "unsigned char" as default. */
-#define DEFAULT_SIGNED_CHAR 0
-
-
-/* Register usage. */
-
-/* We have 16 general purpose registers (registers 0-15),
- and 16 floating point registers (registers 16-31).
- (On non-IEEE machines, we have only 4 fp registers.)
-
- Amongst the general purpose registers, some are used
- for specific purposes:
- GPR 11: Hard frame pointer (if needed)
- GPR 12: Global offset table pointer (if needed)
- GPR 13: Literal pool base register
- GPR 14: Return address register
- GPR 15: Stack pointer
-
- Registers 32-35 are 'fake' hard registers that do not
- correspond to actual hardware:
- Reg 32: Argument pointer
- Reg 33: Condition code
- Reg 34: Frame pointer
- Reg 35: Return address pointer
-
- Registers 36 and 37 are mapped to access registers
- 0 and 1, used to implement thread-local storage. */
-
-#define FIRST_PSEUDO_REGISTER 38
-
-/* Standard register usage. */
-#define GENERAL_REGNO_P(N) ((int)(N) >= 0 && (N) < 16)
-#define ADDR_REGNO_P(N) ((N) >= 1 && (N) < 16)
-#define FP_REGNO_P(N) ((N) >= 16 && (N) < 32)
-#define CC_REGNO_P(N) ((N) == 33)
-#define FRAME_REGNO_P(N) ((N) == 32 || (N) == 34 || (N) == 35)
-#define ACCESS_REGNO_P(N) ((N) == 36 || (N) == 37)
-
-#define GENERAL_REG_P(X) (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
-#define ADDR_REG_P(X) (REG_P (X) && ADDR_REGNO_P (REGNO (X)))
-#define FP_REG_P(X) (REG_P (X) && FP_REGNO_P (REGNO (X)))
-#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
-#define FRAME_REG_P(X) (REG_P (X) && FRAME_REGNO_P (REGNO (X)))
-#define ACCESS_REG_P(X) (REG_P (X) && ACCESS_REGNO_P (REGNO (X)))
-
-/* Set up fixed registers and calling convention:
-
- GPRs 0-5 are always call-clobbered,
- GPRs 6-15 are always call-saved.
- GPR 12 is fixed if used as GOT pointer.
- GPR 13 is always fixed (as literal pool pointer).
- GPR 14 is always fixed on S/390 machines (as return address).
- GPR 15 is always fixed (as stack pointer).
- The 'fake' hard registers are call-clobbered and fixed.
- The access registers are call-saved and fixed.
-
- On 31-bit, FPRs 18-19 are call-clobbered;
- on 64-bit, FPRs 24-31 are call-clobbered.
- The remaining FPRs are call-saved. */
-
-#define FIXED_REGISTERS \
-{ 0, 0, 0, 0, \
- 0, 0, 0, 0, \
- 0, 0, 0, 0, \
- 0, 1, 1, 1, \
- 0, 0, 0, 0, \
- 0, 0, 0, 0, \
- 0, 0, 0, 0, \
- 0, 0, 0, 0, \
- 1, 1, 1, 1, \
- 1, 1 }
-
-#define CALL_USED_REGISTERS \
-{ 1, 1, 1, 1, \
- 1, 1, 0, 0, \
- 0, 0, 0, 0, \
- 0, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1 }
-
-#define CALL_REALLY_USED_REGISTERS \
-{ 1, 1, 1, 1, \
- 1, 1, 0, 0, \
- 0, 0, 0, 0, \
- 0, 0, 0, 0, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 1, 1, 1, 1, \
- 0, 0 }
-
-/* Preferred register allocation order. */
-#define REG_ALLOC_ORDER \
-{ 1, 2, 3, 4, 5, 0, 12, 11, 10, 9, 8, 7, 6, 14, 13, \
- 16, 17, 18, 19, 20, 21, 22, 23, \
- 24, 25, 26, 27, 28, 29, 30, 31, \
- 15, 32, 33, 34, 35, 36, 37 }
-
-
-/* Fitting values into registers. */
-
-/* Integer modes <= word size fit into any GPR.
- Integer modes > word size fit into successive GPRs, starting with
- an even-numbered register.
- SImode and DImode fit into FPRs as well.
-
- Floating point modes <= word size fit into any FPR or GPR.
- Floating point modes > word size (i.e. DFmode on 32-bit) fit
- into any FPR, or an even-odd GPR pair.
- TFmode fits only into an even-odd FPR pair.
-
- Complex floating point modes fit either into two FPRs, or into
- successive GPRs (again starting with an even number).
- TCmode fits only into two successive even-odd FPR pairs.
-
- Condition code modes fit only into the CC register. */
-
-/* Because all registers in a class have the same size HARD_REGNO_NREGS
- is equivalent to CLASS_MAX_NREGS. */
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- s390_class_max_nregs (REGNO_REG_CLASS (REGNO), (MODE))
-
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- s390_hard_regno_mode_ok ((REGNO), (MODE))
-
-#define HARD_REGNO_RENAME_OK(FROM, TO) \
- s390_hard_regno_rename_ok (FROM, TO)
-
-#define MODES_TIEABLE_P(MODE1, MODE2) \
- (((MODE1) == SFmode || (MODE1) == DFmode) \
- == ((MODE2) == SFmode || (MODE2) == DFmode))
-
-/* When generating code that runs in z/Architecture mode,
- but conforms to the 31-bit ABI, GPRs can hold 8 bytes;
- the ABI guarantees only that the lower 4 bytes are
- saved across calls, however. */
-#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
- (!TARGET_64BIT && TARGET_ZARCH \
- && GET_MODE_SIZE (MODE) > 4 \
- && (((REGNO) >= 6 && (REGNO) <= 15) || (REGNO) == 32))
-
-/* Maximum number of registers to represent a value of mode MODE
- in a register of class CLASS. */
-#define CLASS_MAX_NREGS(CLASS, MODE) \
- s390_class_max_nregs ((CLASS), (MODE))
-
-/* If a 4-byte value is loaded into a FPR, it is placed into the
- *upper* half of the register, not the lower. Therefore, we
- cannot use SUBREGs to switch between modes in FP registers.
- Likewise for access registers, since they have only half the
- word size on 64-bit. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
- ? ((reg_classes_intersect_p (FP_REGS, CLASS) \
- && (GET_MODE_SIZE (FROM) < 8 || GET_MODE_SIZE (TO) < 8)) \
- || reg_classes_intersect_p (ACCESS_REGS, CLASS)) : 0)
-
-/* Register classes. */
-
-/* We use the following register classes:
- GENERAL_REGS All general purpose registers
- ADDR_REGS All general purpose registers except %r0
- (These registers can be used in address generation)
- FP_REGS All floating point registers
- CC_REGS The condition code register
- ACCESS_REGS The access registers
-
- GENERAL_FP_REGS Union of GENERAL_REGS and FP_REGS
- ADDR_FP_REGS Union of ADDR_REGS and FP_REGS
- GENERAL_CC_REGS Union of GENERAL_REGS and CC_REGS
- ADDR_CC_REGS Union of ADDR_REGS and CC_REGS
-
- NO_REGS No registers
- ALL_REGS All registers
-
- Note that the 'fake' frame pointer and argument pointer registers
- are included amongst the address registers here. */
-
-enum reg_class
-{
- NO_REGS, CC_REGS, ADDR_REGS, GENERAL_REGS, ACCESS_REGS,
- ADDR_CC_REGS, GENERAL_CC_REGS,
- FP_REGS, ADDR_FP_REGS, GENERAL_FP_REGS,
- ALL_REGS, LIM_REG_CLASSES
-};
-#define N_REG_CLASSES (int) LIM_REG_CLASSES
-
-#define REG_CLASS_NAMES \
-{ "NO_REGS", "CC_REGS", "ADDR_REGS", "GENERAL_REGS", "ACCESS_REGS", \
- "ADDR_CC_REGS", "GENERAL_CC_REGS", \
- "FP_REGS", "ADDR_FP_REGS", "GENERAL_FP_REGS", "ALL_REGS" }
-
-/* Class -> register mapping. */
-#define REG_CLASS_CONTENTS \
-{ \
- { 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0x00000000, 0x00000002 }, /* CC_REGS */ \
- { 0x0000fffe, 0x0000000d }, /* ADDR_REGS */ \
- { 0x0000ffff, 0x0000000d }, /* GENERAL_REGS */ \
- { 0x00000000, 0x00000030 }, /* ACCESS_REGS */ \
- { 0x0000fffe, 0x0000000f }, /* ADDR_CC_REGS */ \
- { 0x0000ffff, 0x0000000f }, /* GENERAL_CC_REGS */ \
- { 0xffff0000, 0x00000000 }, /* FP_REGS */ \
- { 0xfffffffe, 0x0000000d }, /* ADDR_FP_REGS */ \
- { 0xffffffff, 0x0000000d }, /* GENERAL_FP_REGS */ \
- { 0xffffffff, 0x0000003f }, /* ALL_REGS */ \
-}
-
-/* In some case register allocation order is not enough for IRA to
- generate a good code. The following macro (if defined) increases
- cost of REGNO for a pseudo approximately by pseudo usage frequency
- multiplied by the macro value.
-
- We avoid usage of BASE_REGNUM by nonzero macro value because the
- reload can decide not to use the hard register because some
- constant was forced to be in memory. */
-#define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno) \
- (regno == BASE_REGNUM ? 0.0 : 0.5)
-
-/* Register -> class mapping. */
-extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
-#define REGNO_REG_CLASS(REGNO) (regclass_map[REGNO])
-
-/* ADDR_REGS can be used as base or index register. */
-#define INDEX_REG_CLASS ADDR_REGS
-#define BASE_REG_CLASS ADDR_REGS
-
-/* Check whether REGNO is a hard register of the suitable class
- or a pseudo register currently allocated to one such. */
-#define REGNO_OK_FOR_INDEX_P(REGNO) \
- (((REGNO) < FIRST_PSEUDO_REGISTER \
- && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS) \
- || ADDR_REGNO_P (reg_renumber[REGNO]))
-#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
-
-
-/* We need secondary memory to move data between GPRs and FPRs. With
- DFP the ldgr lgdr instructions are available. But these
- instructions do not handle GPR pairs so it is not possible for 31
- bit. */
-#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
- ((CLASS1) != (CLASS2) \
- && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS) \
- && (!TARGET_DFP || !TARGET_64BIT || GET_MODE_SIZE (MODE) != 8))
-
-/* Get_secondary_mem widens its argument to BITS_PER_WORD which loses on 64bit
- because the movsi and movsf patterns don't handle r/f moves. */
-#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
- (GET_MODE_BITSIZE (MODE) < 32 \
- ? mode_for_size (32, GET_MODE_CLASS (MODE), 0) \
- : MODE)
-
-
-/* Stack layout and calling conventions. */
-
-/* Our stack grows from higher to lower addresses. However, local variables
- are accessed by positive offsets, and function arguments are stored at
- increasing addresses. */
-#define STACK_GROWS_DOWNWARD
-#define FRAME_GROWS_DOWNWARD 1
-/* #undef ARGS_GROW_DOWNWARD */
-
-/* The basic stack layout looks like this: the stack pointer points
- to the register save area for called functions. Above that area
- is the location to place outgoing arguments. Above those follow
- dynamic allocations (alloca), and finally the local variables. */
-
-/* Offset from stack-pointer to first location of outgoing args. */
-#define STACK_POINTER_OFFSET (TARGET_64BIT ? 160 : 96)
-
-/* Offset within stack frame to start allocating local variables at. */
-#define STARTING_FRAME_OFFSET 0
-
-/* Offset from the stack pointer register to an item dynamically
- allocated on the stack, e.g., by `alloca'. */
-#define STACK_DYNAMIC_OFFSET(FUNDECL) \
- (STACK_POINTER_OFFSET + crtl->outgoing_args_size)
-
-/* Offset of first parameter from the argument pointer register value.
- We have a fake argument pointer register that points directly to
- the argument area. */
-#define FIRST_PARM_OFFSET(FNDECL) 0
-
-/* Defining this macro makes __builtin_frame_address(0) and
- __builtin_return_address(0) work with -fomit-frame-pointer. */
-#define INITIAL_FRAME_ADDRESS_RTX \
- (plus_constant (arg_pointer_rtx, -STACK_POINTER_OFFSET))
-
-/* The return address of the current frame is retrieved
- from the initial value of register RETURN_REGNUM.
- For frames farther back, we use the stack slot where
- the corresponding RETURN_REGNUM register was saved. */
-#define DYNAMIC_CHAIN_ADDRESS(FRAME) \
- (TARGET_PACKED_STACK ? \
- plus_constant ((FRAME), STACK_POINTER_OFFSET - UNITS_PER_LONG) : (FRAME))
-
-/* For -mpacked-stack this adds 160 - 8 (96 - 4) to the output of
- builtin_frame_address. Otherwise arg pointer -
- STACK_POINTER_OFFSET would be returned for
- __builtin_frame_address(0) what might result in an address pointing
- somewhere into the middle of the local variables since the packed
- stack layout generally does not need all the bytes in the register
- save area. */
-#define FRAME_ADDR_RTX(FRAME) \
- DYNAMIC_CHAIN_ADDRESS ((FRAME))
-
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
- s390_return_addr_rtx ((COUNT), DYNAMIC_CHAIN_ADDRESS ((FRAME)))
-
-/* In 31-bit mode, we need to mask off the high bit of return addresses. */
-#define MASK_RETURN_ADDR (TARGET_64BIT ? constm1_rtx : GEN_INT (0x7fffffff))
-
-
-/* Exception handling. */
-
-/* Describe calling conventions for DWARF-2 exception handling. */
-#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, RETURN_REGNUM)
-#define INCOMING_FRAME_SP_OFFSET STACK_POINTER_OFFSET
-#define DWARF_FRAME_RETURN_COLUMN 14
-
-/* Describe how we implement __builtin_eh_return. */
-#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
-#define EH_RETURN_HANDLER_RTX gen_rtx_MEM (Pmode, return_address_pointer_rtx)
-
-/* Select a format to encode pointers in exception handling data. */
-#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
- (flag_pic \
- ? ((GLOBAL) ? DW_EH_PE_indirect : 0) | DW_EH_PE_pcrel | DW_EH_PE_sdata4 \
- : DW_EH_PE_absptr)
-
-/* Register save slot alignment. */
-#define DWARF_CIE_DATA_ALIGNMENT (-UNITS_PER_LONG)
-
-
-/* Frame registers. */
-
-#define STACK_POINTER_REGNUM 15
-#define FRAME_POINTER_REGNUM 34
-#define HARD_FRAME_POINTER_REGNUM 11
-#define ARG_POINTER_REGNUM 32
-#define RETURN_ADDRESS_POINTER_REGNUM 35
-
-/* The static chain must be call-clobbered, but not used for
- function argument passing. As register 1 is clobbered by
- the trampoline code, we only have one option. */
-#define STATIC_CHAIN_REGNUM 0
-
-/* Number of hardware registers that go into the DWARF-2 unwind info.
- To avoid ABI incompatibility, this number must not change even as
- 'fake' hard registers are added or removed. */
-#define DWARF_FRAME_REGISTERS 34
-
-
-/* Frame pointer and argument pointer elimination. */
-
-#define ELIMINABLE_REGS \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
- { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
- { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
- { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
- { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
- { BASE_REGNUM, BASE_REGNUM }}
-
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- (OFFSET) = s390_initial_elimination_offset ((FROM), (TO))
-
-
-/* Stack arguments. */
-
-/* We need current_function_outgoing_args to be valid. */
-#define ACCUMULATE_OUTGOING_ARGS 1
-
-
-/* Register arguments. */
-
-typedef struct s390_arg_structure
-{
- int gprs; /* gpr so far */
- int fprs; /* fpr so far */
-}
-CUMULATIVE_ARGS;
-
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, NN, N_NAMED_ARGS) \
- ((CUM).gprs=0, (CUM).fprs=0)
-
-/* Arguments can be placed in general registers 2 to 6, or in floating
- point registers 0 and 2 for 31 bit and fprs 0, 2, 4 and 6 for 64
- bit. */
-#define FUNCTION_ARG_REGNO_P(N) (((N) >=2 && (N) <7) || \
- (N) == 16 || (N) == 17 || (TARGET_64BIT && ((N) == 18 || (N) == 19)))
-
-
-/* Only gpr 2 and fpr 0 are ever used as return registers. */
-#define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16)
-
-
-/* Function entry and exit. */
-
-/* When returning from a function, the stack pointer does not matter. */
-#define EXIT_IGNORE_STACK 1
-
-
-/* Profiling. */
-
-#define FUNCTION_PROFILER(FILE, LABELNO) \
- s390_function_profiler ((FILE), ((LABELNO)))
-
-#define PROFILE_BEFORE_PROLOGUE 1
-
-
-/* Trampolines for nested functions. */
-
-#define TRAMPOLINE_SIZE (TARGET_64BIT ? 32 : 16)
-#define TRAMPOLINE_ALIGNMENT BITS_PER_WORD
-
-/* Addressing modes, and classification of registers for them. */
-
-/* Recognize any constant value that is a valid address. */
-#define CONSTANT_ADDRESS_P(X) 0
-
-/* Maximum number of registers that can appear in a valid memory address. */
-#define MAX_REGS_PER_ADDRESS 2
-
-/* This definition replaces the formerly used 'm' constraint with a
- different constraint letter in order to avoid changing semantics of
- the 'm' constraint when accepting new address formats in
- TARGET_LEGITIMATE_ADDRESS_P. The constraint letter defined here
- must not be used in insn definitions or inline assemblies. */
-#define TARGET_MEM_CONSTRAINT 'e'
-
-/* Try a machine-dependent way of reloading an illegitimate address
- operand. If we find one, push the reload and jump to WIN. This
- macro is used in only one place: `find_reloads_address' in reload.c. */
-#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) \
-do { \
- rtx new_rtx = legitimize_reload_address (AD, MODE, OPNUM, (int)(TYPE)); \
- if (new_rtx) \
- { \
- (AD) = new_rtx; \
- goto WIN; \
- } \
-} while (0)
-
-/* Helper macro for s390.c and s390.md to check for symbolic constants. */
-#define SYMBOLIC_CONST(X) \
-(GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == LABEL_REF \
- || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
-
-#define TLS_SYMBOLIC_CONST(X) \
-((GET_CODE (X) == SYMBOL_REF && tls_symbolic_operand (X)) \
- || (GET_CODE (X) == CONST && tls_symbolic_reference_mentioned_p (X)))
-
-
-/* Condition codes. */
-
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. */
-#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
-
-/* Canonicalize a comparison from one we don't have to one we do have. */
-#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
-
-/* Relative costs of operations. */
-
-/* A C expression for the cost of a branch instruction. A value of 1
- is the default; other values are interpreted relative to that. */
-#define BRANCH_COST(speed_p, predictable_p) s390_branch_cost
-
-/* Nonzero if access to memory by bytes is slow and undesirable. */
-#define SLOW_BYTE_ACCESS 1
-
-/* An integer expression for the size in bits of the largest integer machine
- mode that should actually be used. We allow pairs of registers. */
-#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_64BIT ? TImode : DImode)
-
-/* The maximum number of bytes that a single instruction can move quickly
- between memory and registers or between two memory locations. */
-#define MOVE_MAX (TARGET_ZARCH ? 16 : 8)
-#define MOVE_MAX_PIECES (TARGET_ZARCH ? 8 : 4)
-#define MAX_MOVE_MAX 16
-
-/* Determine whether to use move_by_pieces or block move insn. */
-#define MOVE_BY_PIECES_P(SIZE, ALIGN) \
- ( (SIZE) == 1 || (SIZE) == 2 || (SIZE) == 4 \
- || (TARGET_ZARCH && (SIZE) == 8) )
-
-/* Determine whether to use clear_by_pieces or block clear insn. */
-#define CLEAR_BY_PIECES_P(SIZE, ALIGN) \
- ( (SIZE) == 1 || (SIZE) == 2 || (SIZE) == 4 \
- || (TARGET_ZARCH && (SIZE) == 8) )
-
-/* This macro is used to determine whether store_by_pieces should be
- called to "memcpy" storage when the source is a constant string. */
-#define STORE_BY_PIECES_P(SIZE, ALIGN) MOVE_BY_PIECES_P (SIZE, ALIGN)
-
-/* Likewise to decide whether to "memset" storage with byte values
- other than zero. */
-#define SET_BY_PIECES_P(SIZE, ALIGN) STORE_BY_PIECES_P (SIZE, ALIGN)
-
-/* Don't perform CSE on function addresses. */
-#define NO_FUNCTION_CSE
-
-/* This value is used in tree-sra to decide whether it might benefical
- to split a struct move into several word-size moves. For S/390
- only small values make sense here since struct moves are relatively
- cheap thanks to mvc so the small default value choosen for archs
- with memmove patterns should be ok. But this value is multiplied
- in tree-sra with UNITS_PER_WORD to make a decision so we adjust it
- here to compensate for that factor since mvc costs exactly the same
- on 31 and 64 bit. */
-#define MOVE_RATIO(speed) (TARGET_64BIT? 2 : 4)
-
-
-/* Sections. */
-
-/* Output before read-only data. */
-#define TEXT_SECTION_ASM_OP ".text"
-
-/* Output before writable (initialized) data. */
-#define DATA_SECTION_ASM_OP ".data"
-
-/* Output before writable (uninitialized) data. */
-#define BSS_SECTION_ASM_OP ".bss"
-
-/* S/390 constant pool breaks the devices in crtstuff.c to control section
- in where code resides. We have to write it as asm code. */
-#ifndef __s390x__
-#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
- asm (SECTION_OP "\n\
- bras\t%r2,1f\n\
-0: .long\t" USER_LABEL_PREFIX #FUNC " - 0b\n\
-1: l\t%r3,0(%r2)\n\
- bas\t%r14,0(%r3,%r2)\n\
- .previous");
-#endif
-
-
-/* Position independent code. */
-
-#define PIC_OFFSET_TABLE_REGNUM (flag_pic ? 12 : INVALID_REGNUM)
-
-#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X)
-
-
-/* Assembler file format. */
-
-/* Character to start a comment. */
-#define ASM_COMMENT_START "#"
-
-/* Declare an uninitialized external linkage data object. */
-#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
- asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
-
-/* Globalizing directive for a label. */
-#define GLOBAL_ASM_OP ".globl "
-
-/* Advance the location counter to a multiple of 2**LOG bytes. */
-#define ASM_OUTPUT_ALIGN(FILE, LOG) \
- if ((LOG)) fprintf ((FILE), "\t.align\t%d\n", 1 << (LOG))
-
-/* Advance the location counter by SIZE bytes. */
-#define ASM_OUTPUT_SKIP(FILE, SIZE) \
- fprintf ((FILE), "\t.set\t.,.+"HOST_WIDE_INT_PRINT_UNSIGNED"\n", (SIZE))
-
-/* The LOCAL_LABEL_PREFIX variable is used by dbxelf.h. */
-#define LOCAL_LABEL_PREFIX "."
-
-#define LABEL_ALIGN(LABEL) \
- s390_label_align (LABEL)
-
-/* How to refer to registers in assembler output. This sequence is
- indexed by compiler's hard-register-number (see above). */
-#define REGISTER_NAMES \
-{ "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", \
- "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \
- "%f0", "%f2", "%f4", "%f6", "%f1", "%f3", "%f5", "%f7", \
- "%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
- "%ap", "%cc", "%fp", "%rp", "%a0", "%a1" \
-}
-
-/* Print operand X (an rtx) in assembler syntax to file FILE. */
-#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
-#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
-
-/* Output an element of a case-vector that is absolute. */
-#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
-do { \
- char buf[32]; \
- fputs (integer_asm_op (UNITS_PER_LONG, TRUE), (FILE)); \
- ASM_GENERATE_INTERNAL_LABEL (buf, "L", (VALUE)); \
- assemble_name ((FILE), buf); \
- fputc ('\n', (FILE)); \
-} while (0)
-
-/* Output an element of a case-vector that is relative. */
-#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
-do { \
- char buf[32]; \
- fputs (integer_asm_op (UNITS_PER_LONG, TRUE), (FILE)); \
- ASM_GENERATE_INTERNAL_LABEL (buf, "L", (VALUE)); \
- assemble_name ((FILE), buf); \
- fputc ('-', (FILE)); \
- ASM_GENERATE_INTERNAL_LABEL (buf, "L", (REL)); \
- assemble_name ((FILE), buf); \
- fputc ('\n', (FILE)); \
-} while (0)
-
-
-/* Miscellaneous parameters. */
-
-/* Specify the machine mode that this machine uses for the index in the
- tablejump instruction. */
-#define CASE_VECTOR_MODE (TARGET_64BIT ? DImode : SImode)
-
-/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
- is done just by pretending it is already truncated. */
-#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
-
-/* Specify the machine mode that pointers have.
- After generation of rtl, the compiler makes no further distinction
- between pointers and any other objects of this machine mode. */
-#define Pmode ((enum machine_mode) (TARGET_64BIT ? DImode : SImode))
-
-/* This is -1 for "pointer mode" extend. See ptr_extend in s390.md. */
-#define POINTERS_EXTEND_UNSIGNED -1
-
-/* A function address in a call instruction is a byte address (for
- indexing purposes) so give the MEM rtx a byte's mode. */
-#define FUNCTION_MODE QImode
-
-/* Specify the value which is used when clz operand is zero. */
-#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, 1)
-
-/* Machine-specific symbol_ref flags. */
-#define SYMBOL_FLAG_ALIGN1 (SYMBOL_FLAG_MACH_DEP << 0)
-#define SYMBOL_REF_ALIGN1_P(X) \
- ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_ALIGN1))
-#define SYMBOL_FLAG_NOT_NATURALLY_ALIGNED (SYMBOL_FLAG_MACH_DEP << 1)
-#define SYMBOL_REF_NOT_NATURALLY_ALIGNED_P(X) \
- ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_NOT_NATURALLY_ALIGNED))
-
-/* Check whether integer displacement is in range. */
-#define DISP_IN_RANGE(d) \
- (TARGET_LONG_DISPLACEMENT? ((d) >= -524288 && (d) <= 524287) \
- : ((d) >= 0 && (d) <= 4095))
-
-/* Reads can reuse write prefetches, used by tree-ssa-prefetch-loops.c. */
-#define READ_CAN_USE_WRITE_PREFETCH 1
-
-extern const int processor_flags_table[];
-#endif
diff --git a/gcc-4.7/gcc/config/s390/s390.md b/gcc-4.7/gcc/config/s390/s390.md
deleted file mode 100644
index a875eec7b..000000000
--- a/gcc-4.7/gcc/config/s390/s390.md
+++ /dev/null
@@ -1,9416 +0,0 @@
-;;- Machine description for GNU compiler -- S/390 / zSeries version.
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-;; 2009, 2010 Free Software Foundation, Inc.
-;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-;; Ulrich Weigand (uweigand@de.ibm.com) and
-;; Andreas Krebbel (Andreas.Krebbel@de.ibm.com)
-
-;; This file is part of GCC.
-
-;; GCC is free software; you can redistribute it and/or modify it under
-;; the terms of the GNU General Public License as published by the Free
-;; Software Foundation; either version 3, or (at your option) any later
-;; version.
-
-;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-;; for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-;;
-;; See constraints.md for a description of constraints specific to s390.
-;;
-
-;; Special formats used for outputting 390 instructions.
-;;
-;; %C: print opcode suffix for branch condition.
-;; %D: print opcode suffix for inverse branch condition.
-;; %J: print tls_load/tls_gdcall/tls_ldcall suffix
-;; %G: print the size of the operand in bytes.
-;; %O: print only the displacement of a memory reference.
-;; %R: print only the base register of a memory reference.
-;; %S: print S-type memory reference (base+displacement).
-;; %N: print the second word of a DImode operand.
-;; %M: print the second word of a TImode operand.
-;; %Y: print shift count operand.
-;;
-;; %b: print integer X as if it's an unsigned byte.
-;; %c: print integer X as if it's an signed byte.
-;; %x: print integer X as if it's an unsigned halfword.
-;; %h: print integer X as if it's a signed halfword.
-;; %i: print the first nonzero HImode part of X.
-;; %j: print the first HImode part unequal to -1 of X.
-;; %k: print the first nonzero SImode part of X.
-;; %m: print the first SImode part unequal to -1 of X.
-;; %o: print integer X as if it's an unsigned 32bit word.
-;;
-;; We have a special constraint for pattern matching.
-;;
-;; s_operand -- Matches a valid S operand in a RS, SI or SS type instruction.
-;;
-
-;;
-;; UNSPEC usage
-;;
-
-(define_c_enum "unspec" [
- ; Miscellaneous
- UNSPEC_ROUND
- UNSPEC_CCU_TO_INT
- UNSPEC_CCZ_TO_INT
- UNSPEC_ICM
- UNSPEC_TIE
-
- ; GOT/PLT and lt-relative accesses
- UNSPEC_LTREL_OFFSET
- UNSPEC_LTREL_BASE
- UNSPEC_POOL_OFFSET
- UNSPEC_GOTENT
- UNSPEC_GOT
- UNSPEC_GOTOFF
- UNSPEC_PLT
- UNSPEC_PLTOFF
-
- ; Literal pool
- UNSPEC_RELOAD_BASE
- UNSPEC_MAIN_BASE
- UNSPEC_LTREF
- UNSPEC_INSN
- UNSPEC_EXECUTE
-
- ; Atomic Support
- UNSPEC_MB
-
- ; TLS relocation specifiers
- UNSPEC_TLSGD
- UNSPEC_TLSLDM
- UNSPEC_NTPOFF
- UNSPEC_DTPOFF
- UNSPEC_GOTNTPOFF
- UNSPEC_INDNTPOFF
-
- ; TLS support
- UNSPEC_TLSLDM_NTPOFF
- UNSPEC_TLS_LOAD
-
- ; String Functions
- UNSPEC_SRST
- UNSPEC_MVST
-
- ; Stack Smashing Protector
- UNSPEC_SP_SET
- UNSPEC_SP_TEST
-
- ; Test Data Class (TDC)
- UNSPEC_TDC_INSN
-
- ; Population Count
- UNSPEC_POPCNT
- UNSPEC_COPYSIGN
- ])
-
-;;
-;; UNSPEC_VOLATILE usage
-;;
-
-(define_c_enum "unspecv" [
- ; Blockage
- UNSPECV_BLOCKAGE
-
- ; TPF Support
- UNSPECV_TPF_PROLOGUE
- UNSPECV_TPF_EPILOGUE
-
- ; Literal pool
- UNSPECV_POOL
- UNSPECV_POOL_SECTION
- UNSPECV_POOL_ALIGN
- UNSPECV_POOL_ENTRY
- UNSPECV_MAIN_POOL
-
- ; TLS support
- UNSPECV_SET_TP
-
- ; Atomic Support
- UNSPECV_CAS
- UNSPECV_ATOMIC_OP
- ])
-
-;;
-;; Registers
-;;
-
-; Registers with special meaning
-
-(define_constants
- [
- ; Sibling call register.
- (SIBCALL_REGNUM 1)
- ; Literal pool base register.
- (BASE_REGNUM 13)
- ; Return address register.
- (RETURN_REGNUM 14)
- ; Condition code register.
- (CC_REGNUM 33)
- ; Thread local storage pointer register.
- (TP_REGNUM 36)
- ])
-
-; Hardware register names
-
-(define_constants
- [
- ; General purpose registers
- (GPR0_REGNUM 0)
- ; Floating point registers.
- (FPR0_REGNUM 16)
- (FPR2_REGNUM 18)
- ])
-
-;;
-;; PFPO GPR0 argument format
-;;
-
-(define_constants
- [
- ; PFPO operation type
- (PFPO_CONVERT 0x1000000)
- ; PFPO operand types
- (PFPO_OP_TYPE_SF 0x5)
- (PFPO_OP_TYPE_DF 0x6)
- (PFPO_OP_TYPE_TF 0x7)
- (PFPO_OP_TYPE_SD 0x8)
- (PFPO_OP_TYPE_DD 0x9)
- (PFPO_OP_TYPE_TD 0xa)
- ; Bitposition of operand types
- (PFPO_OP0_TYPE_SHIFT 16)
- (PFPO_OP1_TYPE_SHIFT 8)
- ])
-
-
-;; Instruction operand type as used in the Principles of Operation.
-;; Used to determine defaults for length and other attribute values.
-
-(define_attr "op_type"
- "NN,E,RR,RRE,RX,RS,RSI,RI,SI,S,SS,SSE,RXE,RSE,RIL,RIE,RXY,RSY,SIY,RRF,RRR,SIL,RRS,RIS"
- (const_string "NN"))
-
-;; Instruction type attribute used for scheduling.
-
-(define_attr "type" "none,integer,load,lr,la,larl,lm,stm,
- cs,vs,store,sem,idiv,
- imulhi,imulsi,imuldi,
- branch,jsr,fsimptf,fsimpdf,fsimpsf,fhex,
- floadtf,floaddf,floadsf,fstoredf,fstoresf,
- fmultf,fmuldf,fmulsf,fdivtf,fdivdf,fdivsf,
- ftoi,fsqrttf,fsqrtdf,fsqrtsf,
- fmadddf,fmaddsf,
- ftrunctf,ftruncdf, ftruncsd, ftruncdd,
- itoftf, itofdf, itofsf, itofdd, itoftd,
- fdivdd, fdivtd, floaddd, floadsd, fmuldd, fmultd,
- fsimpdd, fsimpsd, fsimptd, fstoredd, fstoresd,
- ftoidfp, other"
- (cond [(eq_attr "op_type" "NN") (const_string "other")
- (eq_attr "op_type" "SS") (const_string "cs")]
- (const_string "integer")))
-
-;; Another attribute used for scheduling purposes:
-;; agen: Instruction uses the address generation unit
-;; reg: Instruction does not use the agen unit
-
-(define_attr "atype" "agen,reg"
- (if_then_else (eq_attr "op_type" "E,RR,RI,RRE,RSI,RIL,RIE,RRF,RRR")
- (const_string "reg")
- (const_string "agen")))
-
-;; Properties concerning Z10 execution grouping and value forwarding.
-;; z10_super: instruction is superscalar.
-;; z10_super_c: instruction is superscalar and meets the condition of z10_c.
-;; z10_fwd: The instruction reads the value of an operand and stores it into a
-;; target register. It can forward this value to a second instruction that reads
-;; the same register if that second instruction is issued in the same group.
-;; z10_rec: The instruction is in the T pipeline and reads a register. If the
-;; instruction in the S pipe writes to the register, then the T instruction
-;; can immediately read the new value.
-;; z10_fr: union of Z10_fwd and z10_rec.
-;; z10_c: second operand of instruction is a register and read with complemented bits.
-;;
-;; An additional suffix A1, A3, or E1 indicates the respective AGI bypass.
-
-
-(define_attr "z10prop" "none,
- z10_super, z10_super_E1, z10_super_A1, z10_super_c, z10_super_c_E1,
- z10_fwd, z10_fwd_A1, z10_fwd_A3, z10_fwd_E1,
- z10_rec,
- z10_fr, z10_fr_A3, z10_fr_E1,
- z10_c"
- (const_string "none"))
-
-;; Properties concerning Z196 decoding
-;; z196_alone: must group alone
-;; z196_end: ends a group
-;; z196_cracked: instruction is cracked or expanded
-(define_attr "z196prop" "none,
- z196_alone, z196_ends,
- z196_cracked"
- (const_string "none"))
-
-;; Length in bytes.
-
-(define_attr "length" ""
- (cond [(eq_attr "op_type" "E,RR") (const_int 2)
- (eq_attr "op_type" "RX,RI,RRE,RS,RSI,S,SI,RRF,RRR") (const_int 4)]
- (const_int 6)))
-
-
-;; Processor type. This attribute must exactly match the processor_type
-;; enumeration in s390.h. The current machine description does not
-;; distinguish between g5 and g6, but there are differences between the two
-;; CPUs could in theory be modeled.
-
-(define_attr "cpu" "g5,g6,z900,z990,z9_109,z9_ec,z10,z196"
- (const (symbol_ref "s390_tune_attr")))
-
-(define_attr "cpu_facility" "standard,ieee,zarch,longdisp,extimm,dfp,z10,z196"
- (const_string "standard"))
-
-(define_attr "enabled" ""
- (cond [(eq_attr "cpu_facility" "standard")
- (const_int 1)
-
- (and (eq_attr "cpu_facility" "ieee")
- (match_test "TARGET_CPU_IEEE_FLOAT"))
- (const_int 1)
-
- (and (eq_attr "cpu_facility" "zarch")
- (match_test "TARGET_ZARCH"))
- (const_int 1)
-
- (and (eq_attr "cpu_facility" "longdisp")
- (match_test "TARGET_LONG_DISPLACEMENT"))
- (const_int 1)
-
- (and (eq_attr "cpu_facility" "extimm")
- (match_test "TARGET_EXTIMM"))
- (const_int 1)
-
- (and (eq_attr "cpu_facility" "dfp")
- (match_test "TARGET_DFP"))
- (const_int 1)
-
- (and (eq_attr "cpu_facility" "z10")
- (match_test "TARGET_Z10"))
- (const_int 1)
-
- (and (eq_attr "cpu_facility" "z196")
- (match_test "TARGET_Z196"))
- (const_int 1)]
- (const_int 0)))
-
-;; Pipeline description for z900. For lack of anything better,
-;; this description is also used for the g5 and g6.
-(include "2064.md")
-
-;; Pipeline description for z990, z9-109 and z9-ec.
-(include "2084.md")
-
-;; Pipeline description for z10
-(include "2097.md")
-
-;; Pipeline description for z196
-(include "2817.md")
-
-;; Predicates
-(include "predicates.md")
-
-;; Constraint definitions
-(include "constraints.md")
-
-;; Other includes
-(include "tpf.md")
-
-;; Iterators
-
-;; These mode iterators allow floating point patterns to be generated from the
-;; same template.
-(define_mode_iterator FP_ALL [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
- (SD "TARGET_HARD_DFP")])
-(define_mode_iterator FP [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
-(define_mode_iterator FPALL [TF DF SF TD DD SD])
-(define_mode_iterator BFP [TF DF SF])
-(define_mode_iterator DFP [TD DD])
-(define_mode_iterator DFP_ALL [TD DD SD])
-(define_mode_iterator DSF [DF SF])
-(define_mode_iterator SD_SF [SF SD])
-(define_mode_iterator DD_DF [DF DD])
-(define_mode_iterator TD_TF [TF TD])
-
-;; This mode iterator allows 31-bit and 64-bit TDSI patterns to be generated
-;; from the same template.
-(define_mode_iterator TDSI [(TI "TARGET_64BIT") DI SI])
-
-;; These mode iterators allow 31-bit and 64-bit GPR patterns to be generated
-;; from the same template.
-(define_mode_iterator GPR [(DI "TARGET_ZARCH") SI])
-(define_mode_iterator DSI [DI SI])
-
-;; These mode iterators allow :P to be used for patterns that operate on
-;; pointer-sized quantities. Exactly one of the two alternatives will match.
-(define_mode_iterator P [(DI "TARGET_64BIT") (SI "!TARGET_64BIT")])
-
-;; These macros refer to the actual word_mode of the configuration. This is equal
-;; to Pmode except on 31-bit machines in zarch mode.
-(define_mode_iterator DW [(TI "TARGET_ZARCH") (DI "!TARGET_ZARCH")])
-(define_mode_iterator W [(DI "TARGET_ZARCH") (SI "!TARGET_ZARCH")])
-
-;; Used by the umul pattern to express modes having half the size.
-(define_mode_attr DWH [(TI "DI") (DI "SI")])
-(define_mode_attr dwh [(TI "di") (DI "si")])
-
-;; This mode iterator allows the QI and HI patterns to be defined from
-;; the same template.
-(define_mode_iterator HQI [HI QI])
-
-;; This mode iterator allows the integer patterns to be defined from the
-;; same template.
-(define_mode_iterator INT [(DI "TARGET_ZARCH") SI HI QI])
-(define_mode_iterator INTALL [TI DI SI HI QI])
-
-;; This iterator allows some 'ashift' and 'lshiftrt' pattern to be defined from
-;; the same template.
-(define_code_iterator SHIFT [ashift lshiftrt])
-
-;; This iterator and attribute allow to combine most atomic operations.
-(define_code_iterator ATOMIC [and ior xor plus minus mult])
-(define_code_iterator ATOMIC_Z196 [and ior xor plus])
-(define_code_attr atomic [(and "and") (ior "ior") (xor "xor")
- (plus "add") (minus "sub") (mult "nand")])
-(define_code_attr noxa [(and "n") (ior "o") (xor "x") (plus "a")])
-
-;; In FP templates, a string like "lt<de>br" will expand to "ltxbr" in
-;; TF/TDmode, "ltdbr" in DF/DDmode, and "ltebr" in SF/SDmode.
-(define_mode_attr xde [(TF "x") (DF "d") (SF "e") (TD "x") (DD "d") (SD "e")])
-
-;; In FP templates, a <dee> in "m<dee><bt>r" will expand to "mx<bt>r" in
-;; TF/TDmode, "md<bt>r" in DF/DDmode, "mee<bt>r" in SFmode and "me<bt>r in
-;; SDmode.
-(define_mode_attr xdee [(TF "x") (DF "d") (SF "ee") (TD "x") (DD "d") (SD "e")])
-
-;; In FP templates, "<RRe>" will expand to "RRE" in TFmode and "RR" otherwise.
-;; Likewise for "<RXe>".
-(define_mode_attr RRe [(TF "RRE") (DF "RR") (SF "RR")])
-(define_mode_attr RXe [(TF "RXE") (DF "RX") (SF "RX")])
-
-;; The decimal floating point variants of add, sub, div and mul support 3
-;; fp register operands. The following attributes allow to merge the bfp and
-;; dfp variants in a single insn definition.
-
-;; This attribute is used to set op_type accordingly.
-(define_mode_attr RRer [(TF "RRE") (DF "RRE") (SF "RRE") (TD "RRR")
- (DD "RRR") (SD "RRR")])
-
-;; This attribute is used in the operand constraint list in order to have the
-;; first and the second operand match for bfp modes.
-(define_mode_attr f0 [(TF "0") (DF "0") (SF "0") (TD "f") (DD "f") (DD "f")])
-
-;; This attribute is used in the operand list of the instruction to have an
-;; additional operand for the dfp instructions.
-(define_mode_attr op1 [(TF "") (DF "") (SF "")
- (TD "%1,") (DD "%1,") (SD "%1,")])
-
-
-;; This attribute is used in the operand constraint list
-;; for instructions dealing with the sign bit of 32 or 64bit fp values.
-;; TFmode values are represented by a fp register pair. Since the
-;; sign bit instructions only handle single source and target fp registers
-;; these instructions can only be used for TFmode values if the source and
-;; target operand uses the same fp register.
-(define_mode_attr fT0 [(TF "0") (DF "f") (SF "f")])
-
-;; In FP templates, "<Rf>" will expand to "f" in TFmode and "R" otherwise.
-;; This is used to disable the memory alternative in TFmode patterns.
-(define_mode_attr Rf [(TF "f") (DF "R") (SF "R") (TD "f") (DD "f") (SD "f")])
-
-;; This attribute adds b for bfp instructions and t for dfp instructions and is used
-;; within instruction mnemonics.
-(define_mode_attr bt [(TF "b") (DF "b") (SF "b") (TD "t") (DD "t") (SD "t")])
-
-;; This attribute is used within instruction mnemonics. It evaluates to d for dfp
-;; modes and to an empty string for bfp modes.
-(define_mode_attr _d [(TF "") (DF "") (SF "") (TD "d") (DD "d") (SD "d")])
-
-;; In GPR and P templates, a constraint like "<d0>" will expand to "d" in DImode
-;; and "0" in SImode. This allows to combine instructions of which the 31bit
-;; version only operates on one register.
-(define_mode_attr d0 [(DI "d") (SI "0")])
-
-;; In combination with d0 this allows to combine instructions of which the 31bit
-;; version only operates on one register. The DImode version needs an additional
-;; register for the assembler output.
-(define_mode_attr 1 [(DI "%1,") (SI "")])
-
-;; In SHIFT templates, a string like "s<lr>dl" will expand to "sldl" in
-;; 'ashift' and "srdl" in 'lshiftrt'.
-(define_code_attr lr [(ashift "l") (lshiftrt "r")])
-
-;; In SHIFT templates, this attribute holds the correct standard name for the
-;; pattern itself and the corresponding function calls.
-(define_code_attr shift [(ashift "ashl") (lshiftrt "lshr")])
-
-;; This attribute handles differences in the instruction 'type' and will result
-;; in "RRE" for DImode and "RR" for SImode.
-(define_mode_attr E [(DI "E") (SI "")])
-
-;; This attribute handles differences in the instruction 'type' and makes RX<Y>
-;; to result in "RXY" for DImode and "RX" for SImode.
-(define_mode_attr Y [(DI "Y") (SI "")])
-
-;; This attribute handles differences in the instruction 'type' and will result
-;; in "RSE" for TImode and "RS" for DImode.
-(define_mode_attr TE [(TI "E") (DI "")])
-
-;; In GPR templates, a string like "lc<g>r" will expand to "lcgr" in DImode
-;; and "lcr" in SImode.
-(define_mode_attr g [(DI "g") (SI "")])
-
-;; In GPR templates, a string like "sl<y>" will expand to "slg" in DImode
-;; and "sly" in SImode. This is useful because on 64bit the ..g instructions
-;; were enhanced with long displacements whereas 31bit instructions got a ..y
-;; variant for long displacements.
-(define_mode_attr y [(DI "g") (SI "y")])
-
-;; In DW templates, a string like "cds<g>" will expand to "cdsg" in TImode
-;; and "cds" in DImode.
-(define_mode_attr tg [(TI "g") (DI "")])
-
-;; In GPR templates, a string like "c<gf>dbr" will expand to "cgdbr" in DImode
-;; and "cfdbr" in SImode.
-(define_mode_attr gf [(DI "g") (SI "f")])
-
-;; In GPR templates, a string like sll<gk> will expand to sllg for DI
-;; and sllk for SI. This way it is possible to merge the new z196 SI
-;; 3 operands shift instructions into the existing patterns.
-(define_mode_attr gk [(DI "g") (SI "k")])
-
-;; ICM mask required to load MODE value into the lowest subreg
-;; of a SImode register.
-(define_mode_attr icm_lo [(HI "3") (QI "1")])
-
-;; In HQI templates, a string like "llg<hc>" will expand to "llgh" in
-;; HImode and "llgc" in QImode.
-(define_mode_attr hc [(HI "h") (QI "c")])
-
-;; In P templates, the mode <DBL> will expand to "TI" in DImode and "DI"
-;; in SImode.
-(define_mode_attr DBL [(DI "TI") (SI "DI")])
-
-;; This attribute expands to DF for TFmode and to DD for TDmode . It is
-;; used for Txmode splitters splitting a Txmode copy into 2 Dxmode copies.
-(define_mode_attr HALF_TMODE [(TF "DF") (TD "DD")])
-
-;; Maximum unsigned integer that fits in MODE.
-(define_mode_attr max_uint [(HI "65535") (QI "255")])
-
-;;
-;;- Compare instructions.
-;;
-
-; Test-under-Mask instructions
-
-(define_insn "*tmqi_mem"
- [(set (reg CC_REGNUM)
- (compare (and:QI (match_operand:QI 0 "memory_operand" "Q,S")
- (match_operand:QI 1 "immediate_operand" "n,n"))
- (match_operand:QI 2 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], false))"
- "@
- tm\t%S0,%b1
- tmy\t%S0,%b1"
- [(set_attr "op_type" "SI,SIY")
- (set_attr "z10prop" "z10_super,z10_super")])
-
-(define_insn "*tmdi_reg"
- [(set (reg CC_REGNUM)
- (compare (and:DI (match_operand:DI 0 "nonimmediate_operand" "d,d,d,d")
- (match_operand:DI 1 "immediate_operand"
- "N0HD0,N1HD0,N2HD0,N3HD0"))
- (match_operand:DI 2 "immediate_operand" "n,n,n,n")))]
- "TARGET_ZARCH
- && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], true))
- && s390_single_part (operands[1], DImode, HImode, 0) >= 0"
- "@
- tmhh\t%0,%i1
- tmhl\t%0,%i1
- tmlh\t%0,%i1
- tmll\t%0,%i1"
- [(set_attr "op_type" "RI")
- (set_attr "z10prop" "z10_super,z10_super,z10_super,z10_super")])
-
-(define_insn "*tmsi_reg"
- [(set (reg CC_REGNUM)
- (compare (and:SI (match_operand:SI 0 "nonimmediate_operand" "d,d")
- (match_operand:SI 1 "immediate_operand" "N0HS0,N1HS0"))
- (match_operand:SI 2 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], true))
- && s390_single_part (operands[1], SImode, HImode, 0) >= 0"
- "@
- tmh\t%0,%i1
- tml\t%0,%i1"
- [(set_attr "op_type" "RI")
- (set_attr "z10prop" "z10_super,z10_super")])
-
-(define_insn "*tm<mode>_full"
- [(set (reg CC_REGNUM)
- (compare (match_operand:HQI 0 "register_operand" "d")
- (match_operand:HQI 1 "immediate_operand" "n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (constm1_rtx, operands[1], true))"
- "tml\t%0,<max_uint>"
- [(set_attr "op_type" "RI")
- (set_attr "z10prop" "z10_super")])
-
-
-;
-; Load-and-Test instructions
-;
-
-; tst(di|si) instruction pattern(s).
-
-(define_insn "*tstdi_sign"
- [(set (reg CC_REGNUM)
- (compare
- (ashiftrt:DI
- (ashift:DI
- (subreg:DI (match_operand:SI 0 "nonimmediate_operand" "d,RT") 0)
- (const_int 32)) (const_int 32))
- (match_operand:DI 1 "const0_operand" "")))
- (set (match_operand:DI 2 "register_operand" "=d,d")
- (sign_extend:DI (match_dup 0)))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_ZARCH"
- "ltgfr\t%2,%0
- ltgf\t%2,%0"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "cpu_facility" "*,z10")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1") ])
-
-; ltr, lt, ltgr, ltg
-(define_insn "*tst<mode>_extimm"
- [(set (reg CC_REGNUM)
- (compare (match_operand:GPR 0 "nonimmediate_operand" "d,RT")
- (match_operand:GPR 1 "const0_operand" "")))
- (set (match_operand:GPR 2 "register_operand" "=d,d")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_EXTIMM"
- "@
- lt<g>r\t%2,%0
- lt<g>\t%2,%0"
- [(set_attr "op_type" "RR<E>,RXY")
- (set_attr "z10prop" "z10_fr_E1,z10_fwd_A3") ])
-
-; ltr, lt, ltgr, ltg
-(define_insn "*tst<mode>_cconly_extimm"
- [(set (reg CC_REGNUM)
- (compare (match_operand:GPR 0 "nonimmediate_operand" "d,RT")
- (match_operand:GPR 1 "const0_operand" "")))
- (clobber (match_scratch:GPR 2 "=X,d"))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_EXTIMM"
- "@
- lt<g>r\t%0,%0
- lt<g>\t%2,%0"
- [(set_attr "op_type" "RR<E>,RXY")
- (set_attr "z10prop" "z10_fr_E1,z10_fwd_A3")])
-
-(define_insn "*tstdi"
- [(set (reg CC_REGNUM)
- (compare (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const0_operand" "")))
- (set (match_operand:DI 2 "register_operand" "=d")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_ZARCH && !TARGET_EXTIMM"
- "ltgr\t%2,%0"
- [(set_attr "op_type" "RRE")
- (set_attr "z10prop" "z10_fr_E1")])
-
-(define_insn "*tstsi"
- [(set (reg CC_REGNUM)
- (compare (match_operand:SI 0 "nonimmediate_operand" "d,Q,S")
- (match_operand:SI 1 "const0_operand" "")))
- (set (match_operand:SI 2 "register_operand" "=d,d,d")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCSmode) && !TARGET_EXTIMM"
- "@
- ltr\t%2,%0
- icm\t%2,15,%S0
- icmy\t%2,15,%S0"
- [(set_attr "op_type" "RR,RS,RSY")
- (set_attr "z10prop" "z10_fr_E1,z10_super_E1,z10_super_E1")])
-
-(define_insn "*tstsi_cconly"
- [(set (reg CC_REGNUM)
- (compare (match_operand:SI 0 "nonimmediate_operand" "d,Q,S")
- (match_operand:SI 1 "const0_operand" "")))
- (clobber (match_scratch:SI 2 "=X,d,d"))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- ltr\t%0,%0
- icm\t%2,15,%S0
- icmy\t%2,15,%S0"
- [(set_attr "op_type" "RR,RS,RSY")
- (set_attr "z10prop" "z10_fr_E1,z10_super_E1,z10_super_E1")])
-
-(define_insn "*tstdi_cconly_31"
- [(set (reg CC_REGNUM)
- (compare (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCSmode) && !TARGET_ZARCH"
- "srda\t%0,0"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-; ltr, ltgr
-(define_insn "*tst<mode>_cconly2"
- [(set (reg CC_REGNUM)
- (compare (match_operand:GPR 0 "register_operand" "d")
- (match_operand:GPR 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCSmode)"
- "lt<g>r\t%0,%0"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_fr_E1")])
-
-; tst(hi|qi) instruction pattern(s).
-
-(define_insn "*tst<mode>CCT"
- [(set (reg CC_REGNUM)
- (compare (match_operand:HQI 0 "nonimmediate_operand" "?Q,?S,d")
- (match_operand:HQI 1 "const0_operand" "")))
- (set (match_operand:HQI 2 "register_operand" "=d,d,0")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- icm\t%2,<icm_lo>,%S0
- icmy\t%2,<icm_lo>,%S0
- tml\t%0,<max_uint>"
- [(set_attr "op_type" "RS,RSY,RI")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,z10_super")])
-
-(define_insn "*tsthiCCT_cconly"
- [(set (reg CC_REGNUM)
- (compare (match_operand:HI 0 "nonimmediate_operand" "Q,S,d")
- (match_operand:HI 1 "const0_operand" "")))
- (clobber (match_scratch:HI 2 "=d,d,X"))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- icm\t%2,3,%S0
- icmy\t%2,3,%S0
- tml\t%0,65535"
- [(set_attr "op_type" "RS,RSY,RI")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,z10_super")])
-
-(define_insn "*tstqiCCT_cconly"
- [(set (reg CC_REGNUM)
- (compare (match_operand:QI 0 "nonimmediate_operand" "?Q,?S,d")
- (match_operand:QI 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- cli\t%S0,0
- cliy\t%S0,0
- tml\t%0,255"
- [(set_attr "op_type" "SI,SIY,RI")
- (set_attr "z10prop" "z10_super,z10_super,z10_super")])
-
-(define_insn "*tst<mode>"
- [(set (reg CC_REGNUM)
- (compare (match_operand:HQI 0 "s_operand" "Q,S")
- (match_operand:HQI 1 "const0_operand" "")))
- (set (match_operand:HQI 2 "register_operand" "=d,d")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- icm\t%2,<icm_lo>,%S0
- icmy\t%2,<icm_lo>,%S0"
- [(set_attr "op_type" "RS,RSY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-(define_insn "*tst<mode>_cconly"
- [(set (reg CC_REGNUM)
- (compare (match_operand:HQI 0 "s_operand" "Q,S")
- (match_operand:HQI 1 "const0_operand" "")))
- (clobber (match_scratch:HQI 2 "=d,d"))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- icm\t%2,<icm_lo>,%S0
- icmy\t%2,<icm_lo>,%S0"
- [(set_attr "op_type" "RS,RSY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-
-; Compare (equality) instructions
-
-(define_insn "*cmpdi_cct"
- [(set (reg CC_REGNUM)
- (compare (match_operand:DI 0 "nonimmediate_operand" "%d,d,d,d,Q")
- (match_operand:DI 1 "general_operand" "d,K,Os,RT,BQ")))]
- "s390_match_ccmode (insn, CCTmode) && TARGET_ZARCH"
- "@
- cgr\t%0,%1
- cghi\t%0,%h1
- cgfi\t%0,%1
- cg\t%0,%1
- #"
- [(set_attr "op_type" "RRE,RI,RIL,RXY,SS")
- (set_attr "z10prop" "z10_super_c,z10_super,z10_super,z10_super,*")])
-
-(define_insn "*cmpsi_cct"
- [(set (reg CC_REGNUM)
- (compare (match_operand:SI 0 "nonimmediate_operand" "%d,d,d,d,d,Q")
- (match_operand:SI 1 "general_operand" "d,K,Os,R,T,BQ")))]
- "s390_match_ccmode (insn, CCTmode)"
- "@
- cr\t%0,%1
- chi\t%0,%h1
- cfi\t%0,%1
- c\t%0,%1
- cy\t%0,%1
- #"
- [(set_attr "op_type" "RR,RI,RIL,RX,RXY,SS")
- (set_attr "z10prop" "z10_super_c,z10_super,z10_super,z10_super,z10_super,*")])
-
-; Compare (signed) instructions
-
-(define_insn "*cmpdi_ccs_sign"
- [(set (reg CC_REGNUM)
- (compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand"
- "d,RT,b"))
- (match_operand:DI 0 "register_operand" "d, d,d")))]
- "s390_match_ccmode(insn, CCSRmode) && TARGET_ZARCH"
- "@
- cgfr\t%0,%1
- cgf\t%0,%1
- cgfrl\t%0,%1"
- [(set_attr "op_type" "RRE,RXY,RIL")
- (set_attr "z10prop" "z10_c,*,*")
- (set_attr "type" "*,*,larl")])
-
-
-
-(define_insn "*cmpsi_ccs_sign"
- [(set (reg CC_REGNUM)
- (compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T,b"))
- (match_operand:SI 0 "register_operand" "d,d,d")))]
- "s390_match_ccmode(insn, CCSRmode)"
- "@
- ch\t%0,%1
- chy\t%0,%1
- chrl\t%0,%1"
- [(set_attr "op_type" "RX,RXY,RIL")
- (set_attr "cpu_facility" "*,*,z10")
- (set_attr "type" "*,*,larl")
- (set_attr "z196prop" "z196_cracked,z196_cracked,z196_cracked")])
-
-(define_insn "*cmphi_ccs_z10"
- [(set (reg CC_REGNUM)
- (compare (match_operand:HI 0 "s_operand" "Q")
- (match_operand:HI 1 "immediate_operand" "K")))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_Z10"
- "chhsi\t%0,%1"
- [(set_attr "op_type" "SIL")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*cmpdi_ccs_signhi_rl"
- [(set (reg CC_REGNUM)
- (compare (sign_extend:DI (match_operand:HI 1 "memory_operand" "RT,b"))
- (match_operand:GPR 0 "register_operand" "d,d")))]
- "s390_match_ccmode(insn, CCSRmode) && TARGET_Z10"
- "@
- cgh\t%0,%1
- cghrl\t%0,%1"
- [(set_attr "op_type" "RXY,RIL")
- (set_attr "type" "*,larl")])
-
-; cr, chi, cfi, c, cy, cgr, cghi, cgfi, cg, chsi, cghsi, crl, cgrl
-(define_insn "*cmp<mode>_ccs"
- [(set (reg CC_REGNUM)
- (compare (match_operand:GPR 0 "nonimmediate_operand"
- "d,d,Q, d,d,d,d")
- (match_operand:GPR 1 "general_operand"
- "d,K,K,Os,R,T,b")))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- c<g>r\t%0,%1
- c<g>hi\t%0,%h1
- c<g>hsi\t%0,%h1
- c<g>fi\t%0,%1
- c<g>\t%0,%1
- c<y>\t%0,%1
- c<g>rl\t%0,%1"
- [(set_attr "op_type" "RR<E>,RI,SIL,RIL,RX<Y>,RXY,RIL")
- (set_attr "cpu_facility" "*,*,z10,extimm,*,*,z10")
- (set_attr "type" "*,*,*,*,*,*,larl")
- (set_attr "z10prop" "z10_super_c,z10_super,z10_super,z10_super,z10_super,z10_super,z10_super")])
-
-
-; Compare (unsigned) instructions
-
-(define_insn "*cmpsi_ccu_zerohi_rlsi"
- [(set (reg CC_REGNUM)
- (compare (zero_extend:SI (mem:HI (match_operand:SI 1
- "larl_operand" "X")))
- (match_operand:SI 0 "register_operand" "d")))]
- "s390_match_ccmode(insn, CCURmode) && TARGET_Z10"
- "clhrl\t%0,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "larl")
- (set_attr "z10prop" "z10_super")])
-
-; clhrl, clghrl
-(define_insn "*cmp<GPR:mode>_ccu_zerohi_rldi"
- [(set (reg CC_REGNUM)
- (compare (zero_extend:GPR (mem:HI (match_operand:DI 1
- "larl_operand" "X")))
- (match_operand:GPR 0 "register_operand" "d")))]
- "s390_match_ccmode(insn, CCURmode) && TARGET_Z10"
- "cl<g>hrl\t%0,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "larl")
- (set_attr "z10prop" "z10_super")])
-
-(define_insn "*cmpdi_ccu_zero"
- [(set (reg CC_REGNUM)
- (compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand"
- "d,RT,b"))
- (match_operand:DI 0 "register_operand" "d, d,d")))]
- "s390_match_ccmode (insn, CCURmode) && TARGET_ZARCH"
- "@
- clgfr\t%0,%1
- clgf\t%0,%1
- clgfrl\t%0,%1"
- [(set_attr "op_type" "RRE,RXY,RIL")
- (set_attr "cpu_facility" "*,*,z10")
- (set_attr "type" "*,*,larl")
- (set_attr "z10prop" "z10_super_c,z10_super_E1,z10_super")])
-
-(define_insn "*cmpdi_ccu"
- [(set (reg CC_REGNUM)
- (compare (match_operand:DI 0 "nonimmediate_operand"
- "d, d,d,Q, d, Q,BQ")
- (match_operand:DI 1 "general_operand"
- "d,Op,b,D,RT,BQ,Q")))]
- "s390_match_ccmode (insn, CCUmode) && TARGET_ZARCH"
- "@
- clgr\t%0,%1
- clgfi\t%0,%1
- clgrl\t%0,%1
- clghsi\t%0,%x1
- clg\t%0,%1
- #
- #"
- [(set_attr "op_type" "RRE,RIL,RIL,SIL,RXY,SS,SS")
- (set_attr "cpu_facility" "*,extimm,z10,z10,*,*,*")
- (set_attr "type" "*,*,larl,*,*,*,*")
- (set_attr "z10prop" "z10_super_c,z10_super,z10_super,z10_super,z10_super,*,*")])
-
-(define_insn "*cmpsi_ccu"
- [(set (reg CC_REGNUM)
- (compare (match_operand:SI 0 "nonimmediate_operand" "d, d,d,Q,d,d, Q,BQ")
- (match_operand:SI 1 "general_operand" "d,Os,b,D,R,T,BQ, Q")))]
- "s390_match_ccmode (insn, CCUmode)"
- "@
- clr\t%0,%1
- clfi\t%0,%o1
- clrl\t%0,%1
- clfhsi\t%0,%x1
- cl\t%0,%1
- cly\t%0,%1
- #
- #"
- [(set_attr "op_type" "RR,RIL,RIL,SIL,RX,RXY,SS,SS")
- (set_attr "cpu_facility" "*,extimm,z10,z10,*,*,*,*")
- (set_attr "type" "*,*,larl,*,*,*,*,*")
- (set_attr "z10prop" "z10_super_c,z10_super,z10_super,z10_super,z10_super,z10_super,*,*")])
-
-(define_insn "*cmphi_ccu"
- [(set (reg CC_REGNUM)
- (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q,Q,BQ")
- (match_operand:HI 1 "general_operand" "Q,S,D,BQ,Q")))]
- "s390_match_ccmode (insn, CCUmode)
- && !register_operand (operands[1], HImode)"
- "@
- clm\t%0,3,%S1
- clmy\t%0,3,%S1
- clhhsi\t%0,%1
- #
- #"
- [(set_attr "op_type" "RS,RSY,SIL,SS,SS")
- (set_attr "cpu_facility" "*,*,z10,*,*")
- (set_attr "z10prop" "*,*,z10_super,*,*")])
-
-(define_insn "*cmpqi_ccu"
- [(set (reg CC_REGNUM)
- (compare (match_operand:QI 0 "nonimmediate_operand" "d,d,Q,S,Q,BQ")
- (match_operand:QI 1 "general_operand" "Q,S,n,n,BQ,Q")))]
- "s390_match_ccmode (insn, CCUmode)
- && !register_operand (operands[1], QImode)"
- "@
- clm\t%0,1,%S1
- clmy\t%0,1,%S1
- cli\t%S0,%b1
- cliy\t%S0,%b1
- #
- #"
- [(set_attr "op_type" "RS,RSY,SI,SIY,SS,SS")
- (set_attr "z10prop" "*,*,z10_super,z10_super,*,*")])
-
-
-; Block compare (CLC) instruction patterns.
-
-(define_insn "*clc"
- [(set (reg CC_REGNUM)
- (compare (match_operand:BLK 0 "memory_operand" "Q")
- (match_operand:BLK 1 "memory_operand" "Q")))
- (use (match_operand 2 "const_int_operand" "n"))]
- "s390_match_ccmode (insn, CCUmode)
- && INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
- "clc\t%O0(%2,%R0),%S1"
- [(set_attr "op_type" "SS")])
-
-(define_split
- [(set (reg CC_REGNUM)
- (compare (match_operand 0 "memory_operand" "")
- (match_operand 1 "memory_operand" "")))]
- "reload_completed
- && s390_match_ccmode (insn, CCUmode)
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
- [(parallel
- [(set (match_dup 0) (match_dup 1))
- (use (match_dup 2))])]
-{
- operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
- operands[0] = adjust_address (operands[0], BLKmode, 0);
- operands[1] = adjust_address (operands[1], BLKmode, 0);
-
- operands[1] = gen_rtx_COMPARE (GET_MODE (SET_DEST (PATTERN (curr_insn))),
- operands[0], operands[1]);
- operands[0] = SET_DEST (PATTERN (curr_insn));
-})
-
-
-; (TF|DF|SF|TD|DD|SD) instructions
-
-; ltxbr, ltdbr, ltebr, ltxtr, ltdtr
-(define_insn "*cmp<mode>_ccs_0"
- [(set (reg CC_REGNUM)
- (compare (match_operand:FP 0 "register_operand" "f")
- (match_operand:FP 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT"
- "lt<xde><bt>r\t%0,%0"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; cxtr, cxbr, cdtr, cdbr, cebr, cdb, ceb
-(define_insn "*cmp<mode>_ccs"
- [(set (reg CC_REGNUM)
- (compare (match_operand:FP 0 "register_operand" "f,f")
- (match_operand:FP 1 "general_operand" "f,<Rf>")))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT"
- "@
- c<xde><bt>r\t%0,%1
- c<xde>b\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimp<mode>")])
-
-
-; Compare and Branch instructions
-
-; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
-; The following instructions do a complementary access of their second
-; operand (z01 only): crj_c, cgrjc, cr, cgr
-(define_insn "*cmp_and_br_signed_<mode>"
- [(set (pc)
- (if_then_else (match_operator 0 "s390_signed_integer_comparison"
- [(match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "nonmemory_operand" "d,C")])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10 && !TARGET_AVOID_CMP_AND_BRANCH"
-{
- if (get_attr_length (insn) == 6)
- return which_alternative ?
- "c<g>ij%C0\t%1,%c2,%l3" : "c<g>rj%C0\t%1,%2,%l3";
- else
- return which_alternative ?
- "c<g>fi\t%1,%c2\;jg%C0\t%l3" : "c<g>r\t%1,%2\;jg%C0\t%l3";
-}
- [(set_attr "op_type" "RIE")
- (set_attr "type" "branch")
- (set_attr "z10prop" "z10_super_c,z10_super")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
- (const_int 6) (const_int 12)))]) ; 8 byte for cr/jg
- ; 10 byte for cgr/jg
-
-; clij, clgij, clrj, clgrj, clfi, clgfi, clr, clgr
-; The following instructions do a complementary access of their second
-; operand (z10 only): clrj, clgrj, clr, clgr
-(define_insn "*cmp_and_br_unsigned_<mode>"
- [(set (pc)
- (if_then_else (match_operator 0 "s390_unsigned_integer_comparison"
- [(match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "nonmemory_operand" "d,I")])
- (label_ref (match_operand 3 "" ""))
- (pc)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10 && !TARGET_AVOID_CMP_AND_BRANCH"
-{
- if (get_attr_length (insn) == 6)
- return which_alternative ?
- "cl<g>ij%C0\t%1,%b2,%l3" : "cl<g>rj%C0\t%1,%2,%l3";
- else
- return which_alternative ?
- "cl<g>fi\t%1,%b2\;jg%C0\t%l3" : "cl<g>r\t%1,%2\;jg%C0\t%l3";
-}
- [(set_attr "op_type" "RIE")
- (set_attr "type" "branch")
- (set_attr "z10prop" "z10_super_c,z10_super")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
- (const_int 6) (const_int 12)))]) ; 8 byte for clr/jg
- ; 10 byte for clgr/jg
-
-; And now the same two patterns as above but with a negated CC mask.
-
-; cij, cgij, crj, cgrj, cfi, cgfi, cr, cgr
-; The following instructions do a complementary access of their second
-; operand (z01 only): crj_c, cgrjc, cr, cgr
-(define_insn "*icmp_and_br_signed_<mode>"
- [(set (pc)
- (if_then_else (match_operator 0 "s390_signed_integer_comparison"
- [(match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "nonmemory_operand" "d,C")])
- (pc)
- (label_ref (match_operand 3 "" ""))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10 && !TARGET_AVOID_CMP_AND_BRANCH"
-{
- if (get_attr_length (insn) == 6)
- return which_alternative ?
- "c<g>ij%D0\t%1,%c2,%l3" : "c<g>rj%D0\t%1,%2,%l3";
- else
- return which_alternative ?
- "c<g>fi\t%1,%c2\;jg%D0\t%l3" : "c<g>r\t%1,%2\;jg%D0\t%l3";
-}
- [(set_attr "op_type" "RIE")
- (set_attr "type" "branch")
- (set_attr "z10prop" "z10_super_c,z10_super")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
- (const_int 6) (const_int 12)))]) ; 8 byte for cr/jg
- ; 10 byte for cgr/jg
-
-; clij, clgij, clrj, clgrj, clfi, clgfi, clr, clgr
-; The following instructions do a complementary access of their second
-; operand (z10 only): clrj, clgrj, clr, clgr
-(define_insn "*icmp_and_br_unsigned_<mode>"
- [(set (pc)
- (if_then_else (match_operator 0 "s390_unsigned_integer_comparison"
- [(match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "nonmemory_operand" "d,I")])
- (pc)
- (label_ref (match_operand 3 "" ""))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10 && !TARGET_AVOID_CMP_AND_BRANCH"
-{
- if (get_attr_length (insn) == 6)
- return which_alternative ?
- "cl<g>ij%D0\t%1,%b2,%l3" : "cl<g>rj%D0\t%1,%2,%l3";
- else
- return which_alternative ?
- "cl<g>fi\t%1,%b2\;jg%D0\t%l3" : "cl<g>r\t%1,%2\;jg%D0\t%l3";
-}
- [(set_attr "op_type" "RIE")
- (set_attr "type" "branch")
- (set_attr "z10prop" "z10_super_c,z10_super")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 3))) (const_int 60000))
- (const_int 6) (const_int 12)))]) ; 8 byte for clr/jg
- ; 10 byte for clgr/jg
-
-;;
-;;- Move instructions.
-;;
-
-;
-; movti instruction pattern(s).
-;
-
-(define_insn "movti"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=d,QS,d,o")
- (match_operand:TI 1 "general_operand" "QS,d,dPRT,d"))]
- "TARGET_ZARCH"
- "@
- lmg\t%0,%N0,%S1
- stmg\t%1,%N1,%S0
- #
- #"
- [(set_attr "op_type" "RSY,RSY,*,*")
- (set_attr "type" "lm,stm,*,*")])
-
-(define_split
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "general_operand" ""))]
- "TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], TImode, 0)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- 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);
-})
-
-(define_split
- [(set (match_operand:TI 0 "nonimmediate_operand" "")
- (match_operand:TI 1 "general_operand" ""))]
- "TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], TImode, 1)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- 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_ZARCH && reload_completed
- && !s_operand (operands[1], VOIDmode)"
- [(set (match_dup 0) (match_dup 1))]
-{
- rtx addr = operand_subword (operands[0], 1, 0, TImode);
- addr = gen_lowpart (Pmode, addr);
- s390_load_address (addr, XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], addr);
-})
-
-
-;
-; Patterns used for secondary reloads
-;
-
-; z10 provides move instructions accepting larl memory operands.
-; Unfortunately there is no such variant for QI, TI and FP mode moves.
-; These patterns are also used for unaligned SI and DI accesses.
-
-(define_expand "reload<INTALL:mode><P:mode>_tomem_z10"
- [(parallel [(match_operand:INTALL 0 "memory_operand" "")
- (match_operand:INTALL 1 "register_operand" "=d")
- (match_operand:P 2 "register_operand" "=&a")])]
- "TARGET_Z10"
-{
- s390_reload_symref_address (operands[1], operands[0], operands[2], 1);
- DONE;
-})
-
-(define_expand "reload<INTALL:mode><P:mode>_toreg_z10"
- [(parallel [(match_operand:INTALL 0 "register_operand" "=d")
- (match_operand:INTALL 1 "memory_operand" "")
- (match_operand:P 2 "register_operand" "=a")])]
- "TARGET_Z10"
-{
- s390_reload_symref_address (operands[0], operands[1], operands[2], 0);
- DONE;
-})
-
-(define_expand "reload<FPALL:mode><P:mode>_tomem_z10"
- [(parallel [(match_operand:FPALL 0 "memory_operand" "")
- (match_operand:FPALL 1 "register_operand" "=d")
- (match_operand:P 2 "register_operand" "=&a")])]
- "TARGET_Z10"
-{
- s390_reload_symref_address (operands[1], operands[0], operands[2], 1);
- DONE;
-})
-
-(define_expand "reload<FPALL:mode><P:mode>_toreg_z10"
- [(parallel [(match_operand:FPALL 0 "register_operand" "=d")
- (match_operand:FPALL 1 "memory_operand" "")
- (match_operand:P 2 "register_operand" "=a")])]
- "TARGET_Z10"
-{
- s390_reload_symref_address (operands[0], operands[1], operands[2], 0);
- DONE;
-})
-
-(define_expand "reload<P:mode>_larl_odd_addend_z10"
- [(parallel [(match_operand:P 0 "register_operand" "=d")
- (match_operand:P 1 "larl_operand" "")
- (match_operand:P 2 "register_operand" "=a")])]
- "TARGET_Z10"
-{
- s390_reload_larl_operand (operands[0], operands[1], operands[2]);
- DONE;
-})
-
-; Handles loading a PLUS (load address) expression
-
-(define_expand "reload<mode>_plus"
- [(parallel [(match_operand:P 0 "register_operand" "=a")
- (match_operand:P 1 "s390_plus_operand" "")
- (match_operand:P 2 "register_operand" "=&a")])]
- ""
-{
- s390_expand_plus_operand (operands[0], operands[1], operands[2]);
- DONE;
-})
-
-; Handles assessing a non-offsetable memory address
-
-(define_expand "reload<mode>_nonoffmem_in"
- [(parallel [(match_operand 0 "register_operand" "")
- (match_operand 1 "" "")
- (match_operand:P 2 "register_operand" "=&a")])]
- ""
-{
- gcc_assert (MEM_P (operands[1]));
- s390_load_address (operands[2], find_replacement (&XEXP (operands[1], 0)));
- operands[1] = replace_equiv_address (operands[1], operands[2]);
- emit_move_insn (operands[0], operands[1]);
- DONE;
-})
-
-(define_expand "reload<mode>_nonoffmem_out"
- [(parallel [(match_operand 0 "" "")
- (match_operand 1 "register_operand" "")
- (match_operand:P 2 "register_operand" "=&a")])]
- ""
-{
- gcc_assert (MEM_P (operands[0]));
- s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
- operands[0] = replace_equiv_address (operands[0], operands[2]);
- emit_move_insn (operands[0], operands[1]);
- DONE;
-})
-
-(define_expand "reload<mode>_PIC_addr"
- [(parallel [(match_operand 0 "register_operand" "=d")
- (match_operand 1 "larl_operand" "")
- (match_operand:P 2 "register_operand" "=a")])]
- ""
-{
- rtx new_rtx = legitimize_pic_address (operands[1], operands[2]);
- emit_move_insn (operands[0], new_rtx);
-})
-
-;
-; movdi instruction pattern(s).
-;
-
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- ""
-{
- /* Handle symbolic constants. */
- if (TARGET_64BIT
- && (SYMBOLIC_CONST (operands[1])
- || (GET_CODE (operands[1]) == PLUS
- && XEXP (operands[1], 0) == pic_offset_table_rtx
- && SYMBOLIC_CONST (XEXP (operands[1], 1)))))
- emit_symbolic_move (operands);
-})
-
-(define_insn "*movdi_larl"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (match_operand:DI 1 "larl_operand" "X"))]
- "TARGET_64BIT
- && !FP_REG_P (operands[0])"
- "larl\t%0,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "larl")
- (set_attr "z10prop" "z10_super_A1")])
-
-(define_insn "*movdi_64"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=d,d,d,d,d,d,d,d,f,d,d,d,d,d,
- RT,!*f,!*f,!*f,!R,!T,b,Q,d,t,Q,t")
- (match_operand:DI 1 "general_operand"
- "K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,d,f,L,b,d,RT,
- d,*f,R,T,*f,*f,d,K,t,d,t,Q"))]
- "TARGET_ZARCH"
- "@
- lghi\t%0,%h1
- llihh\t%0,%i1
- llihl\t%0,%i1
- llilh\t%0,%i1
- llill\t%0,%i1
- lgfi\t%0,%1
- llihf\t%0,%k1
- llilf\t%0,%k1
- ldgr\t%0,%1
- lgdr\t%0,%1
- lay\t%0,%a1
- lgrl\t%0,%1
- lgr\t%0,%1
- lg\t%0,%1
- stg\t%1,%0
- ldr\t%0,%1
- ld\t%0,%1
- ldy\t%0,%1
- std\t%1,%0
- stdy\t%1,%0
- stgrl\t%1,%0
- mvghi\t%0,%1
- #
- #
- stam\t%1,%N1,%S0
- lam\t%0,%N0,%S1"
- [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RRE,RRE,RXY,RIL,RRE,RXY,
- RXY,RR,RX,RXY,RX,RXY,RIL,SIL,*,*,RS,RS")
- (set_attr "type" "*,*,*,*,*,*,*,*,floaddf,floaddf,la,larl,lr,load,store,
- floaddf,floaddf,floaddf,fstoredf,fstoredf,larl,*,*,*,
- *,*")
- (set_attr "cpu_facility" "*,*,*,*,*,extimm,extimm,extimm,dfp,dfp,longdisp,
- z10,*,*,*,*,*,longdisp,*,longdisp,
- z10,z10,*,*,*,*")
- (set_attr "z10prop" "z10_fwd_A1,
- z10_fwd_E1,
- z10_fwd_E1,
- z10_fwd_E1,
- z10_fwd_E1,
- z10_fwd_A1,
- z10_fwd_E1,
- z10_fwd_E1,
- *,
- *,
- z10_fwd_A1,
- z10_fwd_A3,
- z10_fr_E1,
- z10_fwd_A3,
- z10_rec,
- *,
- *,
- *,
- *,
- *,
- z10_rec,
- z10_super,
- *,
- *,
- *,
- *")
-])
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "register_operand" ""))]
- "TARGET_ZARCH && ACCESS_REG_P (operands[1])"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
- (set (strict_low_part (match_dup 2)) (match_dup 4))]
- "operands[2] = gen_lowpart (SImode, operands[0]);
- s390_split_access_reg (operands[1], &operands[4], &operands[3]);")
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "register_operand" ""))]
- "TARGET_ZARCH && ACCESS_REG_P (operands[0])
- && dead_or_set_p (insn, operands[1])"
- [(set (match_dup 3) (match_dup 2))
- (set (match_dup 1) (lshiftrt:DI (match_dup 1) (const_int 32)))
- (set (match_dup 4) (match_dup 2))]
- "operands[2] = gen_lowpart (SImode, operands[1]);
- s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
-
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "register_operand" ""))]
- "TARGET_ZARCH && ACCESS_REG_P (operands[0])
- && !dead_or_set_p (insn, operands[1])"
- [(set (match_dup 3) (match_dup 2))
- (set (match_dup 1) (rotate:DI (match_dup 1) (const_int 32)))
- (set (match_dup 4) (match_dup 2))
- (set (match_dup 1) (rotate:DI (match_dup 1) (const_int 32)))]
- "operands[2] = gen_lowpart (SImode, operands[1]);
- s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
-
-(define_insn "*movdi_31"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=d,d,Q,S,d ,o,!*f,!*f,!*f,!R,!T,d")
- (match_operand:DI 1 "general_operand"
- " Q,S,d,d,dPRT,d, *f, R, T,*f,*f,b"))]
- "!TARGET_ZARCH"
- "@
- lm\t%0,%N0,%S1
- lmy\t%0,%N0,%S1
- stm\t%1,%N1,%S0
- stmy\t%1,%N1,%S0
- #
- #
- ldr\t%0,%1
- ld\t%0,%1
- ldy\t%0,%1
- std\t%1,%0
- stdy\t%1,%0
- #"
- [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,*")
- (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*")
- (set_attr "cpu_facility" "*,*,*,*,*,*,*,*,*,*,*,z10")])
-
-; For a load from a symbol ref we can use one of the target registers
-; together with larl to load the address.
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "memory_operand" ""))]
- "!TARGET_ZARCH && reload_completed && TARGET_Z10
- && larl_operand (XEXP (operands[1], 0), SImode)"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (match_dup 1))]
-{
- operands[2] = operand_subword (operands[0], 1, 0, DImode);
- operands[3] = XEXP (operands[1], 0);
- operands[1] = replace_equiv_address (operands[1], operands[2]);
-})
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- "!TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], DImode, 0)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- 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);
-})
-
-(define_split
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (match_operand:DI 1 "general_operand" ""))]
- "!TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], DImode, 1)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- 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_ZARCH && reload_completed
- && !FP_REG_P (operands[0])
- && !s_operand (operands[1], VOIDmode)"
- [(set (match_dup 0) (match_dup 1))]
-{
- rtx addr = operand_subword (operands[0], 1, 0, DImode);
- s390_load_address (addr, XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], addr);
-})
-
-(define_peephole2
- [(set (match_operand:DI 0 "register_operand" "")
- (mem:DI (match_operand 1 "address_operand" "")))]
- "TARGET_ZARCH
- && !FP_REG_P (operands[0])
- && GET_CODE (operands[1]) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (operands[1])
- && get_pool_mode (operands[1]) == DImode
- && legitimate_reload_constant_p (get_pool_constant (operands[1]))"
- [(set (match_dup 0) (match_dup 2))]
- "operands[2] = get_pool_constant (operands[1]);")
-
-(define_insn "*la_64"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))]
- "TARGET_64BIT"
- "@
- la\t%0,%a1
- lay\t%0,%a1"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "type" "la")
- (set_attr "z10prop" "z10_fwd_A1,z10_fwd_A1")])
-
-(define_peephole2
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operand:QI 1 "address_operand" ""))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_64BIT
- && preferred_la_operand_p (operands[1], const0_rtx)"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-(define_peephole2
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operand:DI 1 "register_operand" ""))
- (parallel
- [(set (match_dup 0)
- (plus:DI (match_dup 0)
- (match_operand:DI 2 "nonmemory_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_64BIT
- && !reg_overlap_mentioned_p (operands[0], operands[2])
- && preferred_la_operand_p (operands[1], operands[2])"
- [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
- "")
-
-;
-; movsi instruction pattern(s).
-;
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
-{
- /* Handle symbolic constants. */
- if (!TARGET_64BIT
- && (SYMBOLIC_CONST (operands[1])
- || (GET_CODE (operands[1]) == PLUS
- && XEXP (operands[1], 0) == pic_offset_table_rtx
- && SYMBOLIC_CONST (XEXP(operands[1], 1)))))
- emit_symbolic_move (operands);
-})
-
-(define_insn "*movsi_larl"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (match_operand:SI 1 "larl_operand" "X"))]
- "!TARGET_64BIT && TARGET_CPU_ZARCH
- && !FP_REG_P (operands[0])"
- "larl\t%0,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "larl")
- (set_attr "z10prop" "z10_fwd_A1")])
-
-(define_insn "*movsi_zarch"
- [(set (match_operand:SI 0 "nonimmediate_operand"
- "=d,d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,b,Q,t")
- (match_operand:SI 1 "general_operand"
- "K,N0HS0,N1HS0,Os,L,b,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,d,K,Q"))]
- "TARGET_ZARCH"
- "@
- lhi\t%0,%h1
- llilh\t%0,%i1
- llill\t%0,%i1
- iilf\t%0,%o1
- lay\t%0,%a1
- lrl\t%0,%1
- lr\t%0,%1
- l\t%0,%1
- ly\t%0,%1
- st\t%1,%0
- sty\t%1,%0
- ler\t%0,%1
- le\t%0,%1
- ley\t%0,%1
- ste\t%1,%0
- stey\t%1,%0
- ear\t%0,%1
- sar\t%0,%1
- stam\t%1,%1,%S0
- strl\t%1,%0
- mvhi\t%0,%1
- lam\t%0,%0,%S1"
- [(set_attr "op_type" "RI,RI,RI,RIL,RXY,RIL,RR,RX,RXY,RX,RXY,
- RR,RX,RXY,RX,RXY,RRE,RRE,RS,RIL,SIL,RS")
- (set_attr "type" "*,
- *,
- *,
- *,
- la,
- larl,
- lr,
- load,
- load,
- store,
- store,
- floadsf,
- floadsf,
- floadsf,
- fstoresf,
- fstoresf,
- *,
- *,
- *,
- larl,
- *,
- *")
- (set_attr "cpu_facility" "*,*,*,extimm,longdisp,z10,*,*,longdisp,*,longdisp,
- *,*,longdisp,*,longdisp,*,*,*,z10,z10,*")
- (set_attr "z10prop" "z10_fwd_A1,
- z10_fwd_E1,
- z10_fwd_E1,
- z10_fwd_A1,
- z10_fwd_A1,
- z10_fwd_A3,
- z10_fr_E1,
- z10_fwd_A3,
- z10_fwd_A3,
- z10_rec,
- z10_rec,
- *,
- *,
- *,
- *,
- *,
- z10_super_E1,
- z10_super,
- *,
- z10_rec,
- z10_super,
- *")])
-
-(define_insn "*movsi_esa"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t")
- (match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,t,d,t,Q"))]
- "!TARGET_ZARCH"
- "@
- lhi\t%0,%h1
- lr\t%0,%1
- l\t%0,%1
- st\t%1,%0
- ler\t%0,%1
- le\t%0,%1
- ste\t%1,%0
- ear\t%0,%1
- sar\t%0,%1
- stam\t%1,%1,%S0
- lam\t%0,%0,%S1"
- [(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,RRE,RRE,RS,RS")
- (set_attr "type" "*,lr,load,store,floadsf,floadsf,fstoresf,*,*,*,*")
- (set_attr "z10prop" "z10_fwd_A1,
- z10_fr_E1,
- z10_fwd_A3,
- z10_rec,
- *,
- *,
- *,
- z10_super_E1,
- z10_super,
- *,
- *")
-])
-
-(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
- (mem:SI (match_operand 1 "address_operand" "")))]
- "!FP_REG_P (operands[0])
- && GET_CODE (operands[1]) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (operands[1])
- && get_pool_mode (operands[1]) == SImode
- && legitimate_reload_constant_p (get_pool_constant (operands[1]))"
- [(set (match_dup 0) (match_dup 2))]
- "operands[2] = get_pool_constant (operands[1]);")
-
-(define_insn "*la_31"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))]
- "!TARGET_64BIT && legitimate_la_operand_p (operands[1])"
- "@
- la\t%0,%a1
- lay\t%0,%a1"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "type" "la")
- (set_attr "z10prop" "z10_fwd_A1,z10_fwd_A1")])
-
-(define_peephole2
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:QI 1 "address_operand" ""))
- (clobber (reg:CC CC_REGNUM))])]
- "!TARGET_64BIT
- && preferred_la_operand_p (operands[1], const0_rtx)"
- [(set (match_dup 0) (match_dup 1))]
- "")
-
-(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "register_operand" ""))
- (parallel
- [(set (match_dup 0)
- (plus:SI (match_dup 0)
- (match_operand:SI 2 "nonmemory_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- "!TARGET_64BIT
- && !reg_overlap_mentioned_p (operands[0], operands[2])
- && preferred_la_operand_p (operands[1], operands[2])"
- [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]
- "")
-
-(define_insn "*la_31_and"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (and:SI (match_operand:QI 1 "address_operand" "ZQZR,ZSZT")
- (const_int 2147483647)))]
- "!TARGET_64BIT"
- "@
- la\t%0,%a1
- lay\t%0,%a1"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "type" "la")
- (set_attr "z10prop" "z10_fwd_A1,z10_fwd_A1")])
-
-(define_insn_and_split "*la_31_and_cc"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (and:SI (match_operand:QI 1 "address_operand" "p")
- (const_int 2147483647)))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_64BIT"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (and:SI (match_dup 1) (const_int 2147483647)))]
- ""
- [(set_attr "op_type" "RX")
- (set_attr "type" "la")])
-
-(define_insn "force_la_31"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (match_operand:QI 1 "address_operand" "ZQZR,ZSZT"))
- (use (const_int 0))]
- "!TARGET_64BIT"
- "@
- la\t%0,%a1
- lay\t%0,%a1"
- [(set_attr "op_type" "RX")
- (set_attr "type" "la")
- (set_attr "z10prop" "z10_fwd_A1,z10_fwd_A1")])
-
-;
-; movhi instruction pattern(s).
-;
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
-{
- /* Make it explicit that loading a register from memory
- always sign-extends (at least) to SImode. */
- if (optimize && can_create_pseudo_p ()
- && register_operand (operands[0], VOIDmode)
- && GET_CODE (operands[1]) == MEM)
- {
- rtx tmp = gen_reg_rtx (SImode);
- rtx ext = gen_rtx_SIGN_EXTEND (SImode, operands[1]);
- emit_insn (gen_rtx_SET (VOIDmode, tmp, ext));
- operands[1] = gen_lowpart (HImode, tmp);
- }
-})
-
-(define_insn "*movhi"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,d,R,T,b,Q")
- (match_operand:HI 1 "general_operand" " d,n,R,T,b,d,d,d,K"))]
- ""
- "@
- lr\t%0,%1
- lhi\t%0,%h1
- lh\t%0,%1
- lhy\t%0,%1
- lhrl\t%0,%1
- sth\t%1,%0
- sthy\t%1,%0
- sthrl\t%1,%0
- mvhhi\t%0,%1"
- [(set_attr "op_type" "RR,RI,RX,RXY,RIL,RX,RXY,RIL,SIL")
- (set_attr "type" "lr,*,*,*,larl,store,store,store,*")
- (set_attr "cpu_facility" "*,*,*,*,z10,*,*,z10,z10")
- (set_attr "z10prop" "z10_fr_E1,
- z10_fwd_A1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_rec,
- z10_rec,
- z10_rec,
- z10_super")])
-
-(define_peephole2
- [(set (match_operand:HI 0 "register_operand" "")
- (mem:HI (match_operand 1 "address_operand" "")))]
- "GET_CODE (operands[1]) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (operands[1])
- && get_pool_mode (operands[1]) == HImode
- && GET_CODE (get_pool_constant (operands[1])) == CONST_INT"
- [(set (match_dup 0) (match_dup 2))]
- "operands[2] = get_pool_constant (operands[1]);")
-
-;
-; movqi instruction pattern(s).
-;
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
-{
- /* On z/Architecture, zero-extending from memory to register
- is just as fast as a QImode load. */
- if (TARGET_ZARCH && optimize && can_create_pseudo_p ()
- && register_operand (operands[0], VOIDmode)
- && GET_CODE (operands[1]) == MEM)
- {
- rtx tmp = gen_reg_rtx (DImode);
- rtx ext = gen_rtx_ZERO_EXTEND (DImode, operands[1]);
- emit_insn (gen_rtx_SET (VOIDmode, tmp, ext));
- operands[1] = gen_lowpart (QImode, tmp);
- }
-})
-
-(define_insn "*movqi"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,T,Q,S,?Q")
- (match_operand:QI 1 "general_operand" " d,n,R,T,d,d,n,n,?Q"))]
- ""
- "@
- lr\t%0,%1
- lhi\t%0,%b1
- ic\t%0,%1
- icy\t%0,%1
- stc\t%1,%0
- stcy\t%1,%0
- mvi\t%S0,%b1
- mviy\t%S0,%b1
- #"
- [(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SI,SIY,SS")
- (set_attr "type" "lr,*,*,*,store,store,store,store,*")
- (set_attr "z10prop" "z10_fr_E1,
- z10_fwd_A1,
- z10_super_E1,
- z10_super_E1,
- z10_rec,
- z10_rec,
- z10_super,
- z10_super,
- *")])
-
-(define_peephole2
- [(set (match_operand:QI 0 "nonimmediate_operand" "")
- (mem:QI (match_operand 1 "address_operand" "")))]
- "GET_CODE (operands[1]) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (operands[1])
- && get_pool_mode (operands[1]) == QImode
- && GET_CODE (get_pool_constant (operands[1])) == CONST_INT"
- [(set (match_dup 0) (match_dup 2))]
- "operands[2] = get_pool_constant (operands[1]);")
-
-;
-; movstrictqi instruction pattern(s).
-;
-
-(define_insn "*movstrictqi"
- [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d,d"))
- (match_operand:QI 1 "memory_operand" "R,T"))]
- ""
- "@
- ic\t%0,%1
- icy\t%0,%1"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-;
-; movstricthi instruction pattern(s).
-;
-
-(define_insn "*movstricthi"
- [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d,d"))
- (match_operand:HI 1 "memory_operand" "Q,S"))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- icm\t%0,3,%S1
- icmy\t%0,3,%S1"
- [(set_attr "op_type" "RS,RSY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-;
-; movstrictsi instruction pattern(s).
-;
-
-(define_insn "movstrictsi"
- [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d,d"))
- (match_operand:SI 1 "general_operand" "d,R,T,t"))]
- "TARGET_ZARCH"
- "@
- lr\t%0,%1
- l\t%0,%1
- ly\t%0,%1
- ear\t%0,%1"
- [(set_attr "op_type" "RR,RX,RXY,RRE")
- (set_attr "type" "lr,load,load,*")
- (set_attr "z10prop" "z10_fr_E1,z10_fwd_A3,z10_fwd_A3,z10_super_E1")])
-
-;
-; mov(tf|td) instruction pattern(s).
-;
-
-(define_expand "mov<mode>"
- [(set (match_operand:TD_TF 0 "nonimmediate_operand" "")
- (match_operand:TD_TF 1 "general_operand" ""))]
- ""
- "")
-
-(define_insn "*mov<mode>_64"
- [(set (match_operand:TD_TF 0 "nonimmediate_operand" "=f,f,f,o, d,QS, d,o")
- (match_operand:TD_TF 1 "general_operand" " G,f,o,f,QS, d,dRT,d"))]
- "TARGET_ZARCH"
- "@
- lzxr\t%0
- lxr\t%0,%1
- #
- #
- lmg\t%0,%N0,%S1
- stmg\t%1,%N1,%S0
- #
- #"
- [(set_attr "op_type" "RRE,RRE,*,*,RSY,RSY,*,*")
- (set_attr "type" "fsimptf,fsimptf,*,*,lm,stm,*,*")
- (set_attr "cpu_facility" "z196,*,*,*,*,*,*,*")])
-
-(define_insn "*mov<mode>_31"
- [(set (match_operand:TD_TF 0 "nonimmediate_operand" "=f,f,f,o")
- (match_operand:TD_TF 1 "general_operand" " G,f,o,f"))]
- "!TARGET_ZARCH"
- "@
- lzxr\t%0
- lxr\t%0,%1
- #
- #"
- [(set_attr "op_type" "RRE,RRE,*,*")
- (set_attr "type" "fsimptf,fsimptf,*,*")
- (set_attr "cpu_facility" "z196,*,*,*")])
-
-; TFmode in GPRs splitters
-
-(define_split
- [(set (match_operand:TD_TF 0 "nonimmediate_operand" "")
- (match_operand:TD_TF 1 "general_operand" ""))]
- "TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 0)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
- operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
- operands[4] = operand_subword (operands[1], 0, 0, <MODE>mode);
- operands[5] = operand_subword (operands[1], 1, 0, <MODE>mode);
-})
-
-(define_split
- [(set (match_operand:TD_TF 0 "nonimmediate_operand" "")
- (match_operand:TD_TF 1 "general_operand" ""))]
- "TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 1)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- operands[2] = operand_subword (operands[0], 1, 0, <MODE>mode);
- operands[3] = operand_subword (operands[0], 0, 0, <MODE>mode);
- operands[4] = operand_subword (operands[1], 1, 0, <MODE>mode);
- operands[5] = operand_subword (operands[1], 0, 0, <MODE>mode);
-})
-
-(define_split
- [(set (match_operand:TD_TF 0 "register_operand" "")
- (match_operand:TD_TF 1 "memory_operand" ""))]
- "TARGET_ZARCH && reload_completed
- && !FP_REG_P (operands[0])
- && !s_operand (operands[1], VOIDmode)"
- [(set (match_dup 0) (match_dup 1))]
-{
- rtx addr = operand_subword (operands[0], 1, 0, <MODE>mode);
- addr = gen_lowpart (Pmode, addr);
- s390_load_address (addr, XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], addr);
-})
-
-; TFmode in BFPs splitters
-
-(define_split
- [(set (match_operand:TD_TF 0 "register_operand" "")
- (match_operand:TD_TF 1 "memory_operand" ""))]
- "reload_completed && offsettable_memref_p (operands[1])
- && FP_REG_P (operands[0])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- operands[2] = simplify_gen_subreg (<HALF_TMODE>mode, operands[0],
- <MODE>mode, 0);
- operands[3] = simplify_gen_subreg (<HALF_TMODE>mode, operands[0],
- <MODE>mode, 8);
- operands[4] = adjust_address_nv (operands[1], <HALF_TMODE>mode, 0);
- operands[5] = adjust_address_nv (operands[1], <HALF_TMODE>mode, 8);
-})
-
-(define_split
- [(set (match_operand:TD_TF 0 "memory_operand" "")
- (match_operand:TD_TF 1 "register_operand" ""))]
- "reload_completed && offsettable_memref_p (operands[0])
- && FP_REG_P (operands[1])"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- operands[2] = adjust_address_nv (operands[0], <HALF_TMODE>mode, 0);
- operands[3] = adjust_address_nv (operands[0], <HALF_TMODE>mode, 8);
- operands[4] = simplify_gen_subreg (<HALF_TMODE>mode, operands[1],
- <MODE>mode, 0);
- operands[5] = simplify_gen_subreg (<HALF_TMODE>mode, operands[1],
- <MODE>mode, 8);
-})
-
-;
-; mov(df|dd) instruction pattern(s).
-;
-
-(define_expand "mov<mode>"
- [(set (match_operand:DD_DF 0 "nonimmediate_operand" "")
- (match_operand:DD_DF 1 "general_operand" ""))]
- ""
- "")
-
-(define_insn "*mov<mode>_64dfp"
- [(set (match_operand:DD_DF 0 "nonimmediate_operand"
- "=f,f,f,d,f,f,R,T,d,d, d,RT")
- (match_operand:DD_DF 1 "general_operand"
- " G,f,d,f,R,T,f,f,G,d,RT, d"))]
- "TARGET_DFP"
- "@
- lzdr\t%0
- ldr\t%0,%1
- ldgr\t%0,%1
- lgdr\t%0,%1
- ld\t%0,%1
- ldy\t%0,%1
- std\t%1,%0
- stdy\t%1,%0
- lghi\t%0,0
- lgr\t%0,%1
- lg\t%0,%1
- stg\t%1,%0"
- [(set_attr "op_type" "RRE,RR,RRE,RRE,RX,RXY,RX,RXY,RI,RRE,RXY,RXY")
- (set_attr "type" "fsimpdf,floaddf,floaddf,floaddf,floaddf,floaddf,
- fstoredf,fstoredf,*,lr,load,store")
- (set_attr "z10prop" "*,*,*,*,*,*,*,*,z10_fwd_A1,z10_fr_E1,z10_fwd_A3,z10_rec")
- (set_attr "cpu_facility" "z196,*,*,*,*,*,*,*,*,*,*,*")])
-
-(define_insn "*mov<mode>_64"
- [(set (match_operand:DD_DF 0 "nonimmediate_operand" "=f,f,f,f,R,T,d,d, d,RT")
- (match_operand:DD_DF 1 "general_operand" " G,f,R,T,f,f,G,d,RT, d"))]
- "TARGET_ZARCH"
- "@
- lzdr\t%0
- ldr\t%0,%1
- ld\t%0,%1
- ldy\t%0,%1
- std\t%1,%0
- stdy\t%1,%0
- lghi\t%0,0
- lgr\t%0,%1
- lg\t%0,%1
- stg\t%1,%0"
- [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RI,RRE,RXY,RXY")
- (set_attr "type" "fsimpdf,fload<mode>,fload<mode>,fload<mode>,
- fstore<mode>,fstore<mode>,*,lr,load,store")
- (set_attr "z10prop" "*,*,*,*,*,*,z10_fwd_A1,z10_fr_E1,z10_fwd_A3,z10_rec")
- (set_attr "cpu_facility" "z196,*,*,*,*,*,*,*,*,*")])
-
-(define_insn "*mov<mode>_31"
- [(set (match_operand:DD_DF 0 "nonimmediate_operand"
- "=f,f,f,f,R,T,d,d,Q,S, d,o")
- (match_operand:DD_DF 1 "general_operand"
- " G,f,R,T,f,f,Q,S,d,d,dPRT,d"))]
- "!TARGET_ZARCH"
- "@
- lzdr\t%0
- ldr\t%0,%1
- ld\t%0,%1
- ldy\t%0,%1
- std\t%1,%0
- stdy\t%1,%0
- lm\t%0,%N0,%S1
- lmy\t%0,%N0,%S1
- stm\t%1,%N1,%S0
- stmy\t%1,%N1,%S0
- #
- #"
- [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RS,RSY,RS,RSY,*,*")
- (set_attr "type" "fsimpdf,fload<mode>,fload<mode>,fload<mode>,
- fstore<mode>,fstore<mode>,lm,lm,stm,stm,*,*")
- (set_attr "cpu_facility" "z196,*,*,*,*,*,*,*,*,*,*,*")])
-
-(define_split
- [(set (match_operand:DD_DF 0 "nonimmediate_operand" "")
- (match_operand:DD_DF 1 "general_operand" ""))]
- "!TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 0)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- operands[2] = operand_subword (operands[0], 0, 0, <MODE>mode);
- operands[3] = operand_subword (operands[0], 1, 0, <MODE>mode);
- operands[4] = operand_subword (operands[1], 0, 0, <MODE>mode);
- operands[5] = operand_subword (operands[1], 1, 0, <MODE>mode);
-})
-
-(define_split
- [(set (match_operand:DD_DF 0 "nonimmediate_operand" "")
- (match_operand:DD_DF 1 "general_operand" ""))]
- "!TARGET_ZARCH && reload_completed
- && s390_split_ok_p (operands[0], operands[1], <MODE>mode, 1)"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
-{
- operands[2] = operand_subword (operands[0], 1, 0, <MODE>mode);
- operands[3] = operand_subword (operands[0], 0, 0, <MODE>mode);
- operands[4] = operand_subword (operands[1], 1, 0, <MODE>mode);
- operands[5] = operand_subword (operands[1], 0, 0, <MODE>mode);
-})
-
-(define_split
- [(set (match_operand:DD_DF 0 "register_operand" "")
- (match_operand:DD_DF 1 "memory_operand" ""))]
- "!TARGET_ZARCH && reload_completed
- && !FP_REG_P (operands[0])
- && !s_operand (operands[1], VOIDmode)"
- [(set (match_dup 0) (match_dup 1))]
-{
- rtx addr = operand_subword (operands[0], 1, 0, <MODE>mode);
- s390_load_address (addr, XEXP (operands[1], 0));
- operands[1] = replace_equiv_address (operands[1], addr);
-})
-
-;
-; mov(sf|sd) instruction pattern(s).
-;
-
-(define_insn "mov<mode>"
- [(set (match_operand:SD_SF 0 "nonimmediate_operand"
- "=f,f,f,f,R,T,d,d,d,d,R,T")
- (match_operand:SD_SF 1 "general_operand"
- " G,f,R,T,f,f,G,d,R,T,d,d"))]
- ""
- "@
- lzer\t%0
- ler\t%0,%1
- le\t%0,%1
- ley\t%0,%1
- ste\t%1,%0
- stey\t%1,%0
- lhi\t%0,0
- lr\t%0,%1
- l\t%0,%1
- ly\t%0,%1
- st\t%1,%0
- sty\t%1,%0"
- [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RI,RR,RX,RXY,RX,RXY")
- (set_attr "type" "fsimpsf,fload<mode>,fload<mode>,fload<mode>,
- fstore<mode>,fstore<mode>,*,lr,load,load,store,store")
- (set_attr "z10prop" "*,*,*,*,*,*,z10_fwd_A1,z10_fr_E1,z10_fwd_A3,z10_fwd_A3,z10_rec,z10_rec")
- (set_attr "cpu_facility" "z196,*,*,*,*,*,*,*,*,*,*,*")])
-
-;
-; movcc instruction pattern
-;
-
-(define_insn "movcc"
- [(set (match_operand:CC 0 "nonimmediate_operand" "=d,c,d,d,d,R,T")
- (match_operand:CC 1 "nonimmediate_operand" "d,d,c,R,T,d,d"))]
- ""
- "@
- lr\t%0,%1
- tmh\t%1,12288
- ipm\t%0
- st\t%0,%1
- sty\t%0,%1
- l\t%1,%0
- ly\t%1,%0"
- [(set_attr "op_type" "RR,RI,RRE,RX,RXY,RX,RXY")
- (set_attr "type" "lr,*,*,store,store,load,load")
- (set_attr "z10prop" "z10_fr_E1,z10_super,*,z10_rec,z10_rec,z10_fwd_A3,z10_fwd_A3")
- (set_attr "z196prop" "*,*,z196_ends,*,*,*,*")])
-
-;
-; Block move (MVC) patterns.
-;
-
-(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"))]
- "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
- "mvc\t%O0(%2,%R0),%S1"
- [(set_attr "op_type" "SS")])
-
-; This splitter converts a QI to QI mode copy into a BLK mode copy in
-; order to have it implemented with mvc.
-
-(define_split
- [(set (match_operand:QI 0 "memory_operand" "")
- (match_operand:QI 1 "memory_operand" ""))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (match_dup 1))
- (use (const_int 1))])]
-{
- operands[0] = adjust_address (operands[0], BLKmode, 0);
- operands[1] = adjust_address (operands[1], BLKmode, 0);
-})
-
-
-(define_peephole2
- [(parallel
- [(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand 2 "const_int_operand" ""))])
- (parallel
- [(set (match_operand:BLK 3 "memory_operand" "")
- (match_operand:BLK 4 "memory_operand" ""))
- (use (match_operand 5 "const_int_operand" ""))])]
- "s390_offset_p (operands[0], operands[3], operands[2])
- && s390_offset_p (operands[1], operands[4], operands[2])
- && !s390_overlap_p (operands[0], operands[1],
- INTVAL (operands[2]) + INTVAL (operands[5]))
- && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
- [(parallel
- [(set (match_dup 6) (match_dup 7))
- (use (match_dup 8))])]
- "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
- operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
- operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
-
-
-;
-; load_multiple pattern(s).
-;
-; ??? Due to reload problems with replacing registers inside match_parallel
-; we currently support load_multiple/store_multiple only after reload.
-;
-
-(define_expand "load_multiple"
- [(match_par_dup 3 [(set (match_operand 0 "" "")
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))])]
- "reload_completed"
-{
- enum machine_mode mode;
- int regno;
- int count;
- rtx from;
- 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]) > 16
- || GET_CODE (operands[1]) != MEM
- || GET_CODE (operands[0]) != REG
- || REGNO (operands[0]) >= 16)
- FAIL;
-
- count = INTVAL (operands[2]);
- regno = REGNO (operands[0]);
- mode = GET_MODE (operands[0]);
- if (mode != SImode && (!TARGET_ZARCH || mode != DImode))
- FAIL;
-
- operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- if (!can_create_pseudo_p ())
- {
- 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;
- }
- 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 (mode, regno + i),
- change_address (operands[1], mode,
- plus_constant (from, off + i * GET_MODE_SIZE (mode))));
-})
-
-(define_insn "*load_multiple_di"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:DI 1 "register_operand" "=r")
- (match_operand:DI 2 "s_operand" "QS"))])]
- "reload_completed && TARGET_ZARCH"
-{
- int words = XVECLEN (operands[0], 0);
- operands[0] = gen_rtx_REG (DImode, REGNO (operands[1]) + words - 1);
- return "lmg\t%1,%0,%S2";
-}
- [(set_attr "op_type" "RSY")
- (set_attr "type" "lm")])
-
-(define_insn "*load_multiple_si"
- [(match_parallel 0 "load_multiple_operation"
- [(set (match_operand:SI 1 "register_operand" "=r,r")
- (match_operand:SI 2 "s_operand" "Q,S"))])]
- "reload_completed"
-{
- int words = XVECLEN (operands[0], 0);
- operands[0] = gen_rtx_REG (SImode, REGNO (operands[1]) + words - 1);
- return which_alternative == 0 ? "lm\t%1,%0,%S2" : "lmy\t%1,%0,%S2";
-}
- [(set_attr "op_type" "RS,RSY")
- (set_attr "type" "lm")])
-
-;
-; store multiple pattern(s).
-;
-
-(define_expand "store_multiple"
- [(match_par_dup 3 [(set (match_operand 0 "" "")
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))])]
- "reload_completed"
-{
- enum machine_mode mode;
- int regno;
- int count;
- rtx to;
- 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]) > 16
- || GET_CODE (operands[0]) != MEM
- || GET_CODE (operands[1]) != REG
- || REGNO (operands[1]) >= 16)
- FAIL;
-
- count = INTVAL (operands[2]);
- regno = REGNO (operands[1]);
- mode = GET_MODE (operands[1]);
- if (mode != SImode && (!TARGET_ZARCH || mode != DImode))
- FAIL;
-
- operands[3] = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
-
- if (!can_create_pseudo_p ())
- {
- 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;
- }
- 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], mode,
- plus_constant (to, off + i * GET_MODE_SIZE (mode))),
- gen_rtx_REG (mode, regno + i));
-})
-
-(define_insn "*store_multiple_di"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:DI 1 "s_operand" "=QS")
- (match_operand:DI 2 "register_operand" "r"))])]
- "reload_completed && TARGET_ZARCH"
-{
- int words = XVECLEN (operands[0], 0);
- operands[0] = gen_rtx_REG (DImode, REGNO (operands[2]) + words - 1);
- return "stmg\t%2,%0,%S1";
-}
- [(set_attr "op_type" "RSY")
- (set_attr "type" "stm")])
-
-
-(define_insn "*store_multiple_si"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "s_operand" "=Q,S")
- (match_operand:SI 2 "register_operand" "r,r"))])]
- "reload_completed"
-{
- int words = XVECLEN (operands[0], 0);
- operands[0] = gen_rtx_REG (SImode, REGNO (operands[2]) + words - 1);
- return which_alternative == 0 ? "stm\t%2,%0,%S1" : "stmy\t%2,%0,%S1";
-}
- [(set_attr "op_type" "RS,RSY")
- (set_attr "type" "stm")])
-
-;;
-;; String instructions.
-;;
-
-(define_insn "*execute_rl"
- [(match_parallel 0 ""
- [(unspec [(match_operand 1 "register_operand" "a")
- (match_operand 2 "" "")
- (match_operand:SI 3 "larl_operand" "X")] UNSPEC_EXECUTE)])]
- "TARGET_Z10 && GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
- && GET_MODE_SIZE (GET_MODE (operands[1])) <= UNITS_PER_WORD"
- "exrl\t%1,%3"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "cs")])
-
-(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")
- (set_attr "type" "cs")])
-
-
-;
-; strlenM instruction pattern(s).
-;
-
-(define_expand "strlen<mode>"
- [(set (reg:SI 0) (match_operand:SI 2 "immediate_operand" ""))
- (parallel
- [(set (match_dup 4)
- (unspec:P [(const_int 0)
- (match_operand:BLK 1 "memory_operand" "")
- (reg:SI 0)
- (match_operand 3 "immediate_operand" "")] UNSPEC_SRST))
- (clobber (scratch:P))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_operand:P 0 "register_operand" "")
- (minus:P (match_dup 4) (match_dup 5)))
- (clobber (reg:CC CC_REGNUM))])]
- ""
-{
- operands[4] = gen_reg_rtx (Pmode);
- operands[5] = gen_reg_rtx (Pmode);
- emit_move_insn (operands[5], force_operand (XEXP (operands[1], 0), NULL_RTX));
- operands[1] = replace_equiv_address (operands[1], operands[5]);
-})
-
-(define_insn "*strlen<mode>"
- [(set (match_operand:P 0 "register_operand" "=a")
- (unspec:P [(match_operand:P 2 "general_operand" "0")
- (mem:BLK (match_operand:P 3 "register_operand" "1"))
- (reg:SI 0)
- (match_operand 4 "immediate_operand" "")] UNSPEC_SRST))
- (clobber (match_scratch:P 1 "=a"))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "srst\t%0,%1\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-;
-; cmpstrM instruction pattern(s).
-;
-
-(define_expand "cmpstrsi"
- [(set (reg:SI 0) (const_int 0))
- (parallel
- [(clobber (match_operand 3 "" ""))
- (clobber (match_dup 4))
- (set (reg:CCU CC_REGNUM)
- (compare:CCU (match_operand:BLK 1 "memory_operand" "")
- (match_operand:BLK 2 "memory_operand" "")))
- (use (reg:SI 0))])
- (parallel
- [(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CCU_TO_INT))
- (clobber (reg:CC CC_REGNUM))])]
- ""
-{
- /* As the result of CMPINT is inverted compared to what we need,
- we have to swap the operands. */
- rtx op1 = operands[2];
- rtx op2 = operands[1];
- rtx addr1 = gen_reg_rtx (Pmode);
- rtx addr2 = gen_reg_rtx (Pmode);
-
- emit_move_insn (addr1, force_operand (XEXP (op1, 0), NULL_RTX));
- emit_move_insn (addr2, force_operand (XEXP (op2, 0), NULL_RTX));
- operands[1] = replace_equiv_address_nv (op1, addr1);
- operands[2] = replace_equiv_address_nv (op2, addr2);
- operands[3] = addr1;
- operands[4] = addr2;
-})
-
-(define_insn "*cmpstr<mode>"
- [(clobber (match_operand:P 0 "register_operand" "=d"))
- (clobber (match_operand:P 1 "register_operand" "=d"))
- (set (reg:CCU CC_REGNUM)
- (compare:CCU (mem:BLK (match_operand:P 2 "register_operand" "0"))
- (mem:BLK (match_operand:P 3 "register_operand" "1"))))
- (use (reg:SI 0))]
- ""
- "clst\t%0,%1\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-;
-; movstr instruction pattern.
-;
-
-(define_expand "movstr"
- [(set (reg:SI 0) (const_int 0))
- (parallel
- [(clobber (match_dup 3))
- (set (match_operand:BLK 1 "memory_operand" "")
- (match_operand:BLK 2 "memory_operand" ""))
- (set (match_operand 0 "register_operand" "")
- (unspec [(match_dup 1)
- (match_dup 2)
- (reg:SI 0)] UNSPEC_MVST))
- (clobber (reg:CC CC_REGNUM))])]
- ""
-{
- rtx addr1 = gen_reg_rtx (Pmode);
- rtx addr2 = gen_reg_rtx (Pmode);
-
- emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
- emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
- operands[1] = replace_equiv_address_nv (operands[1], addr1);
- operands[2] = replace_equiv_address_nv (operands[2], addr2);
- operands[3] = addr2;
-})
-
-(define_insn "*movstr"
- [(clobber (match_operand:P 2 "register_operand" "=d"))
- (set (mem:BLK (match_operand:P 1 "register_operand" "0"))
- (mem:BLK (match_operand:P 3 "register_operand" "2")))
- (set (match_operand:P 0 "register_operand" "=d")
- (unspec [(mem:BLK (match_dup 1))
- (mem:BLK (match_dup 3))
- (reg:SI 0)] UNSPEC_MVST))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "mvst\t%1,%2\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-
-;
-; movmemM instruction pattern(s).
-;
-
-(define_expand "movmem<mode>"
- [(set (match_operand:BLK 0 "memory_operand" "") ; destination
- (match_operand:BLK 1 "memory_operand" "")) ; source
- (use (match_operand:GPR 2 "general_operand" "")) ; count
- (match_operand 3 "" "")]
- ""
- "s390_expand_movmem (operands[0], operands[1], operands[2]); DONE;")
-
-; Move a block that is up to 256 bytes in length.
-; The block length is taken as (operands[2] % 256) + 1.
-
-(define_expand "movmem_short"
- [(parallel
- [(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,Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q,Q,Q"))
- (use (match_operand 2 "nonmemory_operand" "n,a,a,a"))
- (use (match_operand 3 "immediate_operand" "X,R,X,X"))
- (clobber (match_scratch 4 "=X,X,X,&a"))]
- "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
- && GET_MODE (operands[4]) == Pmode"
- "#"
- [(set_attr "type" "cs")
- (set_attr "cpu_facility" "*,*,z10,*")])
-
-(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);")
-
-(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 (scratch))]
- "TARGET_Z10 && reload_completed"
- [(parallel
- [(unspec [(match_dup 2) (const_int 0)
- (label_ref (match_dup 3))] UNSPEC_EXECUTE)
- (set (match_dup 0) (match_dup 1))
- (use (const_int 1))])]
- "operands[3] = gen_label_rtx ();")
-
-(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 ();")
-
-; Move a block of arbitrary length.
-
-(define_expand "movmem_long"
- [(parallel
- [(clobber (match_dup 2))
- (clobber (match_dup 3))
- (set (match_operand:BLK 0 "memory_operand" "")
- (match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand 2 "general_operand" ""))
- (use (match_dup 3))
- (clobber (reg:CC CC_REGNUM))])]
- ""
-{
- enum machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
- enum machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
- rtx reg0 = gen_reg_rtx (dreg_mode);
- rtx reg1 = gen_reg_rtx (dreg_mode);
- rtx addr0 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg0));
- rtx addr1 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg1));
- rtx len0 = gen_lowpart (Pmode, reg0);
- rtx len1 = gen_lowpart (Pmode, reg1);
-
- emit_clobber (reg0);
- emit_move_insn (addr0, force_operand (XEXP (operands[0], 0), NULL_RTX));
- emit_move_insn (len0, operands[2]);
-
- emit_clobber (reg1);
- emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
- emit_move_insn (len1, operands[2]);
-
- operands[0] = replace_equiv_address_nv (operands[0], addr0);
- operands[1] = replace_equiv_address_nv (operands[1], addr1);
- operands[2] = reg0;
- operands[3] = reg1;
-})
-
-(define_insn "*movmem_long"
- [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
- (clobber (match_operand:<DBL> 1 "register_operand" "=d"))
- (set (mem:BLK (subreg:P (match_operand:<DBL> 2 "register_operand" "0") 0))
- (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "1") 0)))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_64BIT || !TARGET_ZARCH"
- "mvcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-(define_insn "*movmem_long_31z"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (clobber (match_operand:TI 1 "register_operand" "=d"))
- (set (mem:BLK (subreg:SI (match_operand:TI 2 "register_operand" "0") 4))
- (mem:BLK (subreg:SI (match_operand:TI 3 "register_operand" "1") 4)))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_64BIT && TARGET_ZARCH"
- "mvcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-
-;
-; Test data class.
-;
-
-(define_expand "signbit<mode>2"
- [(set (reg:CCZ CC_REGNUM)
- (unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
- (match_dup 2)]
- UNSPEC_TDC_INSN))
- (set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))]
- "TARGET_HARD_FLOAT"
-{
- operands[2] = GEN_INT (S390_TDC_SIGNBIT_SET);
-})
-
-(define_expand "isinf<mode>2"
- [(set (reg:CCZ CC_REGNUM)
- (unspec:CCZ [(match_operand:FP_ALL 1 "register_operand" "f")
- (match_dup 2)]
- UNSPEC_TDC_INSN))
- (set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(reg:CCZ CC_REGNUM)] UNSPEC_CCZ_TO_INT))]
- "TARGET_HARD_FLOAT"
-{
- operands[2] = GEN_INT (S390_TDC_INFINITY);
-})
-
-; This insn is used to generate all variants of the Test Data Class
-; instruction, namely tcxb, tcdb, and tceb. The insn's first operand
-; is the register to be tested and the second one is the bit mask
-; specifying the required test(s).
-;
-; tcxb, tcdb, tceb, tdcxt, tdcdt, tdcet
-(define_insn "*TDC_insn_<mode>"
- [(set (reg:CCZ CC_REGNUM)
- (unspec:CCZ [(match_operand:FP_ALL 0 "register_operand" "f")
- (match_operand:SI 1 "const_int_operand")] UNSPEC_TDC_INSN))]
- "TARGET_HARD_FLOAT"
- "t<_d>c<xde><bt>\t%0,%1"
- [(set_attr "op_type" "RXE")
- (set_attr "type" "fsimp<mode>")])
-
-(define_insn_and_split "*ccz_to_int"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:CCZ 1 "register_operand" "0")]
- UNSPEC_CCZ_TO_INT))]
- ""
- "#"
- "reload_completed"
- [(set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 28)))])
-
-
-;
-; setmemM instruction pattern(s).
-;
-
-(define_expand "setmem<mode>"
- [(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand:QI 2 "general_operand" ""))
- (use (match_operand:GPR 1 "general_operand" ""))
- (match_operand 3 "" "")]
- ""
- "s390_expand_setmem (operands[0], operands[1], operands[2]); DONE;")
-
-; Clear a block that is up to 256 bytes in length.
-; The block length is taken as (operands[1] % 256) + 1.
-
-(define_expand "clrmem_short"
- [(parallel
- [(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 CC_REGNUM))])]
- ""
- "operands[2] = gen_rtx_SCRATCH (Pmode);")
-
-(define_insn "*clrmem_short"
- [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q,Q")
- (const_int 0))
- (use (match_operand 1 "nonmemory_operand" "n,a,a,a"))
- (use (match_operand 2 "immediate_operand" "X,R,X,X"))
- (clobber (match_scratch 3 "=X,X,X,&a"))
- (clobber (reg:CC CC_REGNUM))]
- "(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
- && GET_MODE (operands[3]) == Pmode"
- "#"
- [(set_attr "type" "cs")
- (set_attr "cpu_facility" "*,*,z10,*")])
-
-(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 CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (const_int 0))
- (use (match_dup 1))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[1] = GEN_INT ((INTVAL (operands[1]) & 0xff) + 1);")
-
-(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 CC_REGNUM))]
- "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 CC_REGNUM))])]
- "")
-
-(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 (scratch))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10 && reload_completed"
- [(parallel
- [(unspec [(match_dup 1) (const_int 0)
- (label_ref (match_dup 3))] UNSPEC_EXECUTE)
- (set (match_dup 0) (const_int 0))
- (use (const_int 1))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[3] = gen_label_rtx ();")
-
-(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 CC_REGNUM))]
- "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 CC_REGNUM))])]
- "operands[3] = gen_label_rtx ();")
-
-; Initialize a block of arbitrary length with (operands[2] % 256).
-
-(define_expand "setmem_long"
- [(parallel
- [(clobber (match_dup 1))
- (set (match_operand:BLK 0 "memory_operand" "")
- (match_operand 2 "shift_count_or_setmem_operand" ""))
- (use (match_operand 1 "general_operand" ""))
- (use (match_dup 3))
- (clobber (reg:CC CC_REGNUM))])]
- ""
-{
- enum machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
- enum machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
- rtx reg0 = gen_reg_rtx (dreg_mode);
- rtx reg1 = gen_reg_rtx (dreg_mode);
- rtx addr0 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg0));
- rtx len0 = gen_lowpart (Pmode, reg0);
-
- emit_clobber (reg0);
- emit_move_insn (addr0, force_operand (XEXP (operands[0], 0), NULL_RTX));
- emit_move_insn (len0, operands[1]);
-
- emit_move_insn (reg1, const0_rtx);
-
- operands[0] = replace_equiv_address_nv (operands[0], addr0);
- operands[1] = reg0;
- operands[3] = reg1;
-})
-
-(define_insn "*setmem_long"
- [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
- (match_operand 2 "shift_count_or_setmem_operand" "Y"))
- (use (match_dup 3))
- (use (match_operand:<DBL> 1 "register_operand" "d"))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_64BIT || !TARGET_ZARCH"
- "mvcle\t%0,%1,%Y2\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-(define_insn "*setmem_long_and"
- [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
- (and (match_operand 2 "shift_count_or_setmem_operand" "Y")
- (match_operand 4 "const_int_operand" "n")))
- (use (match_dup 3))
- (use (match_operand:<DBL> 1 "register_operand" "d"))
- (clobber (reg:CC CC_REGNUM))]
- "(TARGET_64BIT || !TARGET_ZARCH) &&
- (INTVAL (operands[4]) & 255) == 255"
- "mvcle\t%0,%1,%Y2\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-(define_insn "*setmem_long_31z"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:SI (match_operand:TI 3 "register_operand" "0") 4))
- (match_operand 2 "shift_count_or_setmem_operand" "Y"))
- (use (match_dup 3))
- (use (match_operand:TI 1 "register_operand" "d"))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_64BIT && TARGET_ZARCH"
- "mvcle\t%0,%1,%Y2\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-;
-; cmpmemM instruction pattern(s).
-;
-
-(define_expand "cmpmemsi"
- [(set (match_operand:SI 0 "register_operand" "")
- (compare:SI (match_operand:BLK 1 "memory_operand" "")
- (match_operand:BLK 2 "memory_operand" "") ) )
- (use (match_operand:SI 3 "general_operand" ""))
- (use (match_operand:SI 4 "" ""))]
- ""
- "s390_expand_cmpmem (operands[0], operands[1],
- operands[2], operands[3]); DONE;")
-
-; Compare a block that is up to 256 bytes in length.
-; The block length is taken as (operands[2] % 256) + 1.
-
-(define_expand "cmpmem_short"
- [(parallel
- [(set (reg:CCU CC_REGNUM)
- (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 CC_REGNUM)
- (compare:CCU (match_operand:BLK 0 "memory_operand" "Q,Q,Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q,Q,Q")))
- (use (match_operand 2 "nonmemory_operand" "n,a,a,a"))
- (use (match_operand 3 "immediate_operand" "X,R,X,X"))
- (clobber (match_scratch 4 "=X,X,X,&a"))]
- "(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
- && GET_MODE (operands[4]) == Pmode"
- "#"
- [(set_attr "type" "cs")
- (set_attr "cpu_facility" "*,*,z10,*")])
-
-(define_split
- [(set (reg:CCU CC_REGNUM)
- (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 CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
- (use (match_dup 2))])]
- "operands[2] = GEN_INT ((INTVAL (operands[2]) & 0xff) + 1);")
-
-(define_split
- [(set (reg:CCU CC_REGNUM)
- (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 CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
- (use (const_int 1))])]
- "")
-
-(define_split
- [(set (reg:CCU CC_REGNUM)
- (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 (scratch))]
- "TARGET_Z10 && reload_completed"
- [(parallel
- [(unspec [(match_dup 2) (const_int 0)
- (label_ref (match_dup 4))] UNSPEC_EXECUTE)
- (set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
- (use (const_int 1))])]
- "operands[4] = gen_label_rtx ();")
-
-(define_split
- [(set (reg:CCU CC_REGNUM)
- (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 CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
- (use (const_int 1))])]
- "operands[4] = gen_label_rtx ();")
-
-; Compare a block of arbitrary length.
-
-(define_expand "cmpmem_long"
- [(parallel
- [(clobber (match_dup 2))
- (clobber (match_dup 3))
- (set (reg:CCU CC_REGNUM)
- (compare:CCU (match_operand:BLK 0 "memory_operand" "")
- (match_operand:BLK 1 "memory_operand" "")))
- (use (match_operand 2 "general_operand" ""))
- (use (match_dup 3))])]
- ""
-{
- enum machine_mode sreg_mode = TARGET_ZARCH ? DImode : SImode;
- enum machine_mode dreg_mode = TARGET_ZARCH ? TImode : DImode;
- rtx reg0 = gen_reg_rtx (dreg_mode);
- rtx reg1 = gen_reg_rtx (dreg_mode);
- rtx addr0 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg0));
- rtx addr1 = gen_lowpart (Pmode, gen_highpart (sreg_mode, reg1));
- rtx len0 = gen_lowpart (Pmode, reg0);
- rtx len1 = gen_lowpart (Pmode, reg1);
-
- emit_clobber (reg0);
- emit_move_insn (addr0, force_operand (XEXP (operands[0], 0), NULL_RTX));
- emit_move_insn (len0, operands[2]);
-
- emit_clobber (reg1);
- emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
- emit_move_insn (len1, operands[2]);
-
- operands[0] = replace_equiv_address_nv (operands[0], addr0);
- operands[1] = replace_equiv_address_nv (operands[1], addr1);
- operands[2] = reg0;
- operands[3] = reg1;
-})
-
-(define_insn "*cmpmem_long"
- [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
- (clobber (match_operand:<DBL> 1 "register_operand" "=d"))
- (set (reg:CCU CC_REGNUM)
- (compare:CCU (mem:BLK (subreg:P (match_operand:<DBL> 2 "register_operand" "0") 0))
- (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "1") 0))))
- (use (match_dup 2))
- (use (match_dup 3))]
- "TARGET_64BIT || !TARGET_ZARCH"
- "clcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "length" "8")
- (set_attr "type" "vs")])
-
-(define_insn "*cmpmem_long_31z"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (clobber (match_operand:TI 1 "register_operand" "=d"))
- (set (reg:CCU CC_REGNUM)
- (compare:CCU (mem:BLK (subreg:SI (match_operand:TI 2 "register_operand" "0") 4))
- (mem:BLK (subreg:SI (match_operand:TI 3 "register_operand" "1") 4))))
- (use (match_dup 2))
- (use (match_dup 3))]
- "!TARGET_64BIT && TARGET_ZARCH"
- "clcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
-
-; Convert CCUmode condition code to integer.
-; Result is zero if EQ, positive if LTU, negative if GTU.
-
-(define_insn_and_split "cmpint"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "#"
- "reload_completed"
- [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 2)))
- (parallel
- [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 30)))
- (clobber (reg:CC CC_REGNUM))])])
-
-(define_insn_and_split "*cmpint_cc"
- [(set (reg CC_REGNUM)
- (compare (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT)
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d")
- (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT))]
- "s390_match_ccmode (insn, CCSmode)"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 2)))
- (parallel
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 30)))])]
-{
- rtx result = gen_rtx_ASHIFTRT (SImode, operands[0], GEN_INT (30));
- operands[2] = SET_DEST (XVECEXP (PATTERN (curr_insn), 0, 0));
- operands[3] = gen_rtx_COMPARE (GET_MODE (operands[2]), result, const0_rtx);
-})
-
-(define_insn_and_split "*cmpint_sign"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 34)))
- (parallel
- [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 62)))
- (clobber (reg:CC CC_REGNUM))])])
-
-(define_insn_and_split "*cmpint_sign_cc"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:DI (ashift:DI (subreg:DI
- (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
- UNSPEC_CCU_TO_INT) 0)
- (const_int 32)) (const_int 32))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CCU_TO_INT)))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 34)))
- (parallel
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 62)))])]
-{
- rtx result = gen_rtx_ASHIFTRT (DImode, operands[0], GEN_INT (62));
- operands[2] = SET_DEST (XVECEXP (PATTERN (curr_insn), 0, 0));
- operands[3] = gen_rtx_COMPARE (GET_MODE (operands[2]), result, const0_rtx);
-})
-
-
-;;
-;;- Conversion instructions.
-;;
-
-(define_insn "*sethighpartsi"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (unspec:SI [(match_operand:BLK 1 "s_operand" "Q,S")
- (match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- icm\t%0,%2,%S1
- icmy\t%0,%2,%S1"
- [(set_attr "op_type" "RS,RSY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-(define_insn "*sethighpartdi_64"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (unspec:DI [(match_operand:BLK 1 "s_operand" "QS")
- (match_operand 2 "const_int_operand" "n")] UNSPEC_ICM))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "icmh\t%0,%2,%S1"
- [(set_attr "op_type" "RSY")
- (set_attr "z10prop" "z10_super")])
-
-(define_insn "*sethighpartdi_31"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (unspec:DI [(match_operand:BLK 1 "s_operand" "Q,S")
- (match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH"
- "@
- icm\t%0,%2,%S1
- icmy\t%0,%2,%S1"
- [(set_attr "op_type" "RS,RSY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-
-(define_insn_and_split "*extzv<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (zero_extract:GPR (match_operand:QI 1 "s_operand" "QS")
- (match_operand 2 "const_int_operand" "n")
- (const_int 0)))
- (clobber (reg:CC CC_REGNUM))]
- "INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
- (clobber (reg:CC CC_REGNUM))])
- (set (match_dup 0) (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
-{
- int bitsize = INTVAL (operands[2]);
- int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
- int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
-
- operands[1] = adjust_address (operands[1], BLKmode, 0);
- set_mem_size (operands[1], size);
- operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
- operands[3] = GEN_INT (mask);
-})
-
-(define_insn_and_split "*extv<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (sign_extract:GPR (match_operand:QI 1 "s_operand" "QS")
- (match_operand 2 "const_int_operand" "n")
- (const_int 0)))
- (clobber (reg:CC CC_REGNUM))]
- "INTVAL (operands[2]) > 0
- && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])]
-{
- int bitsize = INTVAL (operands[2]);
- int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
- int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
-
- operands[1] = adjust_address (operands[1], BLKmode, 0);
- set_mem_size (operands[1], size);
- operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
- operands[3] = GEN_INT (mask);
-})
-
-;
-; insv instruction patterns
-;
-
-(define_expand "insv"
- [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
- (match_operand 1 "const_int_operand" "")
- (match_operand 2 "const_int_operand" ""))
- (match_operand 3 "general_operand" ""))]
- ""
-{
- if (s390_expand_insv (operands[0], operands[1], operands[2], operands[3]))
- DONE;
- FAIL;
-})
-
-(define_insn "*insv<mode>_z10"
- [(set (zero_extract:GPR (match_operand:GPR 0 "nonimmediate_operand" "+d")
- (match_operand 1 "const_int_operand" "I")
- (match_operand 2 "const_int_operand" "I"))
- (match_operand:GPR 3 "nonimmediate_operand" "d"))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10
- && (INTVAL (operands[1]) + INTVAL (operands[2])) <=
- GET_MODE_BITSIZE (<MODE>mode)"
-{
- int start = INTVAL (operands[2]);
- int size = INTVAL (operands[1]);
- int offset = 64 - GET_MODE_BITSIZE (<MODE>mode);
-
- operands[2] = GEN_INT (offset + start); /* start bit position */
- operands[1] = GEN_INT (offset + start + size - 1); /* end bit position */
- operands[4] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) -
- start - size); /* left shift count */
-
- return "risbg\t%0,%3,%b2,%b1,%b4";
-}
- [(set_attr "op_type" "RIE")
- (set_attr "z10prop" "z10_super_E1")])
-
-; and op1 with a mask being 1 for the selected bits and 0 for the rest
-; and op3=op0 with a mask being 0 for the selected bits and 1 for the rest
-(define_insn "*insv<mode>_z10_noshift"
- [(set (match_operand:GPR 0 "nonimmediate_operand" "=d")
- (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d")
- (match_operand 2 "const_int_operand" "n"))
- (and:GPR (match_operand:GPR 3 "nonimmediate_operand" "0")
- (match_operand 4 "const_int_operand" "n"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10
- && s390_contiguous_bitmask_p (INTVAL (operands[2]),
- GET_MODE_BITSIZE (<MODE>mode), NULL, NULL)
- && INTVAL (operands[2]) == ~(INTVAL (operands[4]))"
-
-{
- int start;
- int size;
-
- s390_contiguous_bitmask_p (INTVAL (operands[2]),
- GET_MODE_BITSIZE (<MODE>mode), &start, &size);
-
- operands[5] = GEN_INT (64 - start - size); /* start bit position */
- operands[6] = GEN_INT (64 - 1 - start); /* end bit position */
- operands[7] = const0_rtx; /* left shift count */
-
- return "risbg\t%0,%1,%b5,%b6,%b7";
-}
- [(set_attr "op_type" "RIE")
- (set_attr "z10prop" "z10_super_E1")])
-
-; and op1 with a mask being 1 for the selected bits and 0 for the rest
-(define_insn "*insv<mode>_or_z10_noshift"
- [(set (match_operand:GPR 0 "nonimmediate_operand" "=d")
- (ior:GPR (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "d")
- (match_operand 2 "const_int_operand" "n"))
- (match_operand:GPR 3 "nonimmediate_operand" "0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z10
- && s390_contiguous_bitmask_p (INTVAL (operands[2]),
- GET_MODE_BITSIZE (<MODE>mode), NULL, NULL)"
-{
- int start;
- int size;
-
- s390_contiguous_bitmask_p (INTVAL (operands[2]),
- GET_MODE_BITSIZE (<MODE>mode), &start, &size);
-
- operands[4] = GEN_INT (64 - start - size); /* start bit position */
- operands[5] = GEN_INT (64 - 1 - start); /* end bit position */
- operands[6] = const0_rtx; /* left shift count */
-
- return "rosbg\t%0,%1,%b4,%b5,%b6";
-}
- [(set_attr "op_type" "RIE")])
-
-(define_insn "*insv<mode>_mem_reg"
- [(set (zero_extract:W (match_operand:QI 0 "memory_operand" "+Q,S")
- (match_operand 1 "const_int_operand" "n,n")
- (const_int 0))
- (match_operand:W 2 "register_operand" "d,d"))]
- "INTVAL (operands[1]) > 0
- && INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
- && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
-{
- int size = INTVAL (operands[1]) / BITS_PER_UNIT;
-
- operands[1] = GEN_INT ((1ul << size) - 1);
- return (which_alternative == 0) ? "stcm\t%2,%1,%S0"
- : "stcmy\t%2,%1,%S0";
-}
- [(set_attr "op_type" "RS,RSY")
- (set_attr "z10prop" "z10_super,z10_super")])
-
-(define_insn "*insvdi_mem_reghigh"
- [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "+QS")
- (match_operand 1 "const_int_operand" "n")
- (const_int 0))
- (lshiftrt:DI (match_operand:DI 2 "register_operand" "d")
- (const_int 32)))]
- "TARGET_ZARCH
- && INTVAL (operands[1]) > 0
- && INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
- && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
-{
- int size = INTVAL (operands[1]) / BITS_PER_UNIT;
-
- operands[1] = GEN_INT ((1ul << size) - 1);
- return "stcmh\t%2,%1,%S0";
-}
-[(set_attr "op_type" "RSY")
- (set_attr "z10prop" "z10_super")])
-
-(define_insn "*insvdi_reg_imm"
- [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+d")
- (const_int 16)
- (match_operand 1 "const_int_operand" "n"))
- (match_operand:DI 2 "const_int_operand" "n"))]
- "TARGET_ZARCH
- && INTVAL (operands[1]) >= 0
- && INTVAL (operands[1]) < BITS_PER_WORD
- && INTVAL (operands[1]) % 16 == 0"
-{
- switch (BITS_PER_WORD - INTVAL (operands[1]))
- {
- case 64: return "iihh\t%0,%x2"; break;
- case 48: return "iihl\t%0,%x2"; break;
- case 32: return "iilh\t%0,%x2"; break;
- case 16: return "iill\t%0,%x2"; break;
- default: gcc_unreachable();
- }
-}
- [(set_attr "op_type" "RI")
- (set_attr "z10prop" "z10_super_E1")])
-
-; Update the left-most 32 bit of a DI.
-(define_insn "*insv_h_di_reg_extimm"
- [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+d")
- (const_int 32)
- (const_int 0))
- (match_operand:DI 1 "const_int_operand" "n"))]
- "TARGET_EXTIMM"
- "iihf\t%0,%o1"
- [(set_attr "op_type" "RIL")
- (set_attr "z10prop" "z10_fwd_E1")])
-
-; Update the right-most 32 bit of a DI, or the whole of a SI.
-(define_insn "*insv_l<mode>_reg_extimm"
- [(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
- (const_int 32)
- (match_operand 1 "const_int_operand" "n"))
- (match_operand:P 2 "const_int_operand" "n"))]
- "TARGET_EXTIMM
- && BITS_PER_WORD - INTVAL (operands[1]) == 32"
- "iilf\t%0,%o2"
- [(set_attr "op_type" "RIL")
- (set_attr "z10prop" "z10_fwd_A1")])
-
-;
-; extendsidi2 instruction pattern(s).
-;
-
-(define_expand "extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
- ""
-{
- if (!TARGET_ZARCH)
- {
- emit_clobber (operands[0]);
- emit_move_insn (gen_highpart (SImode, operands[0]), operands[1]);
- emit_move_insn (gen_lowpart (SImode, operands[0]), const0_rtx);
- emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (32)));
- DONE;
- }
-})
-
-(define_insn "*extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT,b")))]
- "TARGET_ZARCH"
- "@
- lgfr\t%0,%1
- lgf\t%0,%1
- lgfrl\t%0,%1"
- [(set_attr "op_type" "RRE,RXY,RIL")
- (set_attr "type" "*,*,larl")
- (set_attr "cpu_facility" "*,*,z10")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,z10_super_E1")])
-
-;
-; extend(hi|qi)(si|di)2 instruction pattern(s).
-;
-
-(define_expand "extend<HQI:mode><DSI:mode>2"
- [(set (match_operand:DSI 0 "register_operand" "")
- (sign_extend:DSI (match_operand:HQI 1 "nonimmediate_operand" "")))]
- ""
-{
- if (<DSI:MODE>mode == DImode && !TARGET_ZARCH)
- {
- rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_extend<HQI:mode>si2 (tmp, operands[1]));
- emit_insn (gen_extendsidi2 (operands[0], tmp));
- DONE;
- }
- else if (!TARGET_EXTIMM)
- {
- rtx bitcount = GEN_INT (GET_MODE_BITSIZE (<DSI:MODE>mode) -
- GET_MODE_BITSIZE (<HQI:MODE>mode));
-
- operands[1] = gen_lowpart (<DSI:MODE>mode, operands[1]);
- emit_insn (gen_ashl<DSI:mode>3 (operands[0], operands[1], bitcount));
- emit_insn (gen_ashr<DSI:mode>3 (operands[0], operands[0], bitcount));
- DONE;
- }
-})
-
-;
-; extendhidi2 instruction pattern(s).
-;
-
-(define_insn "*extendhidi2_extimm"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (sign_extend:DI (match_operand:HI 1 "general_operand" "d,RT,b")))]
- "TARGET_ZARCH && TARGET_EXTIMM"
- "@
- lghr\t%0,%1
- lgh\t%0,%1
- lghrl\t%0,%1"
- [(set_attr "op_type" "RRE,RXY,RIL")
- (set_attr "type" "*,*,larl")
- (set_attr "cpu_facility" "extimm,extimm,z10")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,z10_super_E1")])
-
-(define_insn "*extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:HI 1 "memory_operand" "RT")))]
- "TARGET_ZARCH"
- "lgh\t%0,%1"
- [(set_attr "op_type" "RXY")
- (set_attr "z10prop" "z10_super_E1")])
-
-;
-; extendhisi2 instruction pattern(s).
-;
-
-(define_insn "*extendhisi2_extimm"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
- (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" " d,R,T,b")))]
- "TARGET_EXTIMM"
- "@
- lhr\t%0,%1
- lh\t%0,%1
- lhy\t%0,%1
- lhrl\t%0,%1"
- [(set_attr "op_type" "RRE,RX,RXY,RIL")
- (set_attr "type" "*,*,*,larl")
- (set_attr "cpu_facility" "extimm,extimm,extimm,z10")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,z10_super_E1,z10_super_E1")])
-
-(define_insn "*extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T")))]
- "!TARGET_EXTIMM"
- "@
- lh\t%0,%1
- lhy\t%0,%1"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-;
-; extendqi(si|di)2 instruction pattern(s).
-;
-
-; lbr, lgbr, lb, lgb
-(define_insn "*extendqi<mode>2_extimm"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (sign_extend:GPR (match_operand:QI 1 "nonimmediate_operand" "d,RT")))]
- "TARGET_EXTIMM"
- "@
- l<g>br\t%0,%1
- l<g>b\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-; lb, lgb
-(define_insn "*extendqi<mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (sign_extend:GPR (match_operand:QI 1 "memory_operand" "RT")))]
- "!TARGET_EXTIMM && TARGET_LONG_DISPLACEMENT"
- "l<g>b\t%0,%1"
- [(set_attr "op_type" "RXY")
- (set_attr "z10prop" "z10_super_E1")])
-
-(define_insn_and_split "*extendqi<mode>2_short_displ"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (sign_extend:GPR (match_operand:QI 1 "s_operand" "Q")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_EXTIMM && !TARGET_LONG_DISPLACEMENT"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 0) (unspec:GPR [(match_dup 1) (const_int 8)] UNSPEC_ICM))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])]
-{
- operands[1] = adjust_address (operands[1], BLKmode, 0);
- set_mem_size (operands[1], GET_MODE_SIZE (QImode));
- operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)
- - GET_MODE_BITSIZE (QImode));
-})
-
-;
-; zero_extendsidi2 instruction pattern(s).
-;
-
-(define_expand "zero_extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
- ""
-{
- if (!TARGET_ZARCH)
- {
- emit_clobber (operands[0]);
- emit_move_insn (gen_lowpart (SImode, operands[0]), operands[1]);
- emit_move_insn (gen_highpart (SImode, operands[0]), const0_rtx);
- DONE;
- }
-})
-
-(define_insn "*zero_extendsidi2"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,RT,b")))]
- "TARGET_ZARCH"
- "@
- llgfr\t%0,%1
- llgf\t%0,%1
- llgfrl\t%0,%1"
- [(set_attr "op_type" "RRE,RXY,RIL")
- (set_attr "type" "*,*,larl")
- (set_attr "cpu_facility" "*,*,z10")
- (set_attr "z10prop" "z10_fwd_E1,z10_fwd_A3,z10_fwd_A3")])
-
-;
-; LLGT-type instructions (zero-extend from 31 bit to 64 bit).
-;
-
-(define_insn "*llgt_sidi"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (and:DI (subreg:DI (match_operand:SI 1 "memory_operand" "RT") 0)
- (const_int 2147483647)))]
- "TARGET_ZARCH"
- "llgt\t%0,%1"
- [(set_attr "op_type" "RXE")
- (set_attr "z10prop" "z10_super_E1")])
-
-(define_insn_and_split "*llgt_sidi_split"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (and:DI (subreg:DI (match_operand:SI 1 "memory_operand" "RT") 0)
- (const_int 2147483647)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (and:DI (subreg:DI (match_dup 1) 0)
- (const_int 2147483647)))]
- "")
-
-(define_insn "*llgt_sisi"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "d,RT")
- (const_int 2147483647)))]
- "TARGET_ZARCH"
- "@
- llgtr\t%0,%1
- llgt\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-(define_insn "*llgt_didi"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o")
- (const_int 2147483647)))]
- "TARGET_ZARCH"
- "@
- llgtr\t%0,%1
- llgt\t%0,%N1"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-(define_split
- [(set (match_operand:DSI 0 "register_operand" "")
- (and:DSI (match_operand:DSI 1 "nonimmediate_operand" "")
- (const_int 2147483647)))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && reload_completed"
- [(set (match_dup 0)
- (and:DSI (match_dup 1)
- (const_int 2147483647)))]
- "")
-
-;
-; zero_extend(hi|qi)(si|di)2 instruction pattern(s).
-;
-
-(define_expand "zero_extend<mode>di2"
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (match_operand:HQI 1 "nonimmediate_operand" "")))]
- ""
-{
- if (!TARGET_ZARCH)
- {
- rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_zero_extend<mode>si2 (tmp, operands[1]));
- emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
- DONE;
- }
- else if (!TARGET_EXTIMM)
- {
- rtx bitcount = GEN_INT (GET_MODE_BITSIZE(DImode) -
- GET_MODE_BITSIZE(<MODE>mode));
- operands[1] = gen_lowpart (DImode, operands[1]);
- emit_insn (gen_ashldi3 (operands[0], operands[1], bitcount));
- emit_insn (gen_lshrdi3 (operands[0], operands[0], bitcount));
- DONE;
- }
-})
-
-(define_expand "zero_extend<mode>si2"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:HQI 1 "nonimmediate_operand" "")))]
- ""
-{
- if (!TARGET_EXTIMM)
- {
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_andsi3 (operands[0], operands[1],
- GEN_INT ((1 << GET_MODE_BITSIZE(<MODE>mode)) - 1)));
- DONE;
- }
-})
-
-; llhrl, llghrl
-(define_insn "*zero_extendhi<mode>2_z10"
- [(set (match_operand:GPR 0 "register_operand" "=d,d,d")
- (zero_extend:GPR (match_operand:HI 1 "nonimmediate_operand" "d,RT,b")))]
- "TARGET_Z10"
- "@
- ll<g>hr\t%0,%1
- ll<g>h\t%0,%1
- ll<g>hrl\t%0,%1"
- [(set_attr "op_type" "RXY,RRE,RIL")
- (set_attr "type" "*,*,larl")
- (set_attr "cpu_facility" "*,*,z10")
- (set_attr "z10prop" "z10_super_E1,z10_fwd_A3,z10_fwd_A3")])
-
-; llhr, llcr, llghr, llgcr, llh, llc, llgh, llgc
-(define_insn "*zero_extend<HQI:mode><GPR:mode>2_extimm"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (zero_extend:GPR (match_operand:HQI 1 "nonimmediate_operand" "d,RT")))]
- "TARGET_EXTIMM"
- "@
- ll<g><hc>r\t%0,%1
- ll<g><hc>\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_E1,z10_fwd_A3")])
-
-; llgh, llgc
-(define_insn "*zero_extend<HQI:mode><GPR:mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (zero_extend:GPR (match_operand:HQI 1 "memory_operand" "RT")))]
- "TARGET_ZARCH && !TARGET_EXTIMM"
- "llg<hc>\t%0,%1"
- [(set_attr "op_type" "RXY")
- (set_attr "z10prop" "z10_fwd_A3")])
-
-(define_insn_and_split "*zero_extendhisi2_31"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (zero_extend:SI (match_operand:HI 1 "s_operand" "QS")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (const_int 0))
- (parallel
- [(set (strict_low_part (match_dup 2)) (match_dup 1))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[2] = gen_lowpart (HImode, operands[0]);")
-
-(define_insn_and_split "*zero_extendqisi2_31"
- [(set (match_operand:SI 0 "register_operand" "=&d")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "RT")))]
- "!TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (const_int 0))
- (set (strict_low_part (match_dup 2)) (match_dup 1))]
- "operands[2] = gen_lowpart (QImode, operands[0]);")
-
-;
-; zero_extendqihi2 instruction pattern(s).
-;
-
-(define_expand "zero_extendqihi2"
- [(set (match_operand:HI 0 "register_operand" "")
- (zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
- "TARGET_ZARCH && !TARGET_EXTIMM"
-{
- operands[1] = gen_lowpart (HImode, operands[1]);
- emit_insn (gen_andhi3 (operands[0], operands[1], GEN_INT (0xff)));
- DONE;
-})
-
-(define_insn "*zero_extendqihi2_64"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (zero_extend:HI (match_operand:QI 1 "memory_operand" "RT")))]
- "TARGET_ZARCH && !TARGET_EXTIMM"
- "llgc\t%0,%1"
- [(set_attr "op_type" "RXY")
- (set_attr "z10prop" "z10_fwd_A3")])
-
-(define_insn_and_split "*zero_extendqihi2_31"
- [(set (match_operand:HI 0 "register_operand" "=&d")
- (zero_extend:HI (match_operand:QI 1 "memory_operand" "RT")))]
- "!TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (const_int 0))
- (set (strict_low_part (match_dup 2)) (match_dup 1))]
- "operands[2] = gen_lowpart (QImode, operands[0]);")
-
-;
-; fixuns_trunc(dd|td)di2 instruction pattern(s).
-;
-
-(define_expand "fixuns_truncdddi2"
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (unsigned_fix:DI (match_operand:DD 1 "register_operand" "")))
- (unspec:DI [(const_int 5)] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))])]
-
- "TARGET_HARD_DFP"
-{
- if (!TARGET_Z196)
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx temp = gen_reg_rtx (TDmode);
- REAL_VALUE_TYPE cmp, sub;
-
- decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */
- decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */
-
- /* 2^63 can't be represented as 64bit DFP number with full precision. The
- solution is doing the check and the subtraction in TD mode and using a
- TD -> DI convert afterwards. */
- emit_insn (gen_extendddtd2 (temp, operands[1]));
- temp = force_reg (TDmode, temp);
- emit_cmp_and_jump_insns (temp,
- CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode),
- LT, NULL_RTX, VOIDmode, 0, label1);
- emit_insn (gen_subtd3 (temp, temp,
- CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode)));
- emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11)));
- emit_jump (label2);
-
- emit_label (label1);
- emit_insn (gen_fix_truncdddi2_dfp (operands[0], operands[1], GEN_INT (9)));
- emit_label (label2);
- DONE;
- }
-})
-
-(define_expand "fixuns_trunctddi2"
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (unsigned_fix:DI (match_operand:TD 1 "register_operand" "")))
- (unspec:DI [(const_int 5)] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))])]
-
- "TARGET_HARD_DFP"
-{
- if (!TARGET_Z196)
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx temp = gen_reg_rtx (TDmode);
- REAL_VALUE_TYPE cmp, sub;
-
- operands[1] = force_reg (TDmode, operands[1]);
- decimal_real_from_string (&cmp, "9223372036854775808.0"); /* 2^63 */
- decimal_real_from_string (&sub, "18446744073709551616.0"); /* 2^64 */
-
- emit_cmp_and_jump_insns (operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (cmp, TDmode),
- LT, NULL_RTX, VOIDmode, 0, label1);
- emit_insn (gen_subtd3 (temp, operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (sub, TDmode)));
- emit_insn (gen_fix_trunctddi2_dfp (operands[0], temp, GEN_INT (11)));
- emit_jump (label2);
-
- emit_label (label1);
- emit_insn (gen_fix_trunctddi2_dfp (operands[0], operands[1], GEN_INT (9)));
- emit_label (label2);
- DONE;
- }
-})
-
-;
-; fixuns_trunc(sf|df|tf)(si|di)2 and fix_trunc(sf|df|tf)(si|di)2
-; instruction pattern(s).
-;
-
-(define_expand "fixuns_trunc<BFP:mode><GPR:mode>2"
- [(parallel
- [(set (match_operand:GPR 0 "register_operand" "")
- (unsigned_fix:GPR (match_operand:BFP 1 "register_operand" "")))
- (unspec:GPR [(const_int 5)] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_HARD_FLOAT"
-{
- if (!TARGET_Z196)
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- rtx temp = gen_reg_rtx (<BFP:MODE>mode);
- REAL_VALUE_TYPE cmp, sub;
-
- operands[1] = force_reg (<BFP:MODE>mode, operands[1]);
- real_2expN (&cmp, GET_MODE_BITSIZE(<GPR:MODE>mode) - 1, <BFP:MODE>mode);
- real_2expN (&sub, GET_MODE_BITSIZE(<GPR:MODE>mode), <BFP:MODE>mode);
-
- emit_cmp_and_jump_insns (operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (cmp, <BFP:MODE>mode),
- LT, NULL_RTX, VOIDmode, 0, label1);
- emit_insn (gen_sub<BFP:mode>3 (temp, operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (sub, <BFP:MODE>mode)));
- emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0], temp,
- GEN_INT (7)));
- emit_jump (label2);
-
- emit_label (label1);
- emit_insn (gen_fix_trunc<BFP:mode><GPR:mode>2_bfp (operands[0],
- operands[1], GEN_INT (5)));
- emit_label (label2);
- DONE;
- }
-})
-
-; fixuns_trunc(td|dd)si2 expander
-(define_expand "fixuns_trunc<mode>si2"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (unsigned_fix:SI (match_operand:DFP 1 "register_operand" "")))
- (unspec:SI [(const_int 5)] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_Z196 && TARGET_HARD_DFP"
- "")
-
-; fixuns_trunc(tf|df|sf|td|dd)(di|si)2 instruction patterns.
-
-; clfebr, clfdbr, clfxbr, clgebr, clgdbr, clgxbr
-; clfdtr, clfxtr, clgdtr, clgxtr
-(define_insn "*fixuns_trunc<FP:mode><GPR:mode>2_z196"
- [(set (match_operand:GPR 0 "register_operand" "=r")
- (unsigned_fix:GPR (match_operand:FP 1 "register_operand" "f")))
- (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z196"
- "cl<GPR:gf><FP:xde><FP:bt>r\t%0,%h2,%1,0"
- [(set_attr "op_type" "RRF")
- (set_attr "type" "ftoi")])
-
-(define_expand "fix_trunc<DSF:mode><GPR:mode>2"
- [(set (match_operand:GPR 0 "register_operand" "")
- (fix:GPR (match_operand:DSF 1 "register_operand" "")))]
- "TARGET_HARD_FLOAT"
-{
- emit_insn (gen_fix_trunc<DSF:mode><GPR:mode>2_bfp (operands[0], operands[1],
- GEN_INT (5)));
- DONE;
-})
-
-; cgxbr, cgdbr, cgebr, cfxbr, cfdbr, cfebr
-(define_insn "fix_trunc<BFP:mode><GPR:mode>2_bfp"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (fix:GPR (match_operand:BFP 1 "register_operand" "f")))
- (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_FLOAT"
- "c<GPR:gf><BFP:xde>br\t%0,%h2,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "ftoi")])
-
-
-;
-; fix_trunc(td|dd)di2 instruction pattern(s).
-;
-
-(define_expand "fix_trunc<mode>di2"
- [(set (match_operand:DI 0 "register_operand" "")
- (fix:DI (match_operand:DFP 1 "nonimmediate_operand" "")))]
- "TARGET_ZARCH && TARGET_HARD_DFP"
-{
- operands[1] = force_reg (<MODE>mode, operands[1]);
- emit_insn (gen_fix_trunc<mode>di2_dfp (operands[0], operands[1],
- GEN_INT (9)));
- DONE;
-})
-
-; cgxtr, cgdtr
-(define_insn "fix_trunc<DFP:mode>di2_dfp"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (fix:DI (match_operand:DFP 1 "register_operand" "f")))
- (unspec:DI [(match_operand:DI 2 "immediate_operand" "K")] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && TARGET_HARD_DFP"
- "cg<DFP:xde>tr\t%0,%h2,%1"
- [(set_attr "op_type" "RRF")
- (set_attr "type" "ftoidfp")])
-
-
-;
-; fix_trunctf(si|di)2 instruction pattern(s).
-;
-
-(define_expand "fix_trunctf<mode>2"
- [(parallel [(set (match_operand:GPR 0 "register_operand" "")
- (fix:GPR (match_operand:TF 1 "register_operand" "")))
- (unspec:GPR [(const_int 5)] UNSPEC_ROUND)
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_HARD_FLOAT"
- "")
-
-
-;
-; float(si|di)(tf|df|sf|td|dd)2 instruction pattern(s).
-;
-
-; cxgbr, cdgbr, cegbr, cxgtr, cdgtr
-(define_insn "floatdi<mode>2"
- [(set (match_operand:FP 0 "register_operand" "=f")
- (float:FP (match_operand:DI 1 "register_operand" "d")))]
- "TARGET_ZARCH && TARGET_HARD_FLOAT"
- "c<xde>g<bt>r\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "itof<mode>" )])
-
-; cxfbr, cdfbr, cefbr
-(define_insn "floatsi<mode>2"
- [(set (match_operand:BFP 0 "register_operand" "=f")
- (float:BFP (match_operand:SI 1 "register_operand" "d")))]
- "TARGET_HARD_FLOAT"
- "c<xde>fbr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "itof<mode>" )])
-
-; cxftr, cdftr
-(define_insn "floatsi<mode>2"
- [(set (match_operand:DFP 0 "register_operand" "=f")
- (float:DFP (match_operand:SI 1 "register_operand" "d")))]
- "TARGET_Z196 && TARGET_HARD_FLOAT"
- "c<xde>ftr\t%0,0,%1,0"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "itof<mode>" )])
-
-;
-; floatuns(si|di)(tf|df|sf|td|dd)2 instruction pattern(s).
-;
-
-; cxlgbr, cdlgbr, celgbr, cxlgtr, cdlgtr
-; cxlfbr, cdlfbr, celfbr, cxlftr, cdlftr
-(define_insn "floatuns<GPR:mode><FP:mode>2"
- [(set (match_operand:FP 0 "register_operand" "=f")
- (unsigned_float:FP (match_operand:GPR 1 "register_operand" "d")))]
- "TARGET_Z196 && TARGET_HARD_FLOAT"
- "c<FP:xde>l<GPR:gf><FP:bt>r\t%0,0,%1,0"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "itof<FP:mode>" )])
-
-;
-; truncdfsf2 instruction pattern(s).
-;
-
-(define_insn "truncdfsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
- "TARGET_HARD_FLOAT"
- "ledbr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "ftruncdf")])
-
-;
-; trunctf(df|sf)2 instruction pattern(s).
-;
-
-; ldxbr, lexbr
-(define_insn "trunctf<mode>2"
- [(set (match_operand:DSF 0 "register_operand" "=f")
- (float_truncate:DSF (match_operand:TF 1 "register_operand" "f")))
- (clobber (match_scratch:TF 2 "=f"))]
- "TARGET_HARD_FLOAT"
- "l<xde>xbr\t%2,%1\;l<xde>r\t%0,%2"
- [(set_attr "length" "6")
- (set_attr "type" "ftrunctf")])
-
-;
-; trunctddd2 and truncddsd2 instruction pattern(s).
-;
-
-(define_insn "trunctddd2"
- [(set (match_operand:DD 0 "register_operand" "=f")
- (float_truncate:DD (match_operand:TD 1 "register_operand" "f")))
- (clobber (match_scratch:TD 2 "=f"))]
- "TARGET_HARD_DFP"
- "ldxtr\t%2,0,%1,0\;ldr\t%0,%2"
- [(set_attr "length" "6")
- (set_attr "type" "ftruncdd")])
-
-(define_insn "truncddsd2"
- [(set (match_operand:SD 0 "register_operand" "=f")
- (float_truncate:SD (match_operand:DD 1 "register_operand" "f")))]
- "TARGET_HARD_DFP"
- "ledtr\t%0,0,%1,0"
- [(set_attr "op_type" "RRF")
- (set_attr "type" "ftruncsd")])
-
-;
-; extend(sf|df)(df|tf)2 instruction pattern(s).
-;
-
-; ldebr, ldeb, lxdbr, lxdb, lxebr, lxeb
-(define_insn "extend<DSF:mode><BFP:mode>2"
- [(set (match_operand:BFP 0 "register_operand" "=f,f")
- (float_extend:BFP (match_operand:DSF 1 "nonimmediate_operand" "f,R")))]
- "TARGET_HARD_FLOAT
- && GET_MODE_SIZE (<BFP:MODE>mode) > GET_MODE_SIZE (<DSF:MODE>mode)"
- "@
- l<BFP:xde><DSF:xde>br\t%0,%1
- l<BFP:xde><DSF:xde>b\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimp<BFP:mode>, fload<BFP:mode>")])
-
-;
-; extendddtd2 and extendsddd2 instruction pattern(s).
-;
-
-(define_insn "extendddtd2"
- [(set (match_operand:TD 0 "register_operand" "=f")
- (float_extend:TD (match_operand:DD 1 "register_operand" "f")))]
- "TARGET_HARD_DFP"
- "lxdtr\t%0,%1,0"
- [(set_attr "op_type" "RRF")
- (set_attr "type" "fsimptf")])
-
-(define_insn "extendsddd2"
- [(set (match_operand:DD 0 "register_operand" "=f")
- (float_extend:DD (match_operand:SD 1 "register_operand" "f")))]
- "TARGET_HARD_DFP"
- "ldetr\t%0,%1,0"
- [(set_attr "op_type" "RRF")
- (set_attr "type" "fsimptf")])
-
-; Binary <-> Decimal floating point trunc patterns
-;
-
-(define_insn "*trunc<BFP:mode><DFP_ALL:mode>2"
- [(set (reg:DFP_ALL FPR0_REGNUM)
- (float_truncate:DFP_ALL (reg:BFP FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_DFP"
- "pfpo")
-
-(define_insn "*trunc<DFP_ALL:mode><BFP:mode>2"
- [(set (reg:BFP FPR0_REGNUM)
- (float_truncate:BFP (reg:DFP_ALL FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_DFP"
- "pfpo")
-
-(define_expand "trunc<BFP:mode><DFP_ALL:mode>2"
- [(set (reg:BFP FPR2_REGNUM) (match_operand:BFP 1 "nonimmediate_operand" ""))
- (set (reg:SI GPR0_REGNUM) (match_dup 2))
- (parallel
- [(set (reg:DFP_ALL FPR0_REGNUM)
- (float_truncate:DFP_ALL (reg:BFP FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))])
- (set (match_operand:DFP_ALL 0 "nonimmediate_operand" "")
- (reg:DFP_ALL FPR0_REGNUM))]
- "TARGET_HARD_DFP
- && GET_MODE_SIZE (<BFP:MODE>mode) > GET_MODE_SIZE (<DFP_ALL:MODE>mode)"
-{
- HOST_WIDE_INT flags;
-
- flags = (PFPO_CONVERT |
- PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT);
-
- operands[2] = GEN_INT (flags);
-})
-
-(define_expand "trunc<DFP_ALL:mode><BFP:mode>2"
- [(set (reg:DFP_ALL FPR2_REGNUM)
- (match_operand:DFP_ALL 1 "nonimmediate_operand" ""))
- (set (reg:SI GPR0_REGNUM) (match_dup 2))
- (parallel
- [(set (reg:BFP FPR0_REGNUM) (float_truncate:BFP (reg:DFP_ALL FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))])
- (set (match_operand:BFP 0 "nonimmediate_operand" "") (reg:BFP FPR0_REGNUM))]
- "TARGET_HARD_DFP
- && GET_MODE_SIZE (<DFP_ALL:MODE>mode) >= GET_MODE_SIZE (<BFP:MODE>mode)"
-{
- HOST_WIDE_INT flags;
-
- flags = (PFPO_CONVERT |
- PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT);
-
- operands[2] = GEN_INT (flags);
-})
-
-;
-; Binary <-> Decimal floating point extend patterns
-;
-
-(define_insn "*extend<BFP:mode><DFP_ALL:mode>2"
- [(set (reg:DFP_ALL FPR0_REGNUM) (float_extend:DFP_ALL (reg:BFP FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_DFP"
- "pfpo")
-
-(define_insn "*extend<DFP_ALL:mode><BFP:mode>2"
- [(set (reg:BFP FPR0_REGNUM) (float_extend:BFP (reg:DFP_ALL FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_DFP"
- "pfpo")
-
-(define_expand "extend<BFP:mode><DFP_ALL:mode>2"
- [(set (reg:BFP FPR2_REGNUM) (match_operand:BFP 1 "nonimmediate_operand" ""))
- (set (reg:SI GPR0_REGNUM) (match_dup 2))
- (parallel
- [(set (reg:DFP_ALL FPR0_REGNUM)
- (float_extend:DFP_ALL (reg:BFP FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))])
- (set (match_operand:DFP_ALL 0 "nonimmediate_operand" "")
- (reg:DFP_ALL FPR0_REGNUM))]
- "TARGET_HARD_DFP
- && GET_MODE_SIZE (<BFP:MODE>mode) <= GET_MODE_SIZE (<DFP_ALL:MODE>mode)"
-{
- HOST_WIDE_INT flags;
-
- flags = (PFPO_CONVERT |
- PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT);
-
- operands[2] = GEN_INT (flags);
-})
-
-(define_expand "extend<DFP_ALL:mode><BFP:mode>2"
- [(set (reg:DFP_ALL FPR2_REGNUM)
- (match_operand:DFP_ALL 1 "nonimmediate_operand" ""))
- (set (reg:SI GPR0_REGNUM) (match_dup 2))
- (parallel
- [(set (reg:BFP FPR0_REGNUM) (float_extend:BFP (reg:DFP_ALL FPR2_REGNUM)))
- (use (reg:SI GPR0_REGNUM))
- (clobber (reg:CC CC_REGNUM))])
- (set (match_operand:BFP 0 "nonimmediate_operand" "") (reg:BFP FPR0_REGNUM))]
- "TARGET_HARD_DFP
- && GET_MODE_SIZE (<DFP_ALL:MODE>mode) < GET_MODE_SIZE (<BFP:MODE>mode)"
-{
- HOST_WIDE_INT flags;
-
- flags = (PFPO_CONVERT |
- PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP0_TYPE_SHIFT |
- PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT);
-
- operands[2] = GEN_INT (flags);
-})
-
-
-;;
-;; ARITHMETIC OPERATIONS
-;;
-; arithmetic operations set the ConditionCode,
-; because of unpredictable Bits in Register for Halfword and Byte
-; the ConditionCode can be set wrong in operations for Halfword and Byte
-
-;;
-;;- Add instructions.
-;;
-
-;
-; addti3 instruction pattern(s).
-;
-
-(define_insn_and_split "addti3"
- [(set (match_operand:TI 0 "register_operand" "=&d")
- (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
- (match_operand:TI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (reg:CCL1 CC_REGNUM)
- (compare:CCL1 (plus:DI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (plus:DI (match_dup 7) (match_dup 8)))])
- (parallel
- [(set (match_dup 3) (plus:DI
- (plus:DI (ltu:DI (reg:CCL1 CC_REGNUM) (const_int 0))
- (match_dup 4)) (match_dup 5)))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[3] = operand_subword (operands[0], 0, 0, TImode);
- operands[4] = operand_subword (operands[1], 0, 0, TImode);
- operands[5] = operand_subword (operands[2], 0, 0, TImode);
- operands[6] = operand_subword (operands[0], 1, 0, TImode);
- operands[7] = operand_subword (operands[1], 1, 0, TImode);
- operands[8] = operand_subword (operands[2], 1, 0, TImode);")
-
-;
-; adddi3 instruction pattern(s).
-;
-
-(define_expand "adddi3"
- [(parallel
- [(set (match_operand:DI 0 "nonimmediate_operand" "")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:DI 2 "general_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "")
-
-(define_insn "*adddi3_sign"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))
- (match_operand:DI 1 "register_operand" "0,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "@
- agfr\t%0,%2
- agf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z196prop" "z196_cracked,z196_cracked")])
-
-(define_insn "*adddi3_zero_cc"
- [(set (reg CC_REGNUM)
- (compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))
- (match_operand:DI 1 "register_operand" "0,0"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (zero_extend:DI (match_dup 2)) (match_dup 1)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_ZARCH"
- "@
- algfr\t%0,%2
- algf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-(define_insn "*adddi3_zero_cconly"
- [(set (reg CC_REGNUM)
- (compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))
- (match_operand:DI 1 "register_operand" "0,0"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_ZARCH"
- "@
- algfr\t%0,%2
- algf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-(define_insn "*adddi3_zero"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))
- (match_operand:DI 1 "register_operand" "0,0")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "@
- algfr\t%0,%2
- algf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1")])
-
-(define_insn_and_split "*adddi3_31z"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
- (match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (reg:CCL1 CC_REGNUM)
- (compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
- (parallel
- [(set (match_dup 3) (plus:SI
- (plus:SI (ltu:SI (reg:CCL1 CC_REGNUM) (const_int 0))
- (match_dup 4)) (match_dup 5)))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[3] = operand_subword (operands[0], 0, 0, DImode);
- operands[4] = operand_subword (operands[1], 0, 0, DImode);
- operands[5] = operand_subword (operands[2], 0, 0, DImode);
- operands[6] = operand_subword (operands[0], 1, 0, DImode);
- operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);")
-
-(define_insn_and_split "*adddi3_31"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=&d")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
- (match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 3) (plus:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (reg:CCL1 CC_REGNUM)
- (compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
- (set (pc)
- (if_then_else (ltu (reg:CCL1 CC_REGNUM) (const_int 0))
- (pc)
- (label_ref (match_dup 9))))
- (parallel
- [(set (match_dup 3) (plus:SI (match_dup 3) (const_int 1)))
- (clobber (reg:CC CC_REGNUM))])
- (match_dup 9)]
- "operands[3] = operand_subword (operands[0], 0, 0, DImode);
- operands[4] = operand_subword (operands[1], 0, 0, DImode);
- operands[5] = operand_subword (operands[2], 0, 0, DImode);
- operands[6] = operand_subword (operands[0], 1, 0, DImode);
- operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);
- operands[9] = gen_label_rtx ();")
-
-;
-; addsi3 instruction pattern(s).
-;
-
-(define_expand "addsi3"
- [(parallel
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "")
-
-(define_insn "*addsi3_sign"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (plus:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))
- (match_operand:SI 1 "register_operand" "0,0")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- ah\t%0,%2
- ahy\t%0,%2"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "z196prop" "z196_cracked,z196_cracked")])
-
-;
-; add(di|si)3 instruction pattern(s).
-;
-
-; ark, agrk, ar, ahi, ahik, aghik, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag, asi, agsi
-(define_insn "*add<mode>3"
- [(set (match_operand:GPR 0 "nonimmediate_operand" "=d,d,d,d, d, d,d,d,QS")
- (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d,0,d, 0, 0,0,0, 0")
- (match_operand:GPR 2 "general_operand" " d,d,K,K,Op,On,R,T, C") ) )
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- a<g>r\t%0,%2
- a<g>rk\t%0,%1,%2
- a<g>hi\t%0,%h2
- a<g>hik\t%0,%1,%h2
- al<g>fi\t%0,%2
- sl<g>fi\t%0,%n2
- a<g>\t%0,%2
- a<y>\t%0,%2
- a<g>si\t%0,%c2"
- [(set_attr "op_type" "RR<E>,RRF,RI,RIE,RIL,RIL,RX<Y>,RXY,SIY")
- (set_attr "cpu_facility" "*,z196,*,z196,extimm,extimm,*,*,z10")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,*,z10_super_E1,z10_super_E1,
- z10_super_E1,z10_super_E1,z10_super_E1")])
-
-; alr, alfi, slfi, al, aly, alrk, alhsik, algr, algfi, slgfi, alg, alsi, algsi, algrk, alghsik
-(define_insn "*add<mode>3_carry1_cc"
- [(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d, 0, 0,d,0,0,0")
- (match_operand:GPR 2 "general_operand" " d,d,Op,On,K,R,T,C"))
- (match_dup 1)))
- (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d, d, d,d,d,d,d")
- (plus:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode)"
- "@
- al<g>r\t%0,%2
- al<g>rk\t%0,%1,%2
- al<g>fi\t%0,%2
- sl<g>fi\t%0,%n2
- al<g>hsik\t%0,%1,%h2
- al<g>\t%0,%2
- al<y>\t%0,%2
- al<g>si\t%0,%c2"
- [(set_attr "op_type" "RR<E>,RRF,RIL,RIL,RIE,RX<Y>,RXY,SIY")
- (set_attr "cpu_facility" "*,z196,extimm,extimm,z196,*,*,z10")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1,*,
- z10_super_E1,z10_super_E1,z10_super_E1")])
-
-; alr, al, aly, algr, alg, alrk, algrk
-(define_insn "*add<mode>3_carry1_cconly"
- [(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T"))
- (match_dup 1)))
- (clobber (match_scratch:GPR 0 "=d,d,d,d"))]
- "s390_match_ccmode (insn, CCL1mode)"
- "@
- al<g>r\t%0,%2
- al<g>rk\t%0,%1,%2
- al<g>\t%0,%2
- al<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi, alrk, algrk, alhsik, alghsik
-(define_insn "*add<mode>3_carry2_cc"
- [(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d, 0, 0,d,0,0, 0")
- (match_operand:GPR 2 "general_operand" " d,d,Op,On,K,R,T, C"))
- (match_dup 2)))
- (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d, d, d,d,d,d,RS")
- (plus:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode)"
- "@
- al<g>r\t%0,%2
- al<g>rk\t%0,%1,%2
- al<g>fi\t%0,%2
- sl<g>fi\t%0,%n2
- al<g>hsik\t%0,%1,%h2
- al<g>\t%0,%2
- al<y>\t%0,%2
- al<g>si\t%0,%c2"
- [(set_attr "op_type" "RR<E>,RRF,RIL,RIL,RIE,RX<Y>,RXY,SIY")
- (set_attr "cpu_facility" "*,z196,extimm,extimm,z196,*,*,z10")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1,*,
- z10_super_E1,z10_super_E1,z10_super_E1")])
-
-; alr, al, aly, algr, alg, alrk, algrk
-(define_insn "*add<mode>3_carry2_cconly"
- [(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T"))
- (match_dup 2)))
- (clobber (match_scratch:GPR 0 "=d,d,d,d"))]
- "s390_match_ccmode (insn, CCL1mode)"
- "@
- al<g>r\t%0,%2
- al<g>rk\t%0,%1,%2
- al<g>\t%0,%2
- al<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg, alsi, algsi, alrk, algrk, alhsik, alghsik
-(define_insn "*add<mode>3_cc"
- [(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d, 0, 0,d,0,0, 0")
- (match_operand:GPR 2 "general_operand" " d,d,Op,On,K,R,T, C"))
- (const_int 0)))
- (set (match_operand:GPR 0 "nonimmediate_operand" "=d,d, d, d,d,d,d,RS")
- (plus:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCLmode)"
- "@
- al<g>r\t%0,%2
- al<g>rk\t%0,%1,%2
- al<g>fi\t%0,%2
- sl<g>fi\t%0,%n2
- al<g>hsik\t%0,%1,%h2
- al<g>\t%0,%2
- al<y>\t%0,%2
- al<g>si\t%0,%c2"
- [(set_attr "op_type" "RR<E>,RRF,RIL,RIL,RIE,RX<Y>,RXY,SIY")
- (set_attr "cpu_facility" "*,z196,extimm,extimm,z196,*,*,z10")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1,
- *,z10_super_E1,z10_super_E1,z10_super_E1")])
-
-; alr, al, aly, algr, alg, alrk, algrk
-(define_insn "*add<mode>3_cconly"
- [(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T"))
- (const_int 0)))
- (clobber (match_scratch:GPR 0 "=d,d,d,d"))]
- "s390_match_ccmode (insn, CCLmode)"
- "@
- al<g>r\t%0,%2
- al<g>rk\t%0,%1,%2
- al<g>\t%0,%2
- al<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-; alr, al, aly, algr, alg, alrk, algrk
-(define_insn "*add<mode>3_cconly2"
- [(set (reg CC_REGNUM)
- (compare (match_operand:GPR 1 "nonimmediate_operand" "%0,d,0,0")
- (neg:GPR (match_operand:GPR 2 "general_operand" "d,d,R,T"))))
- (clobber (match_scratch:GPR 0 "=d,d,d,d"))]
- "s390_match_ccmode(insn, CCLmode)"
- "@
- al<g>r\t%0,%2
- al<g>rk\t%0,%1,%2
- al<g>\t%0,%2
- al<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-; ahi, afi, aghi, agfi, asi, agsi
-(define_insn "*add<mode>3_imm_cc"
- [(set (reg CC_REGNUM)
- (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" " 0, d,0, 0")
- (match_operand:GPR 2 "const_int_operand" " K, K,Os, C"))
- (const_int 0)))
- (set (match_operand:GPR 0 "nonimmediate_operand" "=d, d,d,QS")
- (plus:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCAmode)
- && (CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")
- || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'O', \"Os\")
- || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'C', \"C\"))
- && INTVAL (operands[2]) != -((HOST_WIDE_INT)1 << (GET_MODE_BITSIZE(<MODE>mode) - 1))"
- "@
- a<g>hi\t%0,%h2
- a<g>hik\t%0,%1,%h2
- a<g>fi\t%0,%2
- a<g>si\t%0,%c2"
- [(set_attr "op_type" "RI,RIE,RIL,SIY")
- (set_attr "cpu_facility" "*,z196,extimm,z10")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-;
-; add(tf|df|sf|td|dd)3 instruction pattern(s).
-;
-
-; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
-(define_insn "add<mode>3"
- [(set (match_operand:FP 0 "register_operand" "=f, f")
- (plus:FP (match_operand:FP 1 "nonimmediate_operand" "%<f0>,0")
- (match_operand:FP 2 "general_operand" " f,<Rf>")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_FLOAT"
- "@
- a<xde><bt>r\t%0,<op1>%2
- a<xde>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fsimp<mode>")])
-
-; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
-(define_insn "*add<mode>3_cc"
- [(set (reg CC_REGNUM)
- (compare (plus:FP (match_operand:FP 1 "nonimmediate_operand" "%<f0>,0")
- (match_operand:FP 2 "general_operand" " f,<Rf>"))
- (match_operand:FP 3 "const0_operand" "")))
- (set (match_operand:FP 0 "register_operand" "=f,f")
- (plus:FP (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "@
- a<xde><bt>r\t%0,<op1>%2
- a<xde>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fsimp<mode>")])
-
-; axbr, adbr, aebr, axb, adb, aeb, adtr, axtr
-(define_insn "*add<mode>3_cconly"
- [(set (reg CC_REGNUM)
- (compare (plus:FP (match_operand:FP 1 "nonimmediate_operand" "%<f0>,0")
- (match_operand:FP 2 "general_operand" " f,<Rf>"))
- (match_operand:FP 3 "const0_operand" "")))
- (clobber (match_scratch:FP 0 "=f,f"))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "@
- a<xde><bt>r\t%0,<op1>%2
- a<xde>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fsimp<mode>")])
-
-
-;;
-;;- Subtract instructions.
-;;
-
-;
-; subti3 instruction pattern(s).
-;
-
-(define_insn_and_split "subti3"
- [(set (match_operand:TI 0 "register_operand" "=&d")
- (minus:TI (match_operand:TI 1 "register_operand" "0")
- (match_operand:TI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (reg:CCL2 CC_REGNUM)
- (compare:CCL2 (minus:DI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (minus:DI (match_dup 7) (match_dup 8)))])
- (parallel
- [(set (match_dup 3) (minus:DI (minus:DI (match_dup 4) (match_dup 5))
- (gtu:DI (reg:CCL2 CC_REGNUM) (const_int 0))))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[3] = operand_subword (operands[0], 0, 0, TImode);
- operands[4] = operand_subword (operands[1], 0, 0, TImode);
- operands[5] = operand_subword (operands[2], 0, 0, TImode);
- operands[6] = operand_subword (operands[0], 1, 0, TImode);
- operands[7] = operand_subword (operands[1], 1, 0, TImode);
- operands[8] = operand_subword (operands[2], 1, 0, TImode);")
-
-;
-; subdi3 instruction pattern(s).
-;
-
-(define_expand "subdi3"
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (minus:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "general_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "")
-
-(define_insn "*subdi3_sign"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (sign_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "@
- sgfr\t%0,%2
- sgf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_c,*")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*subdi3_zero_cc"
- [(set (reg CC_REGNUM)
- (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (zero_extend:DI (match_operand:SI 2 "general_operand" "d,RT")))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (match_dup 1) (zero_extend:DI (match_dup 2))))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_ZARCH"
- "@
- slgfr\t%0,%2
- slgf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_c_E1,z10_super_E1")])
-
-(define_insn "*subdi3_zero_cconly"
- [(set (reg CC_REGNUM)
- (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (zero_extend:DI (match_operand:SI 2 "general_operand" "d,RT")))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_ZARCH"
- "@
- slgfr\t%0,%2
- slgf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_c_E1,z10_super_E1")])
-
-(define_insn "*subdi3_zero"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (zero_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "@
- slgfr\t%0,%2
- slgf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super_c_E1,z10_super_E1")])
-
-(define_insn_and_split "*subdi3_31z"
- [(set (match_operand:DI 0 "register_operand" "=&d")
- (minus:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (reg:CCL2 CC_REGNUM)
- (compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
- (parallel
- [(set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
- (gtu:SI (reg:CCL2 CC_REGNUM) (const_int 0))))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[3] = operand_subword (operands[0], 0, 0, DImode);
- operands[4] = operand_subword (operands[1], 0, 0, DImode);
- operands[5] = operand_subword (operands[2], 0, 0, DImode);
- operands[6] = operand_subword (operands[0], 1, 0, DImode);
- operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);")
-
-(define_insn_and_split "*subdi3_31"
- [(set (match_operand:DI 0 "register_operand" "=&d")
- (minus:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 3) (minus:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (reg:CCL2 CC_REGNUM)
- (compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
- (match_dup 7)))
- (set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
- (set (pc)
- (if_then_else (gtu (reg:CCL2 CC_REGNUM) (const_int 0))
- (pc)
- (label_ref (match_dup 9))))
- (parallel
- [(set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))
- (clobber (reg:CC CC_REGNUM))])
- (match_dup 9)]
- "operands[3] = operand_subword (operands[0], 0, 0, DImode);
- operands[4] = operand_subword (operands[1], 0, 0, DImode);
- operands[5] = operand_subword (operands[2], 0, 0, DImode);
- operands[6] = operand_subword (operands[0], 1, 0, DImode);
- operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);
- operands[9] = gen_label_rtx ();")
-
-;
-; subsi3 instruction pattern(s).
-;
-
-(define_expand "subsi3"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "")
-
-(define_insn "*subsi3_sign"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (minus:SI (match_operand:SI 1 "register_operand" "0,0")
- (sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- sh\t%0,%2
- shy\t%0,%2"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "z196prop" "z196_cracked,z196_cracked")])
-
-;
-; sub(di|si)3 instruction pattern(s).
-;
-
-; sr, s, sy, sgr, sg, srk, sgrk
-(define_insn "*sub<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d")
- (minus:GPR (match_operand:GPR 1 "register_operand" "0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T") ) )
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- s<g>r\t%0,%2
- s<g>rk\t%0,%1,%2
- s<g>\t%0,%2
- s<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")])
-
-; slr, sl, sly, slgr, slg, slrk, slgrk
-(define_insn "*sub<mode>3_borrow_cc"
- [(set (reg CC_REGNUM)
- (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T"))
- (match_dup 1)))
- (set (match_operand:GPR 0 "register_operand" "=d,d,d,d")
- (minus:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL2mode)"
- "@
- sl<g>r\t%0,%2
- sl<g>rk\t%0,%1,%2
- sl<g>\t%0,%2
- sl<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")])
-
-; slr, sl, sly, slgr, slg, slrk, slgrk
-(define_insn "*sub<mode>3_borrow_cconly"
- [(set (reg CC_REGNUM)
- (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T"))
- (match_dup 1)))
- (clobber (match_scratch:GPR 0 "=d,d,d,d"))]
- "s390_match_ccmode (insn, CCL2mode)"
- "@
- sl<g>r\t%0,%2
- sl<g>rk\t%0,%1,%2
- sl<g>\t%0,%2
- sl<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")])
-
-; slr, sl, sly, slgr, slg, slrk, slgrk
-(define_insn "*sub<mode>3_cc"
- [(set (reg CC_REGNUM)
- (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T"))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d,d,d")
- (minus:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCLmode)"
- "@
- sl<g>r\t%0,%2
- sl<g>rk\t%0,%1,%2
- sl<g>\t%0,%2
- sl<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")])
-
-; slr, sl, sly, slgr, slg, slrk, slgrk
-(define_insn "*sub<mode>3_cc2"
- [(set (reg CC_REGNUM)
- (compare (match_operand:GPR 1 "register_operand" "0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T")))
- (set (match_operand:GPR 0 "register_operand" "=d,d,d,d")
- (minus:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL3mode)"
- "@
- sl<g>r\t%0,%2
- sl<g>rk\t%0,%1,%2
- sl<g>\t%0,%2
- sl<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")])
-
-; slr, sl, sly, slgr, slg, slrk, slgrk
-(define_insn "*sub<mode>3_cconly"
- [(set (reg CC_REGNUM)
- (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T"))
- (const_int 0)))
- (clobber (match_scratch:GPR 0 "=d,d,d,d"))]
- "s390_match_ccmode (insn, CCLmode)"
- "@
- sl<g>r\t%0,%2
- sl<g>rk\t%0,%1,%2
- sl<g>\t%0,%2
- sl<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")])
-
-
-; slr, sl, sly, slgr, slg, slrk, slgrk
-(define_insn "*sub<mode>3_cconly2"
- [(set (reg CC_REGNUM)
- (compare (match_operand:GPR 1 "register_operand" "0,d,0,0")
- (match_operand:GPR 2 "general_operand" "d,d,R,T")))
- (clobber (match_scratch:GPR 0 "=d,d,d,d"))]
- "s390_match_ccmode (insn, CCL3mode)"
- "@
- sl<g>r\t%0,%2
- sl<g>rk\t%0,%1,%2
- sl<g>\t%0,%2
- sl<y>\t%0,%2"
- [(set_attr "op_type" "RR<E>,RRF,RX<Y>,RXY")
- (set_attr "cpu_facility" "*,z196,*,*")
- (set_attr "z10prop" "z10_super_c_E1,*,z10_super_E1,z10_super_E1")])
-
-
-;
-; sub(tf|df|sf|td|dd)3 instruction pattern(s).
-;
-
-; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
-(define_insn "sub<mode>3"
- [(set (match_operand:FP 0 "register_operand" "=f, f")
- (minus:FP (match_operand:FP 1 "register_operand" "<f0>,0")
- (match_operand:FP 2 "general_operand" "f,<Rf>")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_FLOAT"
- "@
- s<xde><bt>r\t%0,<op1>%2
- s<xde>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fsimp<mode>")])
-
-; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
-(define_insn "*sub<mode>3_cc"
- [(set (reg CC_REGNUM)
- (compare (minus:FP (match_operand:FP 1 "nonimmediate_operand" "<f0>,0")
- (match_operand:FP 2 "general_operand" "f,<Rf>"))
- (match_operand:FP 3 "const0_operand" "")))
- (set (match_operand:FP 0 "register_operand" "=f,f")
- (minus:FP (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "@
- s<xde><bt>r\t%0,<op1>%2
- s<xde>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fsimp<mode>")])
-
-; sxbr, sdbr, sebr, sdb, seb, sxtr, sdtr
-(define_insn "*sub<mode>3_cconly"
- [(set (reg CC_REGNUM)
- (compare (minus:FP (match_operand:FP 1 "nonimmediate_operand" "<f0>,0")
- (match_operand:FP 2 "general_operand" "f,<Rf>"))
- (match_operand:FP 3 "const0_operand" "")))
- (clobber (match_scratch:FP 0 "=f,f"))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "@
- s<xde><bt>r\t%0,<op1>%2
- s<xde>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fsimp<mode>")])
-
-
-;;
-;;- Conditional add/subtract instructions.
-;;
-
-;
-; add(di|si)cc instruction pattern(s).
-;
-
-; the following 4 patterns are used when the result of an add with
-; carry is checked for an overflow condition
-
-; op1 + op2 + c < op1
-
-; alcr, alc, alcgr, alcg
-(define_insn "*add<mode>3_alc_carry1_cc"
- [(set (reg CC_REGNUM)
- (compare
- (plus:GPR (plus:GPR (match_operand:GPR 3 "s390_alc_comparison" "")
- (match_operand:GPR 1 "nonimmediate_operand" "%0,0"))
- (match_operand:GPR 2 "general_operand" "d,RT"))
- (match_dup 1)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
- (plus:GPR (plus:GPR (match_dup 3) (match_dup 1)) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
- "@
- alc<g>r\t%0,%2
- alc<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z196prop" "z196_alone,z196_alone")])
-
-; alcr, alc, alcgr, alcg
-(define_insn "*add<mode>3_alc_carry1_cconly"
- [(set (reg CC_REGNUM)
- (compare
- (plus:GPR (plus:GPR (match_operand:GPR 3 "s390_alc_comparison" "")
- (match_operand:GPR 1 "nonimmediate_operand" "%0,0"))
- (match_operand:GPR 2 "general_operand" "d,RT"))
- (match_dup 1)))
- (clobber (match_scratch:GPR 0 "=d,d"))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
- "@
- alc<g>r\t%0,%2
- alc<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z196prop" "z196_alone,z196_alone")])
-
-; op1 + op2 + c < op2
-
-; alcr, alc, alcgr, alcg
-(define_insn "*add<mode>3_alc_carry2_cc"
- [(set (reg CC_REGNUM)
- (compare
- (plus:GPR (plus:GPR (match_operand:GPR 3 "s390_alc_comparison" "")
- (match_operand:GPR 1 "nonimmediate_operand" "%0,0"))
- (match_operand:GPR 2 "general_operand" "d,RT"))
- (match_dup 2)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
- (plus:GPR (plus:GPR (match_dup 3) (match_dup 1)) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
- "@
- alc<g>r\t%0,%2
- alc<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-; alcr, alc, alcgr, alcg
-(define_insn "*add<mode>3_alc_carry2_cconly"
- [(set (reg CC_REGNUM)
- (compare
- (plus:GPR (plus:GPR (match_operand:GPR 3 "s390_alc_comparison" "")
- (match_operand:GPR 1 "nonimmediate_operand" "%0,0"))
- (match_operand:GPR 2 "general_operand" "d,RT"))
- (match_dup 2)))
- (clobber (match_scratch:GPR 0 "=d,d"))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_CPU_ZARCH"
- "@
- alc<g>r\t%0,%2
- alc<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-; alcr, alc, alcgr, alcg
-(define_insn "*add<mode>3_alc_cc"
- [(set (reg CC_REGNUM)
- (compare
- (plus:GPR (plus:GPR (match_operand:GPR 3 "s390_alc_comparison" "")
- (match_operand:GPR 1 "nonimmediate_operand" "%0,0"))
- (match_operand:GPR 2 "general_operand" "d,RT"))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
- (plus:GPR (plus:GPR (match_dup 3) (match_dup 1)) (match_dup 2)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
- "@
- alc<g>r\t%0,%2
- alc<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-; alcr, alc, alcgr, alcg
-(define_insn "*add<mode>3_alc"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (plus:GPR (plus:GPR (match_operand:GPR 3 "s390_alc_comparison" "")
- (match_operand:GPR 1 "nonimmediate_operand" "%0,0"))
- (match_operand:GPR 2 "general_operand" "d,RT")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
- "@
- alc<g>r\t%0,%2
- alc<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-; slbr, slb, slbgr, slbg
-(define_insn "*sub<mode>3_slb_cc"
- [(set (reg CC_REGNUM)
- (compare
- (minus:GPR (minus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0")
- (match_operand:GPR 2 "general_operand" "d,RT"))
- (match_operand:GPR 3 "s390_slb_comparison" ""))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
- (minus:GPR (minus:GPR (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
- "@
- slb<g>r\t%0,%2
- slb<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_c,*")])
-
-; slbr, slb, slbgr, slbg
-(define_insn "*sub<mode>3_slb"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (minus:GPR (minus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0")
- (match_operand:GPR 2 "general_operand" "d,RT"))
- (match_operand:GPR 3 "s390_slb_comparison" "")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
- "@
- slb<g>r\t%0,%2
- slb<g>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_c,*")])
-
-(define_expand "add<mode>cc"
- [(match_operand:GPR 0 "register_operand" "")
- (match_operand 1 "comparison_operator" "")
- (match_operand:GPR 2 "register_operand" "")
- (match_operand:GPR 3 "const_int_operand" "")]
- "TARGET_CPU_ZARCH"
- "if (!s390_expand_addcc (GET_CODE (operands[1]),
- XEXP (operands[1], 0), XEXP (operands[1], 1),
- operands[0], operands[2],
- operands[3])) FAIL; DONE;")
-
-;
-; scond instruction pattern(s).
-;
-
-(define_insn_and_split "*scond<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=&d")
- (match_operand:GPR 1 "s390_alc_comparison" ""))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (const_int 0))
- (parallel
- [(set (match_dup 0) (plus:GPR (plus:GPR (match_dup 1) (match_dup 0))
- (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))])]
- "")
-
-(define_insn_and_split "*scond<mode>_neg"
- [(set (match_operand:GPR 0 "register_operand" "=&d")
- (match_operand:GPR 1 "s390_slb_comparison" ""))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
- "#"
- "&& reload_completed"
- [(set (match_dup 0) (const_int 0))
- (parallel
- [(set (match_dup 0) (minus:GPR (minus:GPR (match_dup 0) (match_dup 0))
- (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_dup 0) (neg:GPR (match_dup 0)))
- (clobber (reg:CC CC_REGNUM))])]
- "")
-
-
-(define_expand "cstore<mode>4"
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operator:SI 1 "s390_scond_operator"
- [(match_operand:GPR 2 "register_operand" "")
- (match_operand:GPR 3 "general_operand" "")]))]
- "TARGET_CPU_ZARCH"
- "if (!s390_expand_addcc (GET_CODE (operands[1]), operands[2], operands[3],
- operands[0], const0_rtx, const1_rtx)) FAIL; DONE;")
-
-(define_expand "cstorecc4"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (match_operator:SI 1 "s390_eqne_operator"
- [(match_operand:CCZ1 2 "register_operand")
- (match_operand 3 "const0_operand")]))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "emit_insn (gen_sne (operands[0], operands[2]));
- if (GET_CODE (operands[1]) == EQ)
- emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx));
- DONE;")
-
-(define_insn_and_split "sne"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (ne:SI (match_operand:CCZ1 1 "register_operand" "0")
- (const_int 0)))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "#"
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 28)))
- (clobber (reg:CC CC_REGNUM))])])
-
-
-;;
-;; - Conditional move instructions (introduced with z196)
-;;
-
-(define_expand "mov<mode>cc"
- [(set (match_operand:GPR 0 "nonimmediate_operand" "")
- (if_then_else:GPR (match_operand 1 "comparison_operator" "")
- (match_operand:GPR 2 "nonimmediate_operand" "")
- (match_operand:GPR 3 "nonimmediate_operand" "")))]
- "TARGET_Z196"
- "operands[1] = s390_emit_compare (GET_CODE (operands[1]),
- XEXP (operands[1], 0), XEXP (operands[1], 1));")
-
-; locr, loc, stoc, locgr, locg, stocg
-(define_insn_and_split "*mov<mode>cc"
- [(set (match_operand:GPR 0 "nonimmediate_operand" "=d,d, d, d,QS,QS,&d")
- (if_then_else:GPR
- (match_operator 1 "s390_comparison"
- [(match_operand 2 "cc_reg_operand" " c,c, c, c, c, c, c")
- (const_int 0)])
- (match_operand:GPR 3 "nonimmediate_operand" " d,0,QS, 0, d, 0,QS")
- (match_operand:GPR 4 "nonimmediate_operand" " 0,d, 0,QS, 0, d,QS")))]
- "TARGET_Z196"
- "@
- loc<g>r%C1\t%0,%3
- loc<g>r%D1\t%0,%4
- loc<g>%C1\t%0,%3
- loc<g>%D1\t%0,%4
- stoc<g>%C1\t%3,%0
- stoc<g>%D1\t%4,%0
- #"
- "&& reload_completed
- && MEM_P (operands[3]) && MEM_P (operands[4])"
- [(set (match_dup 0)
- (if_then_else:GPR
- (match_op_dup 1 [(match_dup 2) (const_int 0)])
- (match_dup 3)
- (match_dup 0)))
- (set (match_dup 0)
- (if_then_else:GPR
- (match_op_dup 1 [(match_dup 2) (const_int 0)])
- (match_dup 0)
- (match_dup 4)))]
- ""
- [(set_attr "op_type" "RRF,RRF,RSY,RSY,RSY,RSY,*")])
-
-;;
-;;- Multiply instructions.
-;;
-
-;
-; muldi3 instruction pattern(s).
-;
-
-(define_insn "*muldi3_sign"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (mult:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,RT"))
- (match_operand:DI 1 "register_operand" "0,0")))]
- "TARGET_ZARCH"
- "@
- msgfr\t%0,%2
- msgf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "imuldi")])
-
-(define_insn "muldi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d,d")
- (mult:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0")
- (match_operand:DI 2 "general_operand" "d,K,RT,Os")))]
- "TARGET_ZARCH"
- "@
- msgr\t%0,%2
- mghi\t%0,%h2
- msg\t%0,%2
- msgfi\t%0,%2"
- [(set_attr "op_type" "RRE,RI,RXY,RIL")
- (set_attr "type" "imuldi")
- (set_attr "cpu_facility" "*,*,*,z10")])
-
-;
-; mulsi3 instruction pattern(s).
-;
-
-(define_insn "*mulsi3_sign"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (mult:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))
- (match_operand:SI 1 "register_operand" "0,0")))]
- ""
- "@
- mh\t%0,%2
- mhy\t%0,%2"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "type" "imulhi")
- (set_attr "cpu_facility" "*,z10")])
-
-(define_insn "mulsi3"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
- (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0")
- (match_operand:SI 2 "general_operand" "d,K,R,T,Os")))]
- ""
- "@
- msr\t%0,%2
- mhi\t%0,%h2
- ms\t%0,%2
- msy\t%0,%2
- msfi\t%0,%2"
- [(set_attr "op_type" "RRE,RI,RX,RXY,RIL")
- (set_attr "type" "imulsi,imulhi,imulsi,imulsi,imulsi")
- (set_attr "cpu_facility" "*,*,*,*,z10")])
-
-;
-; mulsidi3 instruction pattern(s).
-;
-
-(define_insn "mulsidi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (mult:DI (sign_extend:DI
- (match_operand:SI 1 "register_operand" "%0,0,0"))
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,R,T"))))]
- "!TARGET_ZARCH"
- "@
- mr\t%0,%2
- m\t%0,%2
- mfy\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")
- (set_attr "type" "imulsi")
- (set_attr "cpu_facility" "*,*,z10")])
-
-;
-; umul instruction pattern(s).
-;
-
-; mlr, ml, mlgr, mlg
-(define_insn "umul<dwh><mode>3"
- [(set (match_operand:DW 0 "register_operand" "=d, d")
- (mult:DW (zero_extend:DW
- (match_operand:<DWH> 1 "register_operand" "%0, 0"))
- (zero_extend:DW
- (match_operand:<DWH> 2 "nonimmediate_operand" " d,RT"))))]
- "TARGET_CPU_ZARCH"
- "@
- ml<tg>r\t%0,%2
- ml<tg>\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "imul<dwh>")])
-
-;
-; mul(tf|df|sf|td|dd)3 instruction pattern(s).
-;
-
-; mxbr, mdbr, meebr, mxb, mxb, meeb, mdtr, mxtr
-(define_insn "mul<mode>3"
- [(set (match_operand:FP 0 "register_operand" "=f,f")
- (mult:FP (match_operand:FP 1 "nonimmediate_operand" "%<f0>,0")
- (match_operand:FP 2 "general_operand" "f,<Rf>")))]
- "TARGET_HARD_FLOAT"
- "@
- m<xdee><bt>r\t%0,<op1>%2
- m<xdee>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fmul<mode>")])
-
-; madbr, maebr, maxb, madb, maeb
-(define_insn "fma<mode>4"
- [(set (match_operand:DSF 0 "register_operand" "=f,f")
- (fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f")
- (match_operand:DSF 2 "nonimmediate_operand" "f,R")
- (match_operand:DSF 3 "register_operand" "0,0")))]
- "TARGET_HARD_FLOAT"
- "@
- ma<xde>br\t%0,%1,%2
- ma<xde>b\t%0,%1,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmadd<mode>")])
-
-; msxbr, msdbr, msebr, msxb, msdb, mseb
-(define_insn "fms<mode>4"
- [(set (match_operand:DSF 0 "register_operand" "=f,f")
- (fma:DSF (match_operand:DSF 1 "nonimmediate_operand" "%f,f")
- (match_operand:DSF 2 "nonimmediate_operand" "f,R")
- (neg:DSF (match_operand:DSF 3 "register_operand" "0,0"))))]
- "TARGET_HARD_FLOAT"
- "@
- ms<xde>br\t%0,%1,%2
- ms<xde>b\t%0,%1,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmadd<mode>")])
-
-;;
-;;- Divide and modulo instructions.
-;;
-
-;
-; divmoddi4 instruction pattern(s).
-;
-
-(define_expand "divmoddi4"
- [(parallel [(set (match_operand:DI 0 "general_operand" "")
- (div:DI (match_operand:DI 1 "register_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_ZARCH"
-{
- rtx insn, div_equal, mod_equal;
-
- div_equal = gen_rtx_DIV (DImode, operands[1], operands[2]);
- mod_equal = gen_rtx_MOD (DImode, operands[1], operands[2]);
-
- operands[4] = gen_reg_rtx(TImode);
- emit_insn (gen_divmodtidi3 (operands[4], operands[1], operands[2]));
-
- insn = emit_move_insn (operands[0], gen_lowpart (DImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, div_equal);
-
- insn = emit_move_insn (operands[3], gen_highpart (DImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, mod_equal);
-
- DONE;
-})
-
-(define_insn "divmodtidi3"
- [(set (match_operand:TI 0 "register_operand" "=d,d")
- (ior:TI
- (ashift:TI
- (zero_extend:TI
- (mod:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,RT")))
- (const_int 64))
- (zero_extend:TI (div:DI (match_dup 1) (match_dup 2)))))]
- "TARGET_ZARCH"
- "@
- dsgr\t%0,%2
- dsg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "idiv")])
-
-(define_insn "divmodtisi3"
- [(set (match_operand:TI 0 "register_operand" "=d,d")
- (ior:TI
- (ashift:TI
- (zero_extend:TI
- (mod:DI (match_operand:DI 1 "register_operand" "0,0")
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,RT"))))
- (const_int 64))
- (zero_extend:TI
- (div:DI (match_dup 1) (sign_extend:DI (match_dup 2))))))]
- "TARGET_ZARCH"
- "@
- dsgfr\t%0,%2
- dsgf\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "idiv")])
-
-;
-; udivmoddi4 instruction pattern(s).
-;
-
-(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_ZARCH"
-{
- 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_ASHIFT (TImode,
- gen_rtx_ZERO_EXTEND (TImode, mod_equal),
- GEN_INT (64)),
- gen_rtx_ZERO_EXTEND (TImode, div_equal));
-
- operands[4] = gen_reg_rtx(TImode);
- emit_clobber (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]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0], gen_lowpart (DImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, div_equal);
-
- insn = emit_move_insn (operands[3], gen_highpart (DImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, mod_equal);
-
- DONE;
-})
-
-(define_insn "udivmodtidi3"
- [(set (match_operand:TI 0 "register_operand" "=d,d")
- (ior:TI
- (ashift:TI
- (zero_extend:TI
- (truncate:DI
- (umod:TI (match_operand:TI 1 "register_operand" "0,0")
- (zero_extend:TI
- (match_operand:DI 2 "nonimmediate_operand" "d,RT")))))
- (const_int 64))
- (zero_extend:TI
- (truncate:DI
- (udiv:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))))]
- "TARGET_ZARCH"
- "@
- dlgr\t%0,%2
- dlg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "idiv")])
-
-;
-; divmodsi4 instruction pattern(s).
-;
-
-(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_ZARCH"
-{
- 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_ASHIFT (DImode,
- gen_rtx_ZERO_EXTEND (DImode, mod_equal),
- GEN_INT (32)),
- gen_rtx_ZERO_EXTEND (DImode, div_equal));
-
- 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]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0], gen_lowpart (SImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, div_equal);
-
- insn = emit_move_insn (operands[3], gen_highpart (SImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, mod_equal);
-
- DONE;
-})
-
-(define_insn "divmoddisi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (ior:DI
- (ashift:DI
- (zero_extend:DI
- (truncate:SI
- (mod:DI (match_operand:DI 1 "register_operand" "0,0")
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,R")))))
- (const_int 32))
- (zero_extend:DI
- (truncate:SI
- (div:DI (match_dup 1) (sign_extend:DI (match_dup 2)))))))]
- "!TARGET_ZARCH"
- "@
- dr\t%0,%2
- d\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "idiv")])
-
-;
-; udivsi3 and umodsi3 instruction pattern(s).
-;
-
-(define_expand "udivmodsi4"
- [(parallel [(set (match_operand:SI 0 "general_operand" "")
- (udiv:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "nonimmediate_operand" "")))
- (set (match_operand:SI 3 "general_operand" "")
- (umod:SI (match_dup 1) (match_dup 2)))])
- (clobber (match_dup 4))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
-{
- rtx insn, div_equal, mod_equal, equal;
-
- div_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
- mod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
- equal = gen_rtx_IOR (DImode,
- gen_rtx_ASHIFT (DImode,
- gen_rtx_ZERO_EXTEND (DImode, mod_equal),
- GEN_INT (32)),
- gen_rtx_ZERO_EXTEND (DImode, div_equal));
-
- operands[4] = gen_reg_rtx(DImode);
- emit_clobber (operands[4]);
- emit_move_insn (gen_lowpart (SImode, operands[4]), operands[1]);
- emit_move_insn (gen_highpart (SImode, operands[4]), const0_rtx);
-
- insn = emit_insn (gen_udivmoddisi3 (operands[4], operands[4], operands[2]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0], gen_lowpart (SImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, div_equal);
-
- insn = emit_move_insn (operands[3], gen_highpart (SImode, operands[4]));
- set_unique_reg_note (insn, REG_EQUAL, mod_equal);
-
- DONE;
-})
-
-(define_insn "udivmoddisi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (ior:DI
- (ashift:DI
- (zero_extend:DI
- (truncate:SI
- (umod:DI (match_operand:DI 1 "register_operand" "0,0")
- (zero_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,RT")))))
- (const_int 32))
- (zero_extend:DI
- (truncate:SI
- (udiv:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
- "@
- dlr\t%0,%2
- dl\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "idiv")])
-
-(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" "")))
- (clobber (match_dup 3))]
- "!TARGET_ZARCH && !TARGET_CPU_ZARCH"
-{
- 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_ASHIFT (DImode,
- gen_rtx_ZERO_EXTEND (DImode, umod_equal),
- GEN_INT (32)),
- gen_rtx_ZERO_EXTEND (DImode, udiv_equal));
-
- operands[3] = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[2]))
- {
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
- {
- rtx label1 = gen_label_rtx ();
-
- operands[1] = make_safe_from (operands[1], operands[0]);
- emit_move_insn (operands[0], const0_rtx);
- emit_cmp_and_jump_insns (operands[1], operands[2], LT, NULL_RTX,
- SImode, 1, label1);
- emit_move_insn (operands[0], const1_rtx);
- emit_label (label1);
- }
- else
- {
- 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]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_lowpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, udiv_equal);
- }
- }
- else
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- 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 (operands[0], const0_rtx);
- emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX,
- SImode, 1, label3);
- emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX,
- SImode, 0, label2);
- emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX,
- SImode, 0, label1);
- emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
- insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
- operands[2]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_lowpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, udiv_equal);
-
- emit_jump (label3);
- emit_label (label1);
- emit_move_insn (operands[0], operands[1]);
- emit_jump (label3);
- emit_label (label2);
- emit_move_insn (operands[0], const1_rtx);
- emit_label (label3);
- }
- 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" "")))
- (clobber (match_dup 3))]
- "!TARGET_ZARCH && !TARGET_CPU_ZARCH"
-{
- 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_ASHIFT (DImode,
- gen_rtx_ZERO_EXTEND (DImode, umod_equal),
- GEN_INT (32)),
- gen_rtx_ZERO_EXTEND (DImode, udiv_equal));
-
- operands[3] = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[2]))
- {
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) <= 0)
- {
- rtx label1 = gen_label_rtx ();
-
- operands[1] = make_safe_from (operands[1], operands[0]);
- emit_move_insn (operands[0], operands[1]);
- emit_cmp_and_jump_insns (operands[0], operands[2], LT, NULL_RTX,
- SImode, 1, label1);
- 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_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]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_highpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, umod_equal);
- }
- }
- else
- {
- rtx label1 = gen_label_rtx ();
- rtx label2 = gen_label_rtx ();
- 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(operands[0], operands[1]);
- emit_cmp_and_jump_insns (operands[2], operands[1], GT, NULL_RTX,
- SImode, 1, label3);
- emit_cmp_and_jump_insns (operands[2], const0_rtx, LT, NULL_RTX,
- SImode, 0, label2);
- emit_cmp_and_jump_insns (operands[2], const1_rtx, EQ, NULL_RTX,
- SImode, 0, label1);
- emit_insn (gen_zero_extendsidi2 (operands[3], operands[1]));
- insn = emit_insn (gen_divmoddisi3 (operands[3], operands[3],
- operands[2]));
- set_unique_reg_note (insn, REG_EQUAL, equal);
-
- insn = emit_move_insn (operands[0],
- gen_highpart (SImode, operands[3]));
- set_unique_reg_note (insn, REG_EQUAL, umod_equal);
-
- emit_jump (label3);
- emit_label (label1);
- emit_move_insn (operands[0], const0_rtx);
- emit_jump (label3);
- emit_label (label2);
- emit_insn (gen_subsi3 (operands[0], operands[0], operands[2]));
- emit_label (label3);
- }
- DONE;
-})
-
-;
-; div(df|sf)3 instruction pattern(s).
-;
-
-; dxbr, ddbr, debr, dxb, ddb, deb, ddtr, dxtr
-(define_insn "div<mode>3"
- [(set (match_operand:FP 0 "register_operand" "=f,f")
- (div:FP (match_operand:FP 1 "register_operand" "<f0>,0")
- (match_operand:FP 2 "general_operand" "f,<Rf>")))]
- "TARGET_HARD_FLOAT"
- "@
- d<xde><bt>r\t%0,<op1>%2
- d<xde>b\t%0,%2"
- [(set_attr "op_type" "<RRer>,RXE")
- (set_attr "type" "fdiv<mode>")])
-
-
-;;
-;;- And instructions.
-;;
-
-(define_expand "and<mode>3"
- [(set (match_operand:INT 0 "nonimmediate_operand" "")
- (and:INT (match_operand:INT 1 "nonimmediate_operand" "")
- (match_operand:INT 2 "general_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "s390_expand_logical_operator (AND, <MODE>mode, operands); DONE;")
-
-;
-; anddi3 instruction pattern(s).
-;
-
-(define_insn "*anddi3_cc"
- [(set (reg CC_REGNUM)
- (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d, 0")
- (match_operand:DI 2 "general_operand" " d,d,RT"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d, d")
- (and:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_ZARCH"
- "@
- ngr\t%0,%2
- ngrk\t%0,%1,%2
- ng\t%0,%2"
- [(set_attr "op_type" "RRE,RRF,RXY")
- (set_attr "cpu_facility" "*,z196,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1")])
-
-(define_insn "*anddi3_cconly"
- [(set (reg CC_REGNUM)
- (compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d, 0")
- (match_operand:DI 2 "general_operand" " d,d,RT"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d,d, d"))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_ZARCH
- /* Do not steal TM patterns. */
- && s390_single_part (operands[2], DImode, HImode, 0) < 0"
- "@
- ngr\t%0,%2
- ngrk\t%0,%1,%2
- ng\t%0,%2"
- [(set_attr "op_type" "RRE,RRF,RXY")
- (set_attr "cpu_facility" "*,z196,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1")])
-
-(define_insn "*anddi3"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=d,d, d, d, d, d, d, d,d,d, d, AQ,Q")
- (and:DI (match_operand:DI 1 "nonimmediate_operand"
- "%d,o, 0, 0, 0, 0, 0, 0,0,d, 0, 0,0")
- (match_operand:DI 2 "general_operand"
- "M, M,N0HDF,N1HDF,N2HDF,N3HDF,N0SDF,N1SDF,d,d,RT,NxQDF,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- #
- #
- nihh\t%0,%j2
- nihl\t%0,%j2
- nilh\t%0,%j2
- nill\t%0,%j2
- nihf\t%0,%m2
- nilf\t%0,%m2
- ngr\t%0,%2
- ngrk\t%0,%1,%2
- ng\t%0,%2
- #
- #"
- [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RIL,RIL,RRE,RRF,RXY,SI,SS")
- (set_attr "cpu_facility" "*,*,*,*,*,*,extimm,extimm,*,z196,*,*,*")
- (set_attr "z10prop" "*,
- *,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- *,
- z10_super_E1,
- *,
- *")])
-
-(define_split
- [(set (match_operand:DI 0 "s_operand" "")
- (and:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);")
-
-
-;
-; andsi3 instruction pattern(s).
-;
-
-(define_insn "*andsi3_cc"
- [(set (reg CC_REGNUM)
- (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,d,0,0")
- (match_operand:SI 2 "general_operand" "Os,d,d,R,T"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
- (and:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- nilf\t%0,%o2
- nr\t%0,%2
- nrk\t%0,%1,%2
- n\t%0,%2
- ny\t%0,%2"
- [(set_attr "op_type" "RIL,RR,RRF,RX,RXY")
- (set_attr "cpu_facility" "*,*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-(define_insn "*andsi3_cconly"
- [(set (reg CC_REGNUM)
- (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,d,0,0")
- (match_operand:SI 2 "general_operand" "Os,d,d,R,T"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d,d,d"))]
- "s390_match_ccmode(insn, CCTmode)
- /* Do not steal TM patterns. */
- && s390_single_part (operands[2], SImode, HImode, 0) < 0"
- "@
- nilf\t%0,%o2
- nr\t%0,%2
- nrk\t%0,%1,%2
- n\t%0,%2
- ny\t%0,%2"
- [(set_attr "op_type" "RIL,RR,RRF,RX,RXY")
- (set_attr "cpu_facility" "*,*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,
- z10_super_E1,z10_super_E1")])
-
-(define_insn "*andsi3_zarch"
- [(set (match_operand:SI 0 "nonimmediate_operand"
- "=d,d, d, d, d,d,d,d,d, AQ,Q")
- (and:SI (match_operand:SI 1 "nonimmediate_operand"
- "%d,o, 0, 0, 0,0,d,0,0, 0,0")
- (match_operand:SI 2 "general_operand"
- " M,M,N0HSF,N1HSF,Os,d,d,R,T,NxQSF,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- #
- #
- nilh\t%0,%j2
- nill\t%0,%j2
- nilf\t%0,%o2
- nr\t%0,%2
- nrk\t%0,%1,%2
- n\t%0,%2
- ny\t%0,%2
- #
- #"
- [(set_attr "op_type" "RRE,RXE,RI,RI,RIL,RR,RRF,RX,RXY,SI,SS")
- (set_attr "cpu_facility" "*,*,*,*,*,*,z196,*,*,*,*")
- (set_attr "z10prop" "*,
- *,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- *,
- z10_super_E1,
- z10_super_E1,
- *,
- *")])
-
-(define_insn "*andsi3_esa"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d, AQ,Q")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0, 0,0")
- (match_operand:SI 2 "general_operand" " d,R,NxQSF,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- nr\t%0,%2
- n\t%0,%2
- #
- #"
- [(set_attr "op_type" "RR,RX,SI,SS")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,*")])
-
-
-(define_split
- [(set (match_operand:SI 0 "s_operand" "")
- (and:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);")
-
-;
-; andhi3 instruction pattern(s).
-;
-
-(define_insn "*andhi3_zarch"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d, AQ,Q")
- (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,d,0, 0,0")
- (match_operand:HI 2 "general_operand" " d,d,n,NxQHF,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- nr\t%0,%2
- nrk\t%0,%1,%2
- nill\t%0,%x2
- #
- #"
- [(set_attr "op_type" "RR,RRF,RI,SI,SS")
- (set_attr "cpu_facility" "*,z196,*,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,*,*")
-])
-
-(define_insn "*andhi3_esa"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,AQ,Q")
- (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:HI 2 "general_operand" "d,NxQHF,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- nr\t%0,%2
- #
- #"
- [(set_attr "op_type" "RR,SI,SS")
- (set_attr "z10prop" "z10_super_E1,*,*")
-])
-
-(define_split
- [(set (match_operand:HI 0 "s_operand" "")
- (and:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);")
-
-;
-; andqi3 instruction pattern(s).
-;
-
-(define_insn "*andqi3_zarch"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,Q,S,Q")
- (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,d,0,0,0,0")
- (match_operand:QI 2 "general_operand" " d,d,n,n,n,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- nr\t%0,%2
- nrk\t%0,%1,%2
- nill\t%0,%b2
- ni\t%S0,%b2
- niy\t%S0,%b2
- #"
- [(set_attr "op_type" "RR,RRF,RI,SI,SIY,SS")
- (set_attr "cpu_facility" "*,z196,*,*,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,z10_super,z10_super,*")])
-
-(define_insn "*andqi3_esa"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,Q,Q")
- (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:QI 2 "general_operand" "d,n,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- nr\t%0,%2
- ni\t%S0,%b2
- #"
- [(set_attr "op_type" "RR,SI,SS")
- (set_attr "z10prop" "z10_super_E1,z10_super,*")])
-
-;
-; Block and (NC) patterns.
-;
-
-(define_insn "*nc"
- [(set (match_operand:BLK 0 "memory_operand" "=Q")
- (and:BLK (match_dup 0)
- (match_operand:BLK 1 "memory_operand" "Q")))
- (use (match_operand 2 "const_int_operand" "n"))
- (clobber (reg:CC CC_REGNUM))]
- "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
- "nc\t%O0(%2,%R0),%S1"
- [(set_attr "op_type" "SS")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_split
- [(set (match_operand 0 "memory_operand" "")
- (and (match_dup 0)
- (match_operand 1 "memory_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
- [(parallel
- [(set (match_dup 0) (and:BLK (match_dup 0) (match_dup 1)))
- (use (match_dup 2))
- (clobber (reg:CC CC_REGNUM))])]
-{
- operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
- operands[0] = adjust_address (operands[0], BLKmode, 0);
- operands[1] = adjust_address (operands[1], BLKmode, 0);
-})
-
-(define_peephole2
- [(parallel
- [(set (match_operand:BLK 0 "memory_operand" "")
- (and:BLK (match_dup 0)
- (match_operand:BLK 1 "memory_operand" "")))
- (use (match_operand 2 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_operand:BLK 3 "memory_operand" "")
- (and:BLK (match_dup 3)
- (match_operand:BLK 4 "memory_operand" "")))
- (use (match_operand 5 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_offset_p (operands[0], operands[3], operands[2])
- && s390_offset_p (operands[1], operands[4], operands[2])
- && !s390_overlap_p (operands[0], operands[1],
- INTVAL (operands[2]) + INTVAL (operands[5]))
- && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
- [(parallel
- [(set (match_dup 6) (and:BLK (match_dup 6) (match_dup 7)))
- (use (match_dup 8))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
- operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
- operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
-
-
-;;
-;;- Bit set (inclusive or) instructions.
-;;
-
-(define_expand "ior<mode>3"
- [(set (match_operand:INT 0 "nonimmediate_operand" "")
- (ior:INT (match_operand:INT 1 "nonimmediate_operand" "")
- (match_operand:INT 2 "general_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "s390_expand_logical_operator (IOR, <MODE>mode, operands); DONE;")
-
-;
-; iordi3 instruction pattern(s).
-;
-
-(define_insn "*iordi3_cc"
- [(set (reg CC_REGNUM)
- (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d, 0")
- (match_operand:DI 2 "general_operand" " d,d,RT"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d, d")
- (ior:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_ZARCH"
- "@
- ogr\t%0,%2
- ogrk\t%0,%1,%2
- og\t%0,%2"
- [(set_attr "op_type" "RRE,RRF,RXY")
- (set_attr "cpu_facility" "*,z196,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1")])
-
-(define_insn "*iordi3_cconly"
- [(set (reg CC_REGNUM)
- (compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d,0")
- (match_operand:DI 2 "general_operand" " d,d,RT"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d,d,d"))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_ZARCH"
- "@
- ogr\t%0,%2
- ogrk\t%0,%1,%2
- og\t%0,%2"
- [(set_attr "op_type" "RRE,RRF,RXY")
- (set_attr "cpu_facility" "*,z196,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1")])
-
-(define_insn "*iordi3"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=d, d, d, d, d, d,d,d, d, AQ,Q")
- (ior:DI (match_operand:DI 1 "nonimmediate_operand"
- " %0, 0, 0, 0, 0, 0,0,d, 0, 0,0")
- (match_operand:DI 2 "general_operand"
- "N0HD0,N1HD0,N2HD0,N3HD0,N0SD0,N1SD0,d,d,RT,NxQD0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- oihh\t%0,%i2
- oihl\t%0,%i2
- oilh\t%0,%i2
- oill\t%0,%i2
- oihf\t%0,%k2
- oilf\t%0,%k2
- ogr\t%0,%2
- ogrk\t%0,%1,%2
- og\t%0,%2
- #
- #"
- [(set_attr "op_type" "RI,RI,RI,RI,RIL,RIL,RRE,RRF,RXY,SI,SS")
- (set_attr "cpu_facility" "*,*,*,*,extimm,extimm,*,z196,*,*,*")
- (set_attr "z10prop" "z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- *,
- z10_super_E1,
- *,
- *")])
-
-(define_split
- [(set (match_operand:DI 0 "s_operand" "")
- (ior:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);")
-
-;
-; iorsi3 instruction pattern(s).
-;
-
-(define_insn "*iorsi3_cc"
- [(set (reg CC_REGNUM)
- (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,d,0,0")
- (match_operand:SI 2 "general_operand" "Os,d,d,R,T"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
- (ior:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- oilf\t%0,%o2
- or\t%0,%2
- ork\t%0,%1,%2
- o\t%0,%2
- oy\t%0,%2"
- [(set_attr "op_type" "RIL,RR,RRF,RX,RXY")
- (set_attr "cpu_facility" "*,*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-(define_insn "*iorsi3_cconly"
- [(set (reg CC_REGNUM)
- (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,d,0,0")
- (match_operand:SI 2 "general_operand" "Os,d,d,R,T"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d,d,d"))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- oilf\t%0,%o2
- or\t%0,%2
- ork\t%0,%1,%2
- o\t%0,%2
- oy\t%0,%2"
- [(set_attr "op_type" "RIL,RR,RRF,RX,RXY")
- (set_attr "cpu_facility" "*,*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,z10_super_E1,z10_super_E1")])
-
-(define_insn "*iorsi3_zarch"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d, d, d,d,d,d,d, AQ,Q")
- (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0, 0, 0,0,d,0,0, 0,0")
- (match_operand:SI 2 "general_operand" "N0HS0,N1HS0,Os,d,d,R,T,NxQS0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- oilh\t%0,%i2
- oill\t%0,%i2
- oilf\t%0,%o2
- or\t%0,%2
- ork\t%0,%1,%2
- o\t%0,%2
- oy\t%0,%2
- #
- #"
- [(set_attr "op_type" "RI,RI,RIL,RR,RRF,RX,RXY,SI,SS")
- (set_attr "cpu_facility" "*,*,*,*,z196,*,*,*,*")
- (set_attr "z10prop" "z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- z10_super_E1,
- *,
- z10_super_E1,
- z10_super_E1,
- *,
- *")])
-
-(define_insn "*iorsi3_esa"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,AQ,Q")
- (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,NxQS0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- or\t%0,%2
- o\t%0,%2
- #
- #"
- [(set_attr "op_type" "RR,RX,SI,SS")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,*")])
-
-(define_split
- [(set (match_operand:SI 0 "s_operand" "")
- (ior:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);")
-
-;
-; iorhi3 instruction pattern(s).
-;
-
-(define_insn "*iorhi3_zarch"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d, AQ,Q")
- (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,d,0, 0,0")
- (match_operand:HI 2 "general_operand" " d,d,n,NxQH0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- or\t%0,%2
- ork\t%0,%1,%2
- oill\t%0,%x2
- #
- #"
- [(set_attr "op_type" "RR,RRF,RI,SI,SS")
- (set_attr "cpu_facility" "*,z196,*,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,*,*")])
-
-(define_insn "*iorhi3_esa"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,AQ,Q")
- (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:HI 2 "general_operand" "d,NxQH0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- or\t%0,%2
- #
- #"
- [(set_attr "op_type" "RR,SI,SS")
- (set_attr "z10prop" "z10_super_E1,*,*")])
-
-(define_split
- [(set (match_operand:HI 0 "s_operand" "")
- (ior:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);")
-
-;
-; iorqi3 instruction pattern(s).
-;
-
-(define_insn "*iorqi3_zarch"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,Q,S,Q")
- (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,d,0,0,0,0")
- (match_operand:QI 2 "general_operand" " d,d,n,n,n,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- or\t%0,%2
- ork\t%0,%1,%2
- oill\t%0,%b2
- oi\t%S0,%b2
- oiy\t%S0,%b2
- #"
- [(set_attr "op_type" "RR,RRF,RI,SI,SIY,SS")
- (set_attr "cpu_facility" "*,z196,*,*,*,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1,
- z10_super,z10_super,*")])
-
-(define_insn "*iorqi3_esa"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,Q,Q")
- (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:QI 2 "general_operand" "d,n,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- or\t%0,%2
- oi\t%S0,%b2
- #"
- [(set_attr "op_type" "RR,SI,SS")
- (set_attr "z10prop" "z10_super_E1,z10_super,*")])
-
-;
-; Block inclusive or (OC) patterns.
-;
-
-(define_insn "*oc"
- [(set (match_operand:BLK 0 "memory_operand" "=Q")
- (ior:BLK (match_dup 0)
- (match_operand:BLK 1 "memory_operand" "Q")))
- (use (match_operand 2 "const_int_operand" "n"))
- (clobber (reg:CC CC_REGNUM))]
- "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
- "oc\t%O0(%2,%R0),%S1"
- [(set_attr "op_type" "SS")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_split
- [(set (match_operand 0 "memory_operand" "")
- (ior (match_dup 0)
- (match_operand 1 "memory_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
- [(parallel
- [(set (match_dup 0) (ior:BLK (match_dup 0) (match_dup 1)))
- (use (match_dup 2))
- (clobber (reg:CC CC_REGNUM))])]
-{
- operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
- operands[0] = adjust_address (operands[0], BLKmode, 0);
- operands[1] = adjust_address (operands[1], BLKmode, 0);
-})
-
-(define_peephole2
- [(parallel
- [(set (match_operand:BLK 0 "memory_operand" "")
- (ior:BLK (match_dup 0)
- (match_operand:BLK 1 "memory_operand" "")))
- (use (match_operand 2 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_operand:BLK 3 "memory_operand" "")
- (ior:BLK (match_dup 3)
- (match_operand:BLK 4 "memory_operand" "")))
- (use (match_operand 5 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_offset_p (operands[0], operands[3], operands[2])
- && s390_offset_p (operands[1], operands[4], operands[2])
- && !s390_overlap_p (operands[0], operands[1],
- INTVAL (operands[2]) + INTVAL (operands[5]))
- && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
- [(parallel
- [(set (match_dup 6) (ior:BLK (match_dup 6) (match_dup 7)))
- (use (match_dup 8))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
- operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
- operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
-
-
-;;
-;;- Xor instructions.
-;;
-
-(define_expand "xor<mode>3"
- [(set (match_operand:INT 0 "nonimmediate_operand" "")
- (xor:INT (match_operand:INT 1 "nonimmediate_operand" "")
- (match_operand:INT 2 "general_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "s390_expand_logical_operator (XOR, <MODE>mode, operands); DONE;")
-
-;
-; xordi3 instruction pattern(s).
-;
-
-(define_insn "*xordi3_cc"
- [(set (reg CC_REGNUM)
- (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d, 0")
- (match_operand:DI 2 "general_operand" " d,d,RT"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d, d")
- (xor:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_ZARCH"
- "@
- xgr\t%0,%2
- xgrk\t%0,%1,%2
- xg\t%0,%2"
- [(set_attr "op_type" "RRE,RRF,RXY")
- (set_attr "cpu_facility" "*,z196,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1")])
-
-(define_insn "*xordi3_cconly"
- [(set (reg CC_REGNUM)
- (compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,d, 0")
- (match_operand:DI 2 "general_operand" " d,d,RT"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d,d, d"))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_ZARCH"
- "@
- xgr\t%0,%2
- xgrk\t%0,%1,%2
- xg\t%0,%2"
- [(set_attr "op_type" "RRE,RRF,RXY")
- (set_attr "cpu_facility" "*,z196,*")
- (set_attr "z10prop" "z10_super_E1,*,z10_super_E1")])
-
-(define_insn "*xordi3"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d, d,d,d, d, AQ,Q")
- (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0, 0,0,d, 0, 0,0")
- (match_operand:DI 2 "general_operand" "N0SD0,N1SD0,d,d,RT,NxQD0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
- "@
- xihf\t%0,%k2
- xilf\t%0,%k2
- xgr\t%0,%2
- xgrk\t%0,%1,%2
- xg\t%0,%2
- #
- #"
- [(set_attr "op_type" "RIL,RIL,RRE,RRF,RXY,SI,SS")
- (set_attr "cpu_facility" "extimm,extimm,*,z196,*,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,z10_super_E1,
- *,z10_super_E1,*,*")])
-
-(define_split
- [(set (match_operand:DI 0 "s_operand" "")
- (xor:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);")
-
-;
-; xorsi3 instruction pattern(s).
-;
-
-(define_insn "*xorsi3_cc"
- [(set (reg CC_REGNUM)
- (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,d,0,0")
- (match_operand:SI 2 "general_operand" "Os,d,d,R,T"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
- (xor:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- xilf\t%0,%o2
- xr\t%0,%2
- xrk\t%0,%1,%2
- x\t%0,%2
- xy\t%0,%2"
- [(set_attr "op_type" "RIL,RR,RRF,RX,RXY")
- (set_attr "cpu_facility" "*,*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,
- z10_super_E1,z10_super_E1")])
-
-(define_insn "*xorsi3_cconly"
- [(set (reg CC_REGNUM)
- (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,d,0,0")
- (match_operand:SI 2 "general_operand" "Os,d,d,R,T"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d,d,d"))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- xilf\t%0,%o2
- xr\t%0,%2
- xrk\t%0,%1,%2
- x\t%0,%2
- xy\t%0,%2"
- [(set_attr "op_type" "RIL,RR,RRF,RX,RXY")
- (set_attr "cpu_facility" "*,*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,
- z10_super_E1,z10_super_E1")])
-
-(define_insn "*xorsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d, AQ,Q")
- (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,d,0,0, 0,0")
- (match_operand:SI 2 "general_operand" "Os,d,d,R,T,NxQS0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "s390_logical_operator_ok_p (operands)"
- "@
- xilf\t%0,%o2
- xr\t%0,%2
- xrk\t%0,%1,%2
- x\t%0,%2
- xy\t%0,%2
- #
- #"
- [(set_attr "op_type" "RIL,RR,RRF,RX,RXY,SI,SS")
- (set_attr "cpu_facility" "*,*,z196,*,*,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,
- z10_super_E1,z10_super_E1,*,*")])
-
-(define_split
- [(set (match_operand:SI 0 "s_operand" "")
- (xor:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);")
-
-;
-; xorhi3 instruction pattern(s).
-;
-
-(define_insn "*xorhi3"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d, AQ,Q")
- (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,d, 0,0")
- (match_operand:HI 2 "general_operand" "Os,d,d,NxQH0,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "s390_logical_operator_ok_p (operands)"
- "@
- xilf\t%0,%x2
- xr\t%0,%2
- xrk\t%0,%1,%2
- #
- #"
- [(set_attr "op_type" "RIL,RR,RRF,SI,SS")
- (set_attr "cpu_facility" "*,*,z196,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,*,*")])
-
-(define_split
- [(set (match_operand:HI 0 "s_operand" "")
- (xor:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed"
- [(parallel
- [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1)))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);")
-
-;
-; xorqi3 instruction pattern(s).
-;
-
-(define_insn "*xorqi3"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,Q,S,Q")
- (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,d,0,0,0")
- (match_operand:QI 2 "general_operand" "Os,d,d,n,n,Q")))
- (clobber (reg:CC CC_REGNUM))]
- "s390_logical_operator_ok_p (operands)"
- "@
- xilf\t%0,%b2
- xr\t%0,%2
- xrk\t%0,%1,%2
- xi\t%S0,%b2
- xiy\t%S0,%b2
- #"
- [(set_attr "op_type" "RIL,RR,RRF,SI,SIY,SS")
- (set_attr "cpu_facility" "*,*,z196,*,*,*")
- (set_attr "z10prop" "z10_super_E1,z10_super_E1,*,z10_super,z10_super,*")])
-
-
-;
-; Block exclusive or (XC) patterns.
-;
-
-(define_insn "*xc"
- [(set (match_operand:BLK 0 "memory_operand" "=Q")
- (xor:BLK (match_dup 0)
- (match_operand:BLK 1 "memory_operand" "Q")))
- (use (match_operand 2 "const_int_operand" "n"))
- (clobber (reg:CC CC_REGNUM))]
- "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
- "xc\t%O0(%2,%R0),%S1"
- [(set_attr "op_type" "SS")])
-
-(define_split
- [(set (match_operand 0 "memory_operand" "")
- (xor (match_dup 0)
- (match_operand 1 "memory_operand" "")))
- (clobber (reg:CC CC_REGNUM))]
- "reload_completed
- && GET_MODE (operands[0]) == GET_MODE (operands[1])
- && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
- [(parallel
- [(set (match_dup 0) (xor:BLK (match_dup 0) (match_dup 1)))
- (use (match_dup 2))
- (clobber (reg:CC CC_REGNUM))])]
-{
- operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
- operands[0] = adjust_address (operands[0], BLKmode, 0);
- operands[1] = adjust_address (operands[1], BLKmode, 0);
-})
-
-(define_peephole2
- [(parallel
- [(set (match_operand:BLK 0 "memory_operand" "")
- (xor:BLK (match_dup 0)
- (match_operand:BLK 1 "memory_operand" "")))
- (use (match_operand 2 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_operand:BLK 3 "memory_operand" "")
- (xor:BLK (match_dup 3)
- (match_operand:BLK 4 "memory_operand" "")))
- (use (match_operand 5 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_offset_p (operands[0], operands[3], operands[2])
- && s390_offset_p (operands[1], operands[4], operands[2])
- && !s390_overlap_p (operands[0], operands[1],
- INTVAL (operands[2]) + INTVAL (operands[5]))
- && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
- [(parallel
- [(set (match_dup 6) (xor:BLK (match_dup 6) (match_dup 7)))
- (use (match_dup 8))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
- operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
- operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
-
-;
-; Block xor (XC) patterns with src == dest.
-;
-
-(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 CC_REGNUM))]
- "INTVAL (operands[1]) >= 1 && INTVAL (operands[1]) <= 256"
- "xc\t%O0(%1,%R0),%S0"
- [(set_attr "op_type" "SS")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_peephole2
- [(parallel
- [(set (match_operand:BLK 0 "memory_operand" "")
- (const_int 0))
- (use (match_operand 1 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (match_operand:BLK 2 "memory_operand" "")
- (const_int 0))
- (use (match_operand 3 "const_int_operand" ""))
- (clobber (reg:CC CC_REGNUM))])]
- "s390_offset_p (operands[0], operands[2], operands[1])
- && INTVAL (operands[1]) + INTVAL (operands[3]) <= 256"
- [(parallel
- [(set (match_dup 4) (const_int 0))
- (use (match_dup 5))
- (clobber (reg:CC CC_REGNUM))])]
- "operands[4] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
- operands[5] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[3]));")
-
-
-;;
-;;- Negate instructions.
-;;
-
-;
-; neg(di|si)2 instruction pattern(s).
-;
-
-(define_expand "neg<mode>2"
- [(parallel
- [(set (match_operand:DSI 0 "register_operand" "=d")
- (neg:DSI (match_operand:DSI 1 "register_operand" "d")))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "")
-
-(define_insn "*negdi2_sign_cc"
- [(set (reg CC_REGNUM)
- (compare (neg:DI (ashiftrt:DI (ashift:DI (subreg:DI
- (match_operand:SI 1 "register_operand" "d") 0)
- (const_int 32)) (const_int 32)))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (sign_extend:DI (match_dup 1))))]
- "TARGET_ZARCH && s390_match_ccmode (insn, CCAmode)"
- "lcgfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "z10prop" "z10_c")])
-
-(define_insn "*negdi2_sign"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "lcgfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "z10prop" "z10_c")])
-
-; lcr, lcgr
-(define_insn "*neg<mode>2_cc"
- [(set (reg CC_REGNUM)
- (compare (neg:GPR (match_operand:GPR 1 "register_operand" "d"))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d")
- (neg:GPR (match_dup 1)))]
- "s390_match_ccmode (insn, CCAmode)"
- "lc<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_super_c_E1")])
-
-; lcr, lcgr
-(define_insn "*neg<mode>2_cconly"
- [(set (reg CC_REGNUM)
- (compare (neg:GPR (match_operand:GPR 1 "register_operand" "d"))
- (const_int 0)))
- (clobber (match_scratch:GPR 0 "=d"))]
- "s390_match_ccmode (insn, CCAmode)"
- "lc<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_super_c_E1")])
-
-; lcr, lcgr
-(define_insn "*neg<mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (neg:GPR (match_operand:GPR 1 "register_operand" "d")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "lc<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_super_c_E1")])
-
-(define_insn_and_split "*negdi2_31"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 2) (neg:SI (match_dup 3)))
- (clobber (reg:CC CC_REGNUM))])
- (parallel
- [(set (reg:CCAP CC_REGNUM)
- (compare:CCAP (neg:SI (match_dup 5)) (const_int 0)))
- (set (match_dup 4) (neg:SI (match_dup 5)))])
- (set (pc)
- (if_then_else (ne (reg:CCAP CC_REGNUM) (const_int 0))
- (pc)
- (label_ref (match_dup 6))))
- (parallel
- [(set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
- (clobber (reg:CC CC_REGNUM))])
- (match_dup 6)]
- "operands[2] = operand_subword (operands[0], 0, 0, DImode);
- operands[3] = operand_subword (operands[1], 0, 0, DImode);
- operands[4] = operand_subword (operands[0], 1, 0, DImode);
- operands[5] = operand_subword (operands[1], 1, 0, DImode);
- operands[6] = gen_label_rtx ();")
-
-;
-; neg(df|sf)2 instruction pattern(s).
-;
-
-(define_expand "neg<mode>2"
- [(parallel
- [(set (match_operand:BFP 0 "register_operand" "=f")
- (neg:BFP (match_operand:BFP 1 "register_operand" "f")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_HARD_FLOAT"
- "")
-
-; lcxbr, lcdbr, lcebr
-(define_insn "*neg<mode>2_cc"
- [(set (reg CC_REGNUM)
- (compare (neg:BFP (match_operand:BFP 1 "register_operand" "f"))
- (match_operand:BFP 2 "const0_operand" "")))
- (set (match_operand:BFP 0 "register_operand" "=f")
- (neg:BFP (match_dup 1)))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "lc<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lcxbr, lcdbr, lcebr
-(define_insn "*neg<mode>2_cconly"
- [(set (reg CC_REGNUM)
- (compare (neg:BFP (match_operand:BFP 1 "register_operand" "f"))
- (match_operand:BFP 2 "const0_operand" "")))
- (clobber (match_scratch:BFP 0 "=f"))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "lc<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lcdfr
-(define_insn "*neg<mode>2_nocc"
- [(set (match_operand:FP 0 "register_operand" "=f")
- (neg:FP (match_operand:FP 1 "register_operand" "<fT0>")))]
- "TARGET_DFP"
- "lcdfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lcxbr, lcdbr, lcebr
-(define_insn "*neg<mode>2"
- [(set (match_operand:BFP 0 "register_operand" "=f")
- (neg:BFP (match_operand:BFP 1 "register_operand" "f")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_FLOAT"
- "lc<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-
-;;
-;;- Absolute value instructions.
-;;
-
-;
-; abs(di|si)2 instruction pattern(s).
-;
-
-(define_insn "*absdi2_sign_cc"
- [(set (reg CC_REGNUM)
- (compare (abs:DI (ashiftrt:DI (ashift:DI (subreg:DI
- (match_operand:SI 1 "register_operand" "d") 0)
- (const_int 32)) (const_int 32)))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (abs:DI (sign_extend:DI (match_dup 1))))]
- "TARGET_ZARCH && s390_match_ccmode (insn, CCAmode)"
- "lpgfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "z10prop" "z10_c")])
-
-(define_insn "*absdi2_sign"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (abs:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "lpgfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "z10prop" "z10_c")])
-
-; lpr, lpgr
-(define_insn "*abs<mode>2_cc"
- [(set (reg CC_REGNUM)
- (compare (abs:GPR (match_operand:DI 1 "register_operand" "d"))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d")
- (abs:GPR (match_dup 1)))]
- "s390_match_ccmode (insn, CCAmode)"
- "lp<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_c")])
-
-; lpr, lpgr
-(define_insn "*abs<mode>2_cconly"
- [(set (reg CC_REGNUM)
- (compare (abs:GPR (match_operand:GPR 1 "register_operand" "d"))
- (const_int 0)))
- (clobber (match_scratch:GPR 0 "=d"))]
- "s390_match_ccmode (insn, CCAmode)"
- "lp<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_c")])
-
-; lpr, lpgr
-(define_insn "abs<mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (abs:GPR (match_operand:GPR 1 "register_operand" "d")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "lp<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_c")])
-
-;
-; abs(df|sf)2 instruction pattern(s).
-;
-
-(define_expand "abs<mode>2"
- [(parallel
- [(set (match_operand:BFP 0 "register_operand" "=f")
- (abs:BFP (match_operand:BFP 1 "register_operand" "f")))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_HARD_FLOAT"
- "")
-
-; lpxbr, lpdbr, lpebr
-(define_insn "*abs<mode>2_cc"
- [(set (reg CC_REGNUM)
- (compare (abs:BFP (match_operand:BFP 1 "register_operand" "f"))
- (match_operand:BFP 2 "const0_operand" "")))
- (set (match_operand:BFP 0 "register_operand" "=f")
- (abs:BFP (match_dup 1)))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "lp<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lpxbr, lpdbr, lpebr
-(define_insn "*abs<mode>2_cconly"
- [(set (reg CC_REGNUM)
- (compare (abs:BFP (match_operand:BFP 1 "register_operand" "f"))
- (match_operand:BFP 2 "const0_operand" "")))
- (clobber (match_scratch:BFP 0 "=f"))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "lp<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lpdfr
-(define_insn "*abs<mode>2_nocc"
- [(set (match_operand:FP 0 "register_operand" "=f")
- (abs:FP (match_operand:FP 1 "register_operand" "<fT0>")))]
- "TARGET_DFP"
- "lpdfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lpxbr, lpdbr, lpebr
-(define_insn "*abs<mode>2"
- [(set (match_operand:BFP 0 "register_operand" "=f")
- (abs:BFP (match_operand:BFP 1 "register_operand" "f")))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_FLOAT"
- "lp<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-
-;;
-;;- Negated absolute value instructions
-;;
-
-;
-; Integer
-;
-
-(define_insn "*negabsdi2_sign_cc"
- [(set (reg CC_REGNUM)
- (compare (neg:DI (abs:DI (ashiftrt:DI (ashift:DI (subreg:DI
- (match_operand:SI 1 "register_operand" "d") 0)
- (const_int 32)) (const_int 32))))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (abs:DI (sign_extend:DI (match_dup 1)))))]
- "TARGET_ZARCH && s390_match_ccmode (insn, CCAmode)"
- "lngfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "z10prop" "z10_c")])
-
-(define_insn "*negabsdi2_sign"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (abs:DI (sign_extend:DI
- (match_operand:SI 1 "register_operand" "d")))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
- "lngfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "z10prop" "z10_c")])
-
-; lnr, lngr
-(define_insn "*negabs<mode>2_cc"
- [(set (reg CC_REGNUM)
- (compare (neg:GPR (abs:GPR (match_operand:GPR 1 "register_operand" "d")))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d")
- (neg:GPR (abs:GPR (match_dup 1))))]
- "s390_match_ccmode (insn, CCAmode)"
- "ln<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_c")])
-
-; lnr, lngr
-(define_insn "*negabs<mode>2_cconly"
- [(set (reg CC_REGNUM)
- (compare (neg:GPR (abs:GPR (match_operand:GPR 1 "register_operand" "d")))
- (const_int 0)))
- (clobber (match_scratch:GPR 0 "=d"))]
- "s390_match_ccmode (insn, CCAmode)"
- "ln<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_c")])
-
-; lnr, lngr
-(define_insn "*negabs<mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (neg:GPR (abs:GPR (match_operand:GPR 1 "register_operand" "d"))))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "ln<g>r\t%0,%1"
- [(set_attr "op_type" "RR<E>")
- (set_attr "z10prop" "z10_c")])
-
-;
-; Floating point
-;
-
-; lnxbr, lndbr, lnebr
-(define_insn "*negabs<mode>2_cc"
- [(set (reg CC_REGNUM)
- (compare (neg:BFP (abs:BFP (match_operand:BFP 1 "register_operand" "f")))
- (match_operand:BFP 2 "const0_operand" "")))
- (set (match_operand:BFP 0 "register_operand" "=f")
- (neg:BFP (abs:BFP (match_dup 1))))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "ln<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lnxbr, lndbr, lnebr
-(define_insn "*negabs<mode>2_cconly"
- [(set (reg CC_REGNUM)
- (compare (neg:BFP (abs:BFP (match_operand:BFP 1 "register_operand" "f")))
- (match_operand:BFP 2 "const0_operand" "")))
- (clobber (match_scratch:BFP 0 "=f"))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT"
- "ln<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lndfr
-(define_insn "*negabs<mode>2_nocc"
- [(set (match_operand:FP 0 "register_operand" "=f")
- (neg:FP (abs:FP (match_operand:BFP 1 "register_operand" "<fT0>"))))]
- "TARGET_DFP"
- "lndfr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-; lnxbr, lndbr, lnebr
-(define_insn "*negabs<mode>2"
- [(set (match_operand:BFP 0 "register_operand" "=f")
- (neg:BFP (abs:BFP (match_operand:BFP 1 "register_operand" "f"))))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_HARD_FLOAT"
- "ln<xde>br\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "fsimp<mode>")])
-
-;;
-;;- Square root instructions.
-;;
-
-;
-; sqrt(df|sf)2 instruction pattern(s).
-;
-
-; sqxbr, sqdbr, sqebr, sqdb, sqeb
-(define_insn "sqrt<mode>2"
- [(set (match_operand:BFP 0 "register_operand" "=f,f")
- (sqrt:BFP (match_operand:BFP 1 "general_operand" "f,<Rf>")))]
- "TARGET_HARD_FLOAT"
- "@
- sq<xde>br\t%0,%1
- sq<xde>b\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsqrt<mode>")])
-
-
-;;
-;;- One complement instructions.
-;;
-
-;
-; one_cmpl(di|si|hi|qi)2 instruction pattern(s).
-;
-
-(define_expand "one_cmpl<mode>2"
- [(parallel
- [(set (match_operand:INT 0 "register_operand" "")
- (xor:INT (match_operand:INT 1 "register_operand" "")
- (const_int -1)))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "")
-
-
-;;
-;; Find leftmost bit instructions.
-;;
-
-(define_expand "clzdi2"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (clz:DI (match_operand:DI 1 "register_operand" "d")))]
- "TARGET_EXTIMM && TARGET_ZARCH"
-{
- rtx insn, clz_equal;
- rtx wide_reg = gen_reg_rtx (TImode);
- rtx msb = gen_rtx_CONST_INT (DImode, (unsigned HOST_WIDE_INT) 1 << 63);
-
- clz_equal = gen_rtx_CLZ (DImode, operands[1]);
-
- emit_insn (gen_clztidi2 (wide_reg, operands[1], msb));
-
- insn = emit_move_insn (operands[0], gen_highpart (DImode, wide_reg));
- set_unique_reg_note (insn, REG_EQUAL, clz_equal);
-
- DONE;
-})
-
-(define_insn "clztidi2"
- [(set (match_operand:TI 0 "register_operand" "=d")
- (ior:TI
- (ashift:TI
- (zero_extend:TI
- (xor:DI (match_operand:DI 1 "register_operand" "d")
- (lshiftrt (match_operand:DI 2 "const_int_operand" "")
- (subreg:SI (clz:DI (match_dup 1)) 4))))
-
- (const_int 64))
- (zero_extend:TI (clz:DI (match_dup 1)))))
- (clobber (reg:CC CC_REGNUM))]
- "(unsigned HOST_WIDE_INT) INTVAL (operands[2])
- == (unsigned HOST_WIDE_INT) 1 << 63
- && TARGET_EXTIMM && TARGET_ZARCH"
- "flogr\t%0,%1"
- [(set_attr "op_type" "RRE")])
-
-
-;;
-;;- Rotate instructions.
-;;
-
-;
-; rotl(di|si)3 instruction pattern(s).
-;
-
-; rll, rllg
-(define_insn "rotl<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
- "TARGET_CPU_ZARCH"
- "rll<g>\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
- (set_attr "atype" "reg")
- (set_attr "z10prop" "z10_super_E1")])
-
-; rll, rllg
-(define_insn "*rotl<mode>3_and"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 3 "const_int_operand" "n"))))]
- "TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63"
- "rll<g>\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
- (set_attr "atype" "reg")
- (set_attr "z10prop" "z10_super_E1")])
-
-
-;;
-;;- Shift instructions.
-;;
-
-;
-; (ashl|lshr)(di|si)3 instruction pattern(s).
-; Left shifts and logical right shifts
-
-(define_expand "<shift><mode>3"
- [(set (match_operand:DSI 0 "register_operand" "")
- (SHIFT:DSI (match_operand:DSI 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
- ""
- "")
-
-; sldl, srdl
-(define_insn "*<shift>di3_31"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (SHIFT:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
- "!TARGET_ZARCH"
- "s<lr>dl\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")
- (set_attr "z196prop" "z196_cracked")])
-
-; sll, srl, sllg, srlg, sllk, srlk
-(define_insn "*<shift><mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (SHIFT:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")))]
- ""
- "@
- s<lr>l<g>\t%0,<1>%Y2
- s<lr>l<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-; sldl, srdl
-(define_insn "*<shift>di3_31_and"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (SHIFT:DI (match_operand:DI 1 "register_operand" "0")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 3 "const_int_operand" "n"))))]
- "!TARGET_ZARCH && (INTVAL (operands[3]) & 63) == 63"
- "s<lr>dl\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-; sll, srl, sllg, srlg, sllk, srlk
-(define_insn "*<shift><mode>3_and"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (SHIFT:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n"))))]
- "(INTVAL (operands[3]) & 63) == 63"
- "@
- s<lr>l<g>\t%0,<1>%Y2
- s<lr>l<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-;
-; ashr(di|si)3 instruction pattern(s).
-; Arithmetic right shifts
-
-(define_expand "ashr<mode>3"
- [(parallel
- [(set (match_operand:DSI 0 "register_operand" "")
- (ashiftrt:DSI (match_operand:DSI 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "")))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "")
-
-(define_insn "*ashrdi3_cc_31"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (ashiftrt:DI (match_dup 1) (match_dup 2)))]
- "!TARGET_ZARCH && s390_match_ccmode(insn, CCSmode)"
- "srda\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-(define_insn "*ashrdi3_cconly_31"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d"))]
- "!TARGET_ZARCH && s390_match_ccmode(insn, CCSmode)"
- "srda\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-(define_insn "*ashrdi3_31"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH"
- "srda\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cc"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
- (ashiftrt:GPR (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- sra<g>\t%0,<1>%Y2
- sra<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))
- (const_int 0)))
- (clobber (match_scratch:GPR 0 "=d,d"))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- sra<g>\t%0,<1>%Y2
- sra<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-; sra, srag
-(define_insn "*ashr<mode>3"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")))
- (clobber (reg:CC CC_REGNUM))]
- ""
- "@
- sra<g>\t%0,<1>%Y2
- sra<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-
-; shift pattern with implicit ANDs
-
-(define_insn "*ashrdi3_cc_31_and"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 3 "const_int_operand" "n")))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (ashiftrt:DI (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
- "!TARGET_ZARCH && s390_match_ccmode(insn, CCSmode)
- && (INTVAL (operands[3]) & 63) == 63"
- "srda\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-(define_insn "*ashrdi3_cconly_31_and"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 3 "const_int_operand" "n")))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d"))]
- "!TARGET_ZARCH && s390_match_ccmode(insn, CCSmode)
- && (INTVAL (operands[3]) & 63) == 63"
- "srda\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-(define_insn "*ashrdi3_31_and"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
- (match_operand:SI 3 "const_int_operand" "n"))))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && (INTVAL (operands[3]) & 63) == 63"
- "srda\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cc_and"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n")))
- (const_int 0)))
- (set (match_operand:GPR 0 "register_operand" "=d,d")
- (ashiftrt:GPR (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
- "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
- "@
- sra<g>\t%0,<1>%Y2
- sra<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_cconly_and"
- [(set (reg CC_REGNUM)
- (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n")))
- (const_int 0)))
- (clobber (match_scratch:GPR 0 "=d,d"))]
- "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
- "@
- sra<g>\t%0,<1>%Y2
- sra<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-; sra, srag, srak
-(define_insn "*ashr<mode>3_and"
- [(set (match_operand:GPR 0 "register_operand" "=d,d")
- (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>,d")
- (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")
- (match_operand:SI 3 "const_int_operand" "n,n"))))
- (clobber (reg:CC CC_REGNUM))]
- "(INTVAL (operands[3]) & 63) == 63"
- "@
- sra<g>\t%0,<1>%Y2
- sra<gk>\t%0,%1,%Y2"
- [(set_attr "op_type" "RS<E>,RSY")
- (set_attr "atype" "reg,reg")
- (set_attr "cpu_facility" "*,z196")
- (set_attr "z10prop" "z10_super_E1,*")])
-
-
-;;
-;; Branch instruction patterns.
-;;
-
-(define_expand "cbranch<mode>4"
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:GPR 1 "register_operand" "")
- (match_operand:GPR 2 "general_operand" "")])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- ""
- "s390_emit_jump (operands[3],
- s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2]));
- DONE;")
-
-(define_expand "cbranch<mode>4"
- [(set (pc)
- (if_then_else (match_operator 0 "comparison_operator"
- [(match_operand:FP 1 "register_operand" "")
- (match_operand:FP 2 "general_operand" "")])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
- "s390_emit_jump (operands[3],
- s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2]));
- DONE;")
-
-(define_expand "cbranchcc4"
- [(set (pc)
- (if_then_else (match_operator 0 "s390_eqne_operator"
- [(match_operand 1 "cc_reg_operand" "")
- (match_operand 2 "const0_operand" "")])
- (label_ref (match_operand 3 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
- "s390_emit_jump (operands[3],
- s390_emit_compare (GET_CODE (operands[0]), operands[1], operands[2]));
- DONE;")
-
-
-
-;;
-;;- Conditional jump instructions.
-;;
-
-(define_insn "*cjump_64"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_CPU_ZARCH"
-{
- if (get_attr_length (insn) == 4)
- return "j%C1\t%l0";
- else
- return "jg%C1\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6)))])
-
-(define_insn "*cjump_31"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "!TARGET_CPU_ZARCH"
-{
- gcc_assert (get_attr_length (insn) == 4);
- return "j%C1\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
-(define_insn "*cjump_long"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
- (match_operand 0 "address_operand" "ZQZR")
- (pc)))]
- ""
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "b%C1r\t%0";
- else
- return "b%C1\t%a0";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
- (set_attr "atype" "agen")])
-
-
-;;
-;;- Negated conditional jump instructions.
-;;
-
-(define_insn "*icjump_64"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_CPU_ZARCH"
-{
- if (get_attr_length (insn) == 4)
- return "j%D1\t%l0";
- else
- return "jg%D1\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6)))])
-
-(define_insn "*icjump_31"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "!TARGET_CPU_ZARCH"
-{
- gcc_assert (get_attr_length (insn) == 4);
- return "j%D1\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
-(define_insn "*icjump_long"
- [(set (pc)
- (if_then_else
- (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
- (pc)
- (match_operand 0 "address_operand" "ZQZR")))]
- ""
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "b%D1r\t%0";
- else
- return "b%D1\t%a0";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
- (set_attr "atype" "agen")])
-
-;;
-;;- Trap instructions.
-;;
-
-(define_insn "trap"
- [(trap_if (const_int 1) (const_int 0))]
- ""
- "j\t.+2"
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")])
-
-(define_expand "ctrap<mode>4"
- [(trap_if (match_operator 0 "comparison_operator"
- [(match_operand:GPR 1 "register_operand" "")
- (match_operand:GPR 2 "general_operand" "")])
- (match_operand 3 "const0_operand" ""))]
- ""
- {
- rtx cond = s390_emit_compare (GET_CODE (operands[0]),
- operands[1], operands[2]);
- emit_insn (gen_condtrap (cond, XEXP (cond, 0)));
- DONE;
- })
-
-(define_expand "ctrap<mode>4"
- [(trap_if (match_operator 0 "comparison_operator"
- [(match_operand:FP 1 "register_operand" "")
- (match_operand:FP 2 "general_operand" "")])
- (match_operand 3 "const0_operand" ""))]
- ""
- {
- rtx cond = s390_emit_compare (GET_CODE (operands[0]),
- operands[1], operands[2]);
- emit_insn (gen_condtrap (cond, XEXP (cond, 0)));
- DONE;
- })
-
-(define_insn "condtrap"
- [(trap_if (match_operator 0 "s390_comparison"
- [(match_operand 1 "cc_reg_operand" "c")
- (const_int 0)])
- (const_int 0))]
- ""
- "j%C0\t.+2";
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")])
-
-; crt, cgrt, cit, cgit
-(define_insn "*cmp_and_trap_signed_int<mode>"
- [(trap_if (match_operator 0 "s390_signed_integer_comparison"
- [(match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "nonmemory_operand" "d,K")])
- (const_int 0))]
- "TARGET_Z10"
- "@
- c<g>rt%C0\t%1,%2
- c<g>it%C0\t%1,%h2"
- [(set_attr "op_type" "RRF,RIE")
- (set_attr "type" "branch")
- (set_attr "z10prop" "z10_super_c,z10_super")])
-
-; clrt, clgrt, clfit, clgit
-(define_insn "*cmp_and_trap_unsigned_int<mode>"
- [(trap_if (match_operator 0 "s390_unsigned_integer_comparison"
- [(match_operand:GPR 1 "register_operand" "d,d")
- (match_operand:GPR 2 "nonmemory_operand" "d,D")])
- (const_int 0))]
- "TARGET_Z10"
- "@
- cl<g>rt%C0\t%1,%2
- cl<gf>it%C0\t%1,%x2"
- [(set_attr "op_type" "RRF,RIE")
- (set_attr "type" "branch")
- (set_attr "z10prop" "z10_super_c,z10_super")])
-
-;;
-;;- Loop instructions.
-;;
-;; This is all complicated by the fact that since this is a jump insn
-;; we must handle our own output reloads.
-
-;; branch on index
-
-; This splitter will be matched by combine and has to add the 2 moves
-; necessary to load the compare and the increment values into a
-; register pair as needed by brxle.
-
-(define_insn_and_split "*brx_stage1_<GPR:mode>"
- [(set (pc)
- (if_then_else
- (match_operator 6 "s390_brx_operator"
- [(plus:GPR (match_operand:GPR 1 "register_operand" "")
- (match_operand:GPR 2 "general_operand" ""))
- (match_operand:GPR 3 "register_operand" "")])
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:GPR 4 "nonimmediate_operand" "")
- (plus:GPR (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:GPR 5 ""))]
- "TARGET_CPU_ZARCH"
- "#"
- "!reload_completed && !reload_in_progress"
- [(set (match_dup 7) (match_dup 2)) ; the increment
- (set (match_dup 8) (match_dup 3)) ; the comparison value
- (parallel [(set (pc)
- (if_then_else
- (match_op_dup 6
- [(plus:GPR (match_dup 1) (match_dup 7))
- (match_dup 8)])
- (label_ref (match_dup 0))
- (pc)))
- (set (match_dup 4)
- (plus:GPR (match_dup 1) (match_dup 7)))
- (clobber (match_dup 5))
- (clobber (reg:CC CC_REGNUM))])]
- {
- rtx dreg = gen_reg_rtx (word_mode == DImode ? TImode : DImode);
- operands[7] = gen_lowpart (<GPR:MODE>mode,
- gen_highpart (word_mode, dreg));
- operands[8] = gen_lowpart (<GPR:MODE>mode,
- gen_lowpart (word_mode, dreg));
- })
-
-; brxlg, brxhg
-
-(define_insn_and_split "*brxg_64bit"
- [(set (pc)
- (if_then_else
- (match_operator 5 "s390_brx_operator"
- [(plus:DI (match_operand:DI 1 "register_operand" "d,d,d")
- (subreg:DI (match_operand:TI 2 "register_operand" "d,d,d") 0))
- (subreg:DI (match_dup 2) 8)])
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:DI 3 "nonimmediate_operand" "=1,?X,?X")
- (plus:DI (match_dup 1)
- (subreg:DI (match_dup 2) 0)))
- (clobber (match_scratch:DI 4 "=X,&1,&?d"))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
-{
- if (which_alternative != 0)
- return "#";
- else if (get_attr_length (insn) == 6)
- return "brx%E5g\t%1,%2,%l0";
- else
- return "agr\t%1,%2\;cgr\t%1,%M2\;jg%C5\t%l0";
-}
- "&& reload_completed
- && (!REG_P (operands[3])
- || !rtx_equal_p (operands[1], operands[3]))"
- [(set (match_dup 4) (match_dup 1))
- (parallel [(set (match_dup 4) (plus:DI (match_dup 4) (subreg:DI (match_dup 2) 0)))
- (clobber (reg:CC CC_REGNUM))])
- (set (reg:CCS CC_REGNUM) (compare:CCS (match_dup 4) (subreg:DI (match_dup 2) 8)))
- (set (match_dup 3) (match_dup 4))
- (set (pc) (if_then_else (match_op_dup 5 [(reg:CCS CC_REGNUM) (const_int 0)])
- (label_ref (match_dup 0))
- (pc)))]
- ""
- [(set_attr "op_type" "RIE")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 6) (const_int 16)))])
-
-; brxle, brxh
-
-(define_insn_and_split "*brx_64bit"
- [(set (pc)
- (if_then_else
- (match_operator 5 "s390_brx_operator"
- [(plus:SI (match_operand:SI 1 "register_operand" "d,d,d")
- (subreg:SI (match_operand:TI 2 "register_operand" "d,d,d") 4))
- (subreg:SI (match_dup 2) 12)])
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 3 "nonimmediate_operand" "=1,?X,?X")
- (plus:SI (match_dup 1)
- (subreg:SI (match_dup 2) 4)))
- (clobber (match_scratch:SI 4 "=X,&1,&?d"))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
-{
- if (which_alternative != 0)
- return "#";
- else if (get_attr_length (insn) == 6)
- return "brx%C5\t%1,%2,%l0";
- else
- return "ar\t%1,%2\;cr\t%1,%M2\;jg%C5\t%l0";
-}
- "&& reload_completed
- && (!REG_P (operands[3])
- || !rtx_equal_p (operands[1], operands[3]))"
- [(set (match_dup 4) (match_dup 1))
- (parallel [(set (match_dup 4) (plus:SI (match_dup 4) (subreg:SI (match_dup 2) 4)))
- (clobber (reg:CC CC_REGNUM))])
- (set (reg:CCS CC_REGNUM) (compare:CCS (match_dup 4) (subreg:SI (match_dup 2) 12)))
- (set (match_dup 3) (match_dup 4))
- (set (pc) (if_then_else (match_op_dup 5 [(reg:CCS CC_REGNUM) (const_int 0)])
- (label_ref (match_dup 0))
- (pc)))]
- ""
- [(set_attr "op_type" "RSI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 6) (const_int 14)))])
-
-; brxle, brxh
-
-(define_insn_and_split "*brx_31bit"
- [(set (pc)
- (if_then_else
- (match_operator 5 "s390_brx_operator"
- [(plus:SI (match_operand:SI 1 "register_operand" "d,d,d")
- (subreg:SI (match_operand:DI 2 "register_operand" "d,d,d") 0))
- (subreg:SI (match_dup 2) 4)])
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 3 "nonimmediate_operand" "=1,?X,?X")
- (plus:SI (match_dup 1)
- (subreg:SI (match_dup 2) 0)))
- (clobber (match_scratch:SI 4 "=X,&1,&?d"))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_ZARCH && TARGET_CPU_ZARCH"
-{
- if (which_alternative != 0)
- return "#";
- else if (get_attr_length (insn) == 6)
- return "brx%C5\t%1,%2,%l0";
- else
- return "ar\t%1,%2\;cr\t%1,%M2\;jg%C5\t%l0";
-}
- "&& reload_completed
- && (!REG_P (operands[3])
- || !rtx_equal_p (operands[1], operands[3]))"
- [(set (match_dup 4) (match_dup 1))
- (parallel [(set (match_dup 4) (plus:SI (match_dup 4) (subreg:SI (match_dup 2) 0)))
- (clobber (reg:CC CC_REGNUM))])
- (set (reg:CCS CC_REGNUM) (compare:CCS (match_dup 4) (subreg:SI (match_dup 2) 4)))
- (set (match_dup 3) (match_dup 4))
- (set (pc) (if_then_else (match_op_dup 5 [(reg:CCS CC_REGNUM) (const_int 0)])
- (label_ref (match_dup 0))
- (pc)))]
- ""
- [(set_attr "op_type" "RSI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 6) (const_int 14)))])
-
-
-;; branch on count
-
-(define_expand "doloop_end"
- [(use (match_operand 0 "" "")) ; loop pseudo
- (use (match_operand 1 "" "")) ; iterations; zero if unknown
- (use (match_operand 2 "" "")) ; max iterations
- (use (match_operand 3 "" "")) ; loop level
- (use (match_operand 4 "" ""))] ; label
- ""
-{
- if (GET_MODE (operands[0]) == SImode && !TARGET_CPU_ZARCH)
- emit_jump_insn (gen_doloop_si31 (operands[4], operands[0], operands[0]));
- else if (GET_MODE (operands[0]) == SImode && TARGET_CPU_ZARCH)
- emit_jump_insn (gen_doloop_si64 (operands[4], operands[0], operands[0]));
- else if (GET_MODE (operands[0]) == DImode && TARGET_ZARCH)
- emit_jump_insn (gen_doloop_di (operands[4], operands[0], operands[0]));
- else
- FAIL;
-
- DONE;
-})
-
-(define_insn_and_split "doloop_si64"
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 1 "register_operand" "d,d,d")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 2 "nonimmediate_operand" "=1,?X,?X")
- (plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 "=X,&1,&?d"))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_CPU_ZARCH"
-{
- if (which_alternative != 0)
- return "#";
- else if (get_attr_length (insn) == 4)
- return "brct\t%1,%l0";
- else
- return "ahi\t%1,-1\;jgne\t%l0";
-}
- "&& reload_completed
- && (! REG_P (operands[2])
- || ! rtx_equal_p (operands[1], operands[2]))"
- [(set (match_dup 3) (match_dup 1))
- (parallel [(set (reg:CCAN CC_REGNUM)
- (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
- (const_int 0)))
- (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
- (set (match_dup 2) (match_dup 3))
- (set (pc) (if_then_else (ne (reg:CCAN CC_REGNUM) (const_int 0))
- (label_ref (match_dup 0))
- (pc)))]
- ""
- [(set_attr "op_type" "RI")
- ; Strictly speaking, the z10 properties are valid for brct only, however, it does not
- ; hurt us in the (rare) case of ahi.
- (set_attr "z10prop" "z10_super_E1")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 10)))])
-
-(define_insn_and_split "doloop_si31"
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 1 "register_operand" "d,d,d")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 2 "nonimmediate_operand" "=1,?X,?X")
- (plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 "=X,&1,&?d"))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
-{
- if (which_alternative != 0)
- return "#";
- else if (get_attr_length (insn) == 4)
- return "brct\t%1,%l0";
- else
- gcc_unreachable ();
-}
- "&& reload_completed
- && (! REG_P (operands[2])
- || ! rtx_equal_p (operands[1], operands[2]))"
- [(set (match_dup 3) (match_dup 1))
- (parallel [(set (reg:CCAN CC_REGNUM)
- (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
- (const_int 0)))
- (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
- (set (match_dup 2) (match_dup 3))
- (set (pc) (if_then_else (ne (reg:CCAN CC_REGNUM) (const_int 0))
- (label_ref (match_dup 0))
- (pc)))]
- ""
- [(set_attr "op_type" "RI")
- ; Strictly speaking, the z10 properties are valid for brct only, however, it does not
- ; hurt us in the (rare) case of ahi.
- (set_attr "z10prop" "z10_super_E1")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
-(define_insn "*doloop_si_long"
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 1 "register_operand" "d")
- (const_int 1))
- (match_operand 0 "address_operand" "ZQZR")
- (pc)))
- (set (match_operand:SI 2 "register_operand" "=1")
- (plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 "=X"))
- (clobber (reg:CC CC_REGNUM))]
- "!TARGET_CPU_ZARCH"
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "bctr\t%1,%0";
- else
- return "bct\t%1,%a0";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
- (set_attr "atype" "agen")
- (set_attr "z10prop" "z10_c")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn_and_split "doloop_di"
- [(set (pc)
- (if_then_else
- (ne (match_operand:DI 1 "register_operand" "d,d,d")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:DI 2 "nonimmediate_operand" "=1,?X,?X")
- (plus:DI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:DI 3 "=X,&1,&?d"))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_ZARCH"
-{
- if (which_alternative != 0)
- return "#";
- else if (get_attr_length (insn) == 4)
- return "brctg\t%1,%l0";
- else
- return "aghi\t%1,-1\;jgne\t%l0";
-}
- "&& reload_completed
- && (! REG_P (operands[2])
- || ! rtx_equal_p (operands[1], operands[2]))"
- [(set (match_dup 3) (match_dup 1))
- (parallel [(set (reg:CCAN CC_REGNUM)
- (compare:CCAN (plus:DI (match_dup 3) (const_int -1))
- (const_int 0)))
- (set (match_dup 3) (plus:DI (match_dup 3) (const_int -1)))])
- (set (match_dup 2) (match_dup 3))
- (set (pc) (if_then_else (ne (reg:CCAN CC_REGNUM) (const_int 0))
- (label_ref (match_dup 0))
- (pc)))]
- ""
- [(set_attr "op_type" "RI")
- ; Strictly speaking, the z10 properties are valid for brct only, however, it does not
- ; hurt us in the (rare) case of ahi.
- (set_attr "z10prop" "z10_super_E1")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 10)))])
-
-;;
-;;- Unconditional jump instructions.
-;;
-
-;
-; jump instruction pattern(s).
-;
-
-(define_expand "jump"
- [(match_operand 0 "" "")]
- ""
- "s390_emit_jump (operands[0], NULL_RTX); DONE;")
-
-(define_insn "*jump64"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- "TARGET_CPU_ZARCH"
-{
- if (get_attr_length (insn) == 4)
- return "j\t%l0";
- else
- return "jg\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6)))])
-
-(define_insn "*jump31"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
- "!TARGET_CPU_ZARCH"
-{
- gcc_assert (get_attr_length (insn) == 4);
- return "j\t%l0";
-}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (not (match_test "flag_pic"))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 6))
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 8))))])
-
-;
-; indirect-jump instruction pattern(s).
-;
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand 0 "address_operand" "ZQZR"))]
- ""
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "br\t%0";
- else
- return "b\t%a0";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
- (set_attr "atype" "agen")])
-
-;
-; casesi instruction pattern(s).
-;
-
-(define_insn "casesi_jump"
- [(set (pc) (match_operand 0 "address_operand" "ZQZR"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "br\t%0";
- else
- return "b\t%a0";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
- (set_attr "atype" "agen")])
-
-(define_expand "casesi"
- [(match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")
- (label_ref (match_operand 3 "" ""))
- (label_ref (match_operand 4 "" ""))]
- ""
-{
- rtx index = gen_reg_rtx (SImode);
- rtx base = gen_reg_rtx (Pmode);
- rtx target = gen_reg_rtx (Pmode);
-
- emit_move_insn (index, operands[0]);
- emit_insn (gen_subsi3 (index, index, operands[1]));
- emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1,
- operands[4]);
-
- if (Pmode != SImode)
- index = convert_to_mode (Pmode, index, 1);
- if (GET_CODE (index) != REG)
- index = copy_to_mode_reg (Pmode, index);
-
- if (TARGET_64BIT)
- emit_insn (gen_ashldi3 (index, index, GEN_INT (3)));
- else
- emit_insn (gen_ashlsi3 (index, index, const2_rtx));
-
- emit_move_insn (base, gen_rtx_LABEL_REF (Pmode, operands[3]));
-
- index = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, base, index));
- emit_move_insn (target, index);
-
- if (flag_pic)
- target = gen_rtx_PLUS (Pmode, base, target);
- emit_jump_insn (gen_casesi_jump (target, operands[3]));
-
- DONE;
-})
-
-
-;;
-;;- Jump to subroutine.
-;;
-;;
-
-;
-; untyped call instruction pattern(s).
-;
-
-;; Call subroutine returning any type.
-(define_expand "untyped_call"
- [(parallel [(call (match_operand 0 "" "")
- (const_int 0))
- (match_operand 1 "" "")
- (match_operand 2 "" "")])]
- ""
-{
- int i;
-
- emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx));
-
- for (i = 0; i < XVECLEN (operands[2], 0); i++)
- {
- rtx set = XVECEXP (operands[2], 0, i);
- emit_move_insn (SET_DEST (set), SET_SRC (set));
- }
-
- /* The optimizer does not know that the call sets the function value
- registers we stored in the result block. We avoid problems by
- claiming that all hard registers are used and clobbered at this
- point. */
- emit_insn (gen_blockage ());
-
- DONE;
-})
-
-;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
-;; all of memory. This blocks insns from being moved across this point.
-
-(define_insn "blockage"
- [(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
- ""
- ""
- [(set_attr "type" "none")
- (set_attr "length" "0")])
-
-;
-; sibcall patterns
-;
-
-(define_expand "sibcall"
- [(call (match_operand 0 "" "")
- (match_operand 1 "" ""))]
- ""
-{
- s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX, NULL_RTX);
- DONE;
-})
-
-(define_insn "*sibcall_br"
- [(call (mem:QI (reg SIBCALL_REGNUM))
- (match_operand 0 "const_int_operand" "n"))]
- "SIBLING_CALL_P (insn)
- && GET_MODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == Pmode"
- "br\t%%r1"
- [(set_attr "op_type" "RR")
- (set_attr "type" "branch")
- (set_attr "atype" "agen")])
-
-(define_insn "*sibcall_brc"
- [(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
- (match_operand 1 "const_int_operand" "n"))]
- "SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC"
- "j\t%0"
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")])
-
-(define_insn "*sibcall_brcl"
- [(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
- (match_operand 1 "const_int_operand" "n"))]
- "SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
- "jg\t%0"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "branch")])
-
-;
-; sibcall_value patterns
-;
-
-(define_expand "sibcall_value"
- [(set (match_operand 0 "" "")
- (call (match_operand 1 "" "")
- (match_operand 2 "" "")))]
- ""
-{
- s390_emit_call (XEXP (operands[1], 0), NULL_RTX, operands[0], NULL_RTX);
- DONE;
-})
-
-(define_insn "*sibcall_value_br"
- [(set (match_operand 0 "" "")
- (call (mem:QI (reg SIBCALL_REGNUM))
- (match_operand 1 "const_int_operand" "n")))]
- "SIBLING_CALL_P (insn)
- && GET_MODE (XEXP (XEXP (XEXP (PATTERN (insn), 1), 0), 0)) == Pmode"
- "br\t%%r1"
- [(set_attr "op_type" "RR")
- (set_attr "type" "branch")
- (set_attr "atype" "agen")])
-
-(define_insn "*sibcall_value_brc"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
- (match_operand 2 "const_int_operand" "n")))]
- "SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC"
- "j\t%1"
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")])
-
-(define_insn "*sibcall_value_brcl"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
- (match_operand 2 "const_int_operand" "n")))]
- "SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
- "jg\t%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "branch")])
-
-
-;
-; call instruction pattern(s).
-;
-
-(define_expand "call"
- [(call (match_operand 0 "" "")
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))]
- ""
-{
- s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX,
- gen_rtx_REG (Pmode, RETURN_REGNUM));
- DONE;
-})
-
-(define_insn "*bras"
- [(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
- (match_operand 1 "const_int_operand" "n"))
- (clobber (match_operand 2 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn)
- && TARGET_SMALL_EXEC
- && GET_MODE (operands[2]) == Pmode"
- "bras\t%2,%0"
- [(set_attr "op_type" "RI")
- (set_attr "type" "jsr")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*brasl"
- [(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
- (match_operand 1 "const_int_operand" "n"))
- (clobber (match_operand 2 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn)
- && TARGET_CPU_ZARCH
- && GET_MODE (operands[2]) == Pmode"
- "brasl\t%2,%0"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "jsr")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*basr"
- [(call (mem:QI (match_operand 0 "address_operand" "ZQZR"))
- (match_operand 1 "const_int_operand" "n"))
- (clobber (match_operand 2 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn) && GET_MODE (operands[2]) == Pmode"
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "basr\t%2,%0";
- else
- return "bas\t%2,%a0";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "jsr")
- (set_attr "atype" "agen")
- (set_attr "z196prop" "z196_cracked")])
-
-;
-; call_value instruction pattern(s).
-;
-
-(define_expand "call_value"
- [(set (match_operand 0 "" "")
- (call (match_operand 1 "" "")
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))]
- ""
-{
- s390_emit_call (XEXP (operands[1], 0), NULL_RTX, operands[0],
- gen_rtx_REG (Pmode, RETURN_REGNUM));
- DONE;
-})
-
-(define_insn "*bras_r"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
- (match_operand:SI 2 "const_int_operand" "n")))
- (clobber (match_operand 3 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn)
- && TARGET_SMALL_EXEC
- && GET_MODE (operands[3]) == Pmode"
- "bras\t%3,%1"
- [(set_attr "op_type" "RI")
- (set_attr "type" "jsr")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*brasl_r"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
- (match_operand 2 "const_int_operand" "n")))
- (clobber (match_operand 3 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn)
- && TARGET_CPU_ZARCH
- && GET_MODE (operands[3]) == Pmode"
- "brasl\t%3,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "jsr")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*basr_r"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "address_operand" "ZQZR"))
- (match_operand 2 "const_int_operand" "n")))
- (clobber (match_operand 3 "register_operand" "=r"))]
- "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "basr\t%3,%1";
- else
- return "bas\t%3,%a1";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 1 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "jsr")
- (set_attr "atype" "agen")
- (set_attr "z196prop" "z196_cracked")])
-
-;;
-;;- Thread-local storage support.
-;;
-
-(define_expand "get_tp_64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "") (reg:DI TP_REGNUM))]
- "TARGET_64BIT"
- "")
-
-(define_expand "get_tp_31"
- [(set (match_operand:SI 0 "nonimmediate_operand" "") (reg:SI TP_REGNUM))]
- "!TARGET_64BIT"
- "")
-
-(define_expand "set_tp_64"
- [(set (reg:DI TP_REGNUM) (match_operand:DI 0 "nonimmediate_operand" ""))
- (set (reg:DI TP_REGNUM) (unspec_volatile:DI [(reg:DI TP_REGNUM)] UNSPECV_SET_TP))]
- "TARGET_64BIT"
- "")
-
-(define_expand "set_tp_31"
- [(set (reg:SI TP_REGNUM) (match_operand:SI 0 "nonimmediate_operand" ""))
- (set (reg:SI TP_REGNUM) (unspec_volatile:SI [(reg:SI TP_REGNUM)] UNSPECV_SET_TP))]
- "!TARGET_64BIT"
- "")
-
-(define_insn "*set_tp"
- [(set (reg TP_REGNUM) (unspec_volatile [(reg TP_REGNUM)] UNSPECV_SET_TP))]
- ""
- ""
- [(set_attr "type" "none")
- (set_attr "length" "0")])
-
-(define_insn "*tls_load_64"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (unspec:DI [(match_operand:DI 1 "memory_operand" "RT")
- (match_operand:DI 2 "" "")]
- UNSPEC_TLS_LOAD))]
- "TARGET_64BIT"
- "lg\t%0,%1%J2"
- [(set_attr "op_type" "RXE")
- (set_attr "z10prop" "z10_fwd_A3")])
-
-(define_insn "*tls_load_31"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (unspec:SI [(match_operand:SI 1 "memory_operand" "R,T")
- (match_operand:SI 2 "" "")]
- UNSPEC_TLS_LOAD))]
- "!TARGET_64BIT"
- "@
- l\t%0,%1%J2
- ly\t%0,%1%J2"
- [(set_attr "op_type" "RX,RXY")
- (set_attr "type" "load")
- (set_attr "z10prop" "z10_fwd_A3,z10_fwd_A3")])
-
-(define_insn "*bras_tls"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
- (match_operand 2 "const_int_operand" "n")))
- (clobber (match_operand 3 "register_operand" "=r"))
- (use (match_operand 4 "" ""))]
- "!SIBLING_CALL_P (insn)
- && TARGET_SMALL_EXEC
- && GET_MODE (operands[3]) == Pmode"
- "bras\t%3,%1%J4"
- [(set_attr "op_type" "RI")
- (set_attr "type" "jsr")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*brasl_tls"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
- (match_operand 2 "const_int_operand" "n")))
- (clobber (match_operand 3 "register_operand" "=r"))
- (use (match_operand 4 "" ""))]
- "!SIBLING_CALL_P (insn)
- && TARGET_CPU_ZARCH
- && GET_MODE (operands[3]) == Pmode"
- "brasl\t%3,%1%J4"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "jsr")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "*basr_tls"
- [(set (match_operand 0 "" "")
- (call (mem:QI (match_operand 1 "address_operand" "ZQZR"))
- (match_operand 2 "const_int_operand" "n")))
- (clobber (match_operand 3 "register_operand" "=r"))
- (use (match_operand 4 "" ""))]
- "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
-{
- if (get_attr_op_type (insn) == OP_TYPE_RR)
- return "basr\t%3,%1%J4";
- else
- return "bas\t%3,%a1%J4";
-}
- [(set (attr "op_type")
- (if_then_else (match_operand 1 "register_operand" "")
- (const_string "RR") (const_string "RX")))
- (set_attr "type" "jsr")
- (set_attr "atype" "agen")
- (set_attr "z196prop" "z196_cracked")])
-
-;;
-;;- Atomic operations
-;;
-
-;
-; memory barrier pattern.
-;
-
-(define_expand "memory_barrier"
- [(set (match_dup 0)
- (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
- ""
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
-
-(define_insn "*memory_barrier"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_dup 0)] UNSPEC_MB))]
- ""
- "bcr\t15,0"
- [(set_attr "op_type" "RR")])
-
-; Although bcr is superscalar on Z10, this variant will never become part of
-; an execution group.
-
-;
-; compare and swap patterns.
-;
-
-(define_expand "sync_compare_and_swap<mode>"
- [(parallel
- [(set (match_operand:TDSI 0 "register_operand" "")
- (match_operand:TDSI 1 "memory_operand" ""))
- (set (match_dup 1)
- (unspec_volatile:TDSI
- [(match_dup 1)
- (match_operand:TDSI 2 "register_operand" "")
- (match_operand:TDSI 3 "register_operand" "")]
- UNSPECV_CAS))
- (set (reg:CCZ1 CC_REGNUM)
- (compare:CCZ1 (match_dup 1) (match_dup 2)))])]
- "")
-
-(define_expand "sync_compare_and_swap<mode>"
- [(parallel
- [(set (match_operand:HQI 0 "register_operand" "")
- (match_operand:HQI 1 "memory_operand" ""))
- (set (match_dup 1)
- (unspec_volatile:HQI
- [(match_dup 1)
- (match_operand:HQI 2 "general_operand" "")
- (match_operand:HQI 3 "general_operand" "")]
- UNSPECV_CAS))
- (clobber (reg:CC CC_REGNUM))])]
- ""
- "s390_expand_cs_hqi (<MODE>mode, operands[0], operands[1],
- operands[2], operands[3]); DONE;")
-
-; cds, cdsg
-(define_insn "*sync_compare_and_swap<mode>"
- [(set (match_operand:DW 0 "register_operand" "=r")
- (match_operand:DW 1 "memory_operand" "+Q"))
- (set (match_dup 1)
- (unspec_volatile:DW
- [(match_dup 1)
- (match_operand:DW 2 "register_operand" "0")
- (match_operand:DW 3 "register_operand" "r")]
- UNSPECV_CAS))
- (set (reg:CCZ1 CC_REGNUM)
- (compare:CCZ1 (match_dup 1) (match_dup 2)))]
- ""
- "cds<tg>\t%0,%3,%S1"
- [(set_attr "op_type" "RS<TE>")
- (set_attr "type" "sem")])
-
-; cs, csg
-(define_insn "*sync_compare_and_swap<mode>"
- [(set (match_operand:GPR 0 "register_operand" "=r")
- (match_operand:GPR 1 "memory_operand" "+Q"))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(match_dup 1)
- (match_operand:GPR 2 "register_operand" "0")
- (match_operand:GPR 3 "register_operand" "r")]
- UNSPECV_CAS))
- (set (reg:CCZ1 CC_REGNUM)
- (compare:CCZ1 (match_dup 1) (match_dup 2)))]
- ""
- "cs<g>\t%0,%3,%S1"
- [(set_attr "op_type" "RS<E>")
- (set_attr "type" "sem")])
-
-
-;
-; Other atomic instruction patterns.
-;
-
-(define_expand "sync_lock_test_and_set<mode>"
- [(match_operand:HQI 0 "register_operand")
- (match_operand:HQI 1 "memory_operand")
- (match_operand:HQI 2 "general_operand")]
- ""
- "s390_expand_atomic (<MODE>mode, SET, operands[0], operands[1],
- operands[2], false); DONE;")
-
-; z196 load and add, xor, or and and instructions
-
-; lan, lang, lao, laog, lax, laxg, laa, laag
-(define_insn "sync_<atomic><mode>"
- [(parallel
- [(set (match_operand:GPR 0 "memory_operand" "+QS")
- (unspec_volatile:GPR
- [(ATOMIC_Z196:GPR (match_dup 0)
- (match_operand:GPR 1 "general_operand" "d"))]
- UNSPECV_ATOMIC_OP))
- (clobber (match_scratch:GPR 2 "=d"))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_Z196"
- "la<noxa><g>\t%2,%1,%0")
-
-; lan, lang, lao, laog, lax, laxg, laa, laag
-(define_insn "sync_old_<atomic><mode>"
- [(parallel
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (match_operand:GPR 1 "memory_operand" "+QS"))
- (set (match_dup 1)
- (unspec_volatile:GPR
- [(ATOMIC_Z196:GPR (match_dup 1)
- (match_operand:GPR 2 "general_operand" "d"))]
- UNSPECV_ATOMIC_OP))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_Z196"
- "la<noxa><g>\t%0,%2,%1")
-
-
-(define_expand "sync_<atomic><mode>"
- [(set (match_operand:HQI 0 "memory_operand")
- (ATOMIC:HQI (match_dup 0)
- (match_operand:HQI 1 "general_operand")))]
- ""
- "s390_expand_atomic (<MODE>mode, <CODE>, NULL_RTX, operands[0],
- operands[1], false); DONE;")
-
-(define_expand "sync_old_<atomic><mode>"
- [(set (match_operand:HQI 0 "register_operand")
- (match_operand:HQI 1 "memory_operand"))
- (set (match_dup 1)
- (ATOMIC:HQI (match_dup 1)
- (match_operand:HQI 2 "general_operand")))]
- ""
- "s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
- operands[2], false); DONE;")
-
-(define_expand "sync_new_<atomic><mode>"
- [(set (match_operand:HQI 0 "register_operand")
- (ATOMIC:HQI (match_operand:HQI 1 "memory_operand")
- (match_operand:HQI 2 "general_operand")))
- (set (match_dup 1) (ATOMIC:HQI (match_dup 1) (match_dup 2)))]
- ""
- "s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
- operands[2], true); DONE;")
-
-;;
-;;- Miscellaneous instructions.
-;;
-
-;
-; allocate stack instruction pattern(s).
-;
-
-(define_expand "allocate_stack"
- [(match_operand 0 "general_operand" "")
- (match_operand 1 "general_operand" "")]
- "TARGET_BACKCHAIN"
-{
- rtx temp = gen_reg_rtx (Pmode);
-
- emit_move_insn (temp, s390_back_chain_rtx ());
- anti_adjust_stack (operands[1]);
- emit_move_insn (s390_back_chain_rtx (), temp);
-
- emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
- DONE;
-})
-
-
-;
-; setjmp instruction pattern.
-;
-
-(define_expand "builtin_setjmp_receiver"
- [(match_operand 0 "" "")]
- "flag_pic"
-{
- emit_insn (s390_load_got ());
- emit_use (pic_offset_table_rtx);
- DONE;
-})
-
-;; These patterns say how to save and restore the stack pointer. We need not
-;; save the stack pointer at function level since we are careful to
-;; preserve the backchain. At block level, we have to restore the backchain
-;; when we restore the stack pointer.
-;;
-;; For nonlocal gotos, we must save both the stack pointer and its
-;; backchain and restore both. Note that in the nonlocal case, the
-;; save area is a memory location.
-
-(define_expand "save_stack_function"
- [(match_operand 0 "general_operand" "")
- (match_operand 1 "general_operand" "")]
- ""
- "DONE;")
-
-(define_expand "restore_stack_function"
- [(match_operand 0 "general_operand" "")
- (match_operand 1 "general_operand" "")]
- ""
- "DONE;")
-
-(define_expand "restore_stack_block"
- [(match_operand 0 "register_operand" "")
- (match_operand 1 "register_operand" "")]
- "TARGET_BACKCHAIN"
-{
- rtx temp = gen_reg_rtx (Pmode);
-
- emit_move_insn (temp, s390_back_chain_rtx ());
- emit_move_insn (operands[0], operands[1]);
- emit_move_insn (s390_back_chain_rtx (), temp);
-
- DONE;
-})
-
-(define_expand "save_stack_nonlocal"
- [(match_operand 0 "memory_operand" "")
- (match_operand 1 "register_operand" "")]
- ""
-{
- rtx base = gen_rtx_REG (Pmode, BASE_REGNUM);
-
- /* Copy the backchain to the first word, sp to the second and the
- literal pool base to the third. */
-
- rtx save_bc = adjust_address (operands[0], Pmode, 0);
- rtx save_sp = adjust_address (operands[0], Pmode, GET_MODE_SIZE (Pmode));
- rtx save_bp = adjust_address (operands[0], Pmode, 2 * GET_MODE_SIZE (Pmode));
-
- if (TARGET_BACKCHAIN)
- emit_move_insn (save_bc, force_reg (Pmode, s390_back_chain_rtx ()));
-
- emit_move_insn (save_sp, operands[1]);
- emit_move_insn (save_bp, base);
-
- DONE;
-})
-
-(define_expand "restore_stack_nonlocal"
- [(match_operand 0 "register_operand" "")
- (match_operand 1 "memory_operand" "")]
- ""
-{
- rtx base = gen_rtx_REG (Pmode, BASE_REGNUM);
- rtx temp = NULL_RTX;
-
- /* Restore the backchain from the first word, sp from the second and the
- literal pool base from the third. */
-
- rtx save_bc = adjust_address (operands[1], Pmode, 0);
- rtx save_sp = adjust_address (operands[1], Pmode, GET_MODE_SIZE (Pmode));
- rtx save_bp = adjust_address (operands[1], Pmode, 2 * GET_MODE_SIZE (Pmode));
-
- if (TARGET_BACKCHAIN)
- temp = force_reg (Pmode, save_bc);
-
- emit_move_insn (base, save_bp);
- emit_move_insn (operands[0], save_sp);
-
- if (temp)
- emit_move_insn (s390_back_chain_rtx (), temp);
-
- emit_use (base);
- DONE;
-})
-
-(define_expand "exception_receiver"
- [(const_int 0)]
- ""
-{
- s390_set_has_landing_pad_p (true);
- DONE;
-})
-
-;
-; nop instruction pattern(s).
-;
-
-(define_insn "nop"
- [(const_int 0)]
- ""
- "lr\t0,0"
- [(set_attr "op_type" "RR")
- (set_attr "z10prop" "z10_fr_E1")])
-
-(define_insn "nop1"
- [(const_int 1)]
- ""
- "lr\t1,1"
- [(set_attr "op_type" "RR")])
-
-
-;
-; Special literal pool access instruction pattern(s).
-;
-
-(define_insn "*pool_entry"
- [(unspec_volatile [(match_operand 0 "consttable_operand" "X")]
- UNSPECV_POOL_ENTRY)]
- ""
-{
- enum machine_mode mode = GET_MODE (PATTERN (insn));
- unsigned int align = GET_MODE_BITSIZE (mode);
- s390_output_pool_entry (operands[0], mode, align);
- return "";
-}
- [(set (attr "length")
- (symbol_ref "GET_MODE_SIZE (GET_MODE (PATTERN (insn)))"))])
-
-(define_insn "pool_align"
- [(unspec_volatile [(match_operand 0 "const_int_operand" "n")]
- UNSPECV_POOL_ALIGN)]
- ""
- ".align\t%0"
- [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
-
-(define_insn "pool_section_start"
- [(unspec_volatile [(const_int 1)] UNSPECV_POOL_SECTION)]
- ""
- ".section\t.rodata"
- [(set_attr "length" "0")])
-
-(define_insn "pool_section_end"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_SECTION)]
- ""
- ".previous"
- [(set_attr "length" "0")])
-
-(define_insn "main_base_31_small"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))]
- "!TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "basr\t%0,0"
- [(set_attr "op_type" "RR")
- (set_attr "type" "la")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "main_base_31_large"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))
- (set (pc) (label_ref (match_operand 2 "" "")))]
- "!TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "bras\t%0,%2"
- [(set_attr "op_type" "RI")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "main_base_64"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))]
- "TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "larl\t%0,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "larl")
- (set_attr "z10prop" "z10_fwd_A1")])
-
-(define_insn "main_pool"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL))]
- "GET_MODE (operands[0]) == Pmode"
-{
- gcc_unreachable ();
-}
- [(set (attr "type")
- (if_then_else (match_test "TARGET_CPU_ZARCH")
- (const_string "larl") (const_string "la")))])
-
-(define_insn "reload_base_31"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))]
- "!TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "basr\t%0,0\;la\t%0,%1-.(%0)"
- [(set_attr "length" "6")
- (set_attr "type" "la")
- (set_attr "z196prop" "z196_cracked")])
-
-(define_insn "reload_base_64"
- [(set (match_operand 0 "register_operand" "=a")
- (unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))]
- "TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
- "larl\t%0,%1"
- [(set_attr "op_type" "RIL")
- (set_attr "type" "larl")
- (set_attr "z10prop" "z10_fwd_A1")])
-
-(define_insn "pool"
- [(unspec_volatile [(match_operand 0 "const_int_operand" "n")] UNSPECV_POOL)]
- ""
-{
- gcc_unreachable ();
-}
- [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
-
-;;
-;; 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 (false); DONE;")
-
-(define_expand "sibcall_epilogue"
- [(use (const_int 0))]
- ""
- "s390_emit_epilogue (true); DONE;")
-
-(define_insn "*return"
- [(return)
- (use (match_operand 0 "register_operand" "a"))]
- "GET_MODE (operands[0]) == Pmode"
- "br\t%0"
- [(set_attr "op_type" "RR")
- (set_attr "type" "jsr")
- (set_attr "atype" "agen")])
-
-
-;; Instruction definition to extend a 31-bit pointer into a 64-bit
-;; pointer. This is used for compatibility.
-
-(define_expand "ptr_extend"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:SI 1 "register_operand" "r"))]
- "TARGET_64BIT"
-{
- emit_insn (gen_anddi3 (operands[0],
- gen_lowpart (DImode, operands[1]),
- GEN_INT (0x7fffffff)));
- DONE;
-})
-
-;; Instruction definition to expand eh_return macro to support
-;; swapping in special linkage return addresses.
-
-(define_expand "eh_return"
- [(use (match_operand 0 "register_operand" ""))]
- "TARGET_TPF"
-{
- s390_emit_tpf_eh_return (operands[0]);
- DONE;
-})
-
-;
-; Stack Protector Patterns
-;
-
-(define_expand "stack_protect_set"
- [(set (match_operand 0 "memory_operand" "")
- (match_operand 1 "memory_operand" ""))]
- ""
-{
-#ifdef TARGET_THREAD_SSP_OFFSET
- operands[1]
- = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
- GEN_INT (TARGET_THREAD_SSP_OFFSET)));
-#endif
- if (TARGET_64BIT)
- emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
- else
- emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
-
- DONE;
-})
-
-(define_insn "stack_protect_set<mode>"
- [(set (match_operand:DSI 0 "memory_operand" "=Q")
- (unspec:DSI [(match_operand:DSI 1 "memory_operand" "Q")] UNSPEC_SP_SET))]
- ""
- "mvc\t%O0(%G0,%R0),%S1"
- [(set_attr "op_type" "SS")])
-
-(define_expand "stack_protect_test"
- [(set (reg:CC CC_REGNUM)
- (compare (match_operand 0 "memory_operand" "")
- (match_operand 1 "memory_operand" "")))
- (match_operand 2 "" "")]
- ""
-{
- rtx cc_reg, test;
-#ifdef TARGET_THREAD_SSP_OFFSET
- operands[1]
- = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
- GEN_INT (TARGET_THREAD_SSP_OFFSET)));
-#endif
- if (TARGET_64BIT)
- emit_insn (gen_stack_protect_testdi (operands[0], operands[1]));
- else
- emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
-
- cc_reg = gen_rtx_REG (CCZmode, CC_REGNUM);
- test = gen_rtx_EQ (VOIDmode, cc_reg, const0_rtx);
- emit_jump_insn (gen_cbranchcc4 (test, cc_reg, const0_rtx, operands[2]));
- DONE;
-})
-
-(define_insn "stack_protect_test<mode>"
- [(set (reg:CCZ CC_REGNUM)
- (unspec:CCZ [(match_operand:DSI 0 "memory_operand" "Q")
- (match_operand:DSI 1 "memory_operand" "Q")] UNSPEC_SP_TEST))]
- ""
- "clc\t%O0(%G0,%R0),%S1"
- [(set_attr "op_type" "SS")])
-
-; This is used in s390_emit_prologue in order to prevent insns
-; adjusting the stack pointer to be moved over insns writing stack
-; slots using a copy of the stack pointer in a different register.
-(define_insn "stack_tie"
- [(set (match_operand:BLK 0 "memory_operand" "+m")
- (unspec:BLK [(match_dup 0)] UNSPEC_TIE))]
- ""
- ""
- [(set_attr "length" "0")])
-
-
-;
-; Data prefetch patterns
-;
-
-(define_insn "prefetch"
- [(prefetch (match_operand 0 "address_operand" "ZQZRZSZT,X")
- (match_operand:SI 1 "const_int_operand" " n,n")
- (match_operand:SI 2 "const_int_operand" " n,n"))]
- "TARGET_Z10"
-{
- switch (which_alternative)
- {
- case 0:
- return INTVAL (operands[1]) == 1 ? "pfd\t2,%a0" : "pfd\t1,%a0";
- case 1:
- if (larl_operand (operands[0], Pmode))
- return INTVAL (operands[1]) == 1 ? "pfdrl\t2,%a0" : "pfdrl\t1,%a0";
- default:
-
- /* This might be reached for symbolic operands with an odd
- addend. We simply omit the prefetch for such rare cases. */
-
- return "";
- }
-}
- [(set_attr "type" "load,larl")
- (set_attr "op_type" "RXY,RIL")
- (set_attr "z10prop" "z10_super")
- (set_attr "z196prop" "z196_alone")])
-
-
-;
-; Byte swap instructions
-;
-
-(define_insn "bswap<mode>2"
- [(set (match_operand:GPR 0 "register_operand" "=d, d")
- (bswap:GPR (match_operand:GPR 1 "nonimmediate_operand" " d,RT")))]
- "TARGET_CPU_ZARCH"
- "@
- lrv<g>r\t%0,%1
- lrv<g>\t%0,%1"
- [(set_attr "type" "*,load")
- (set_attr "op_type" "RRE,RXY")
- (set_attr "z10prop" "z10_super")])
-
-
-;
-; Population count instruction
-;
-
-; The S/390 popcount instruction counts the bits of op1 in 8 byte
-; portions and stores the result in the corresponding bytes in op0.
-(define_insn "*popcount<mode>"
- [(set (match_operand:INT 0 "register_operand" "=d")
- (unspec:INT [(match_operand:INT 1 "register_operand" "d")] UNSPEC_POPCNT))
- (clobber (reg:CC CC_REGNUM))]
- "TARGET_Z196"
- "popcnt\t%0,%1"
- [(set_attr "op_type" "RRE")])
-
-(define_expand "popcountdi2"
- [; popcnt op0, op1
- (parallel [(set (match_operand:DI 0 "register_operand" "")
- (unspec:DI [(match_operand:DI 1 "register_operand")]
- UNSPEC_POPCNT))
- (clobber (reg:CC CC_REGNUM))])
- ; sllg op2, op0, 32
- (set (match_dup 2) (ashift:DI (match_dup 0) (const_int 32)))
- ; agr op0, op2
- (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])
- ; sllg op2, op0, 16
- (set (match_dup 2)
- (ashift:DI (match_dup 0) (const_int 16)))
- ; agr op0, op2
- (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])
- ; sllg op2, op0, 8
- (set (match_dup 2) (ashift:DI (match_dup 0) (const_int 8)))
- ; agr op0, op2
- (parallel [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])
- ; srlg op0, op0, 56
- (set (match_dup 0) (lshiftrt:DI (match_dup 0) (const_int 56)))]
- "TARGET_Z196 && TARGET_64BIT"
- "operands[2] = gen_reg_rtx (DImode);")
-
-(define_expand "popcountsi2"
- [; popcnt op0, op1
- (parallel [(set (match_operand:SI 0 "register_operand" "")
- (unspec:SI [(match_operand:SI 1 "register_operand")]
- UNSPEC_POPCNT))
- (clobber (reg:CC CC_REGNUM))])
- ; sllk op2, op0, 16
- (set (match_dup 2)
- (ashift:SI (match_dup 0) (const_int 16)))
- ; ar op0, op2
- (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])
- ; sllk op2, op0, 8
- (set (match_dup 2) (ashift:SI (match_dup 0) (const_int 8)))
- ; ar op0, op2
- (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])
- ; srl op0, op0, 24
- (set (match_dup 0) (lshiftrt:SI (match_dup 0) (const_int 24)))]
- "TARGET_Z196"
- "operands[2] = gen_reg_rtx (SImode);")
-
-(define_expand "popcounthi2"
- [; popcnt op0, op1
- (parallel [(set (match_operand:HI 0 "register_operand" "")
- (unspec:HI [(match_operand:HI 1 "register_operand")]
- UNSPEC_POPCNT))
- (clobber (reg:CC CC_REGNUM))])
- ; sllk op2, op0, 8
- (set (match_dup 2)
- (ashift:SI (match_dup 0) (const_int 8)))
- ; ar op0, op2
- (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))
- (clobber (reg:CC CC_REGNUM))])
- ; srl op0, op0, 8
- (set (match_dup 0) (lshiftrt:HI (match_dup 0) (const_int 8)))]
- "TARGET_Z196"
- "operands[2] = gen_reg_rtx (SImode);")
-
-(define_expand "popcountqi2"
- [; popcnt op0, op1
- (parallel [(set (match_operand:QI 0 "register_operand" "")
- (unspec:QI [(match_operand:QI 1 "register_operand")]
- UNSPEC_POPCNT))
- (clobber (reg:CC CC_REGNUM))])]
- "TARGET_Z196"
- "")
-
-;;
-;;- Copy sign instructions
-;;
-
-(define_insn "copysign<mode>3"
- [(set (match_operand:FP 0 "register_operand" "=f")
- (unspec:FP [(match_operand:FP 1 "register_operand" "<fT0>")
- (match_operand:FP 2 "register_operand" "f")]
- UNSPEC_COPYSIGN))]
- "TARGET_Z196"
- "cpsdr\t%0,%2,%1"
- [(set_attr "op_type" "RRF")
- (set_attr "type" "fsimp<mode>")])
diff --git a/gcc-4.7/gcc/config/s390/s390.opt b/gcc-4.7/gcc/config/s390/s390.opt
deleted file mode 100644
index 51b395ee9..000000000
--- a/gcc-4.7/gcc/config/s390/s390.opt
+++ /dev/null
@@ -1,148 +0,0 @@
-; Options for the S/390 / zSeries port of the compiler.
-
-; Copyright (C) 2005, 2006, 2007, 2010, 2011 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-HeaderInclude
-config/s390/s390-opts.h
-
-; The architecture name to use in diagnostics.
-Variable
-const char *s390_arch_string
-
-Variable
-int s390_tune_flags
-
-Variable
-int s390_arch_flags
-
-Variable
-HOST_WIDE_INT s390_warn_framesize = 0
-
-m31
-Target Report RejectNegative Negative(m64) InverseMask(64BIT)
-31 bit ABI
-
-m64
-Target Report RejectNegative Negative(m31) Mask(64BIT)
-64 bit ABI
-
-march=
-Target RejectNegative Joined Enum(processor_type) Var(s390_arch) Init(PROCESSOR_max)
-Generate code for given CPU
-
-Enum
-Name(processor_type) Type(enum processor_type)
-
-EnumValue
-Enum(processor_type) String(g5) Value(PROCESSOR_9672_G5)
-
-EnumValue
-Enum(processor_type) String(g6) Value(PROCESSOR_9672_G6)
-
-EnumValue
-Enum(processor_type) String(z900) Value(PROCESSOR_2064_Z900)
-
-EnumValue
-Enum(processor_type) String(z990) Value(PROCESSOR_2084_Z990)
-
-EnumValue
-Enum(processor_type) String(z9-109) Value(PROCESSOR_2094_Z9_109)
-
-EnumValue
-Enum(processor_type) String(z9-ec) Value(PROCESSOR_2094_Z9_EC)
-
-EnumValue
-Enum(processor_type) String(z10) Value(PROCESSOR_2097_Z10)
-
-EnumValue
-Enum(processor_type) String(z196) Value(PROCESSOR_2817_Z196)
-
-mbackchain
-Target Report Mask(BACKCHAIN)
-Maintain backchain pointer
-
-mdebug
-Target Report Mask(DEBUG_ARG)
-Additional debug prints
-
-mesa
-Target Report RejectNegative Negative(mzarch) InverseMask(ZARCH)
-ESA/390 architecture
-
-mhard-dfp
-Target Report Mask(HARD_DFP)
-Enable decimal floating point hardware support
-
-mhard-float
-Target Report RejectNegative Negative(msoft-float) InverseMask(SOFT_FLOAT, HARD_FLOAT)
-Enable hardware floating point
-
-mlong-double-128
-Target Report RejectNegative Negative(mlong-double-64) Mask(LONG_DOUBLE_128)
-Use 128-bit long double
-
-mlong-double-64
-Target Report RejectNegative Negative(mlong-double-128) InverseMask(LONG_DOUBLE_128)
-Use 64-bit long double
-
-mpacked-stack
-Target Report Mask(PACKED_STACK)
-Use packed stack layout
-
-msmall-exec
-Target Report Mask(SMALL_EXEC)
-Use bras for executable < 64k
-
-msoft-float
-Target Report RejectNegative Negative(mhard-float) Mask(SOFT_FLOAT)
-Disable hardware floating point
-
-mstack-guard=
-Target RejectNegative Joined UInteger Var(s390_stack_guard)
-Set the max. number of bytes which has to be left to stack size before a trap instruction is triggered
-
-mstack-size=
-Target RejectNegative Joined UInteger Var(s390_stack_size)
-Emit extra code in the function prologue in order to trap if the stack size exceeds the given limit
-
-mtune=
-Target RejectNegative Joined Enum(processor_type) Var(s390_tune) Init(PROCESSOR_max)
-Schedule code for given CPU
-
-mmvcle
-Target Report Mask(MVCLE)
-mvcle use
-
-mwarn-dynamicstack
-Target RejectNegative Var(s390_warn_dynamicstack_p)
-Warn if a function uses alloca or creates an array with dynamic size
-
-mwarn-framesize=
-Target RejectNegative Joined
-Warn if a single function's framesize exceeds the given framesize
-
-mzarch
-Target Report RejectNegative Negative(mesa) Mask(ZARCH)
-z/Architecture
-
-mbranch-cost=
-Target Report Joined RejectNegative UInteger Var(s390_branch_cost) Init(1)
-Set the branch costs for conditional branch instructions. Reasonable
-values are small, non-negative integers. The default branch cost is
-1.
diff --git a/gcc-4.7/gcc/config/s390/s390x.h b/gcc-4.7/gcc/config/s390/s390x.h
deleted file mode 100644
index 3712eb156..000000000
--- a/gcc-4.7/gcc/config/s390/s390x.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Definitions of target machine for IBM zSeries 64-bit
- Copyright (C) 2002, 2007 Free Software Foundation, Inc.
- Contributed by Hartmut Penner (hpenner@de.ibm.com) and
- Ulrich Weigand (uweigand@de.ibm.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef _S390X_H
-#define _S390X_H
-
-#define DEFAULT_TARGET_64BIT
-
-#endif
diff --git a/gcc-4.7/gcc/config/s390/t-linux64 b/gcc-4.7/gcc/config/s390/t-linux64
deleted file mode 100644
index ede76a2cb..000000000
--- a/gcc-4.7/gcc/config/s390/t-linux64
+++ /dev/null
@@ -1,10 +0,0 @@
-# On Debian, Ubuntu and other derivative distributions, the 32bit libraries
-# are found in /lib32 and /usr/lib32, /lib64 and /usr/lib64 are symlinks to
-# /lib and /usr/lib, while other distributions install libraries into /lib64
-# and /usr/lib64. The LSB does not enforce the use of /lib64 and /usr/lib64,
-# it doesn't tell anything about the 32bit libraries on those systems. Set
-# MULTILIB_OSDIRNAMES according to what is found on the target.
-
-MULTILIB_OPTIONS = m64/m31
-MULTILIB_DIRNAMES = 64 32
-MULTILIB_OSDIRNAMES = ../lib64 $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)
diff --git a/gcc-4.7/gcc/config/s390/tpf.h b/gcc-4.7/gcc/config/s390/tpf.h
deleted file mode 100644
index e4a1b50b6..000000000
--- a/gcc-4.7/gcc/config/s390/tpf.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
- Copyright (C) 2003, 2004, 2005, 2007, 2009,
- 2010, 2011 Free Software Foundation, Inc.
- Contributed by P.J. Darcy (darcypj@us.ibm.com),
- Hartmut Penner (hpenner@de.ibm.com), and
- Ulrich Weigand (uweigand@de.ibm.com).
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#ifndef _TPF_H
-#define _TPF_H
-
-/* TPF wants the following macros defined/undefined as follows. */
-#undef TARGET_TPF
-#define TARGET_TPF 1
-#undef ASM_APP_ON
-#define ASM_APP_ON "#APP\n"
-#undef ASM_APP_OFF
-#define ASM_APP_OFF "#NO_APP\n"
-#define NO_IMPLICIT_EXTERN_C
-#define TARGET_POSIX_IO
-
-#undef SIZE_TYPE
-#define SIZE_TYPE ("long unsigned int")
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE ("long int")
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 32
-
-
-/* TPF OS specific stack-pointer offset. */
-#undef STACK_POINTER_OFFSET
-#define STACK_POINTER_OFFSET 448
-
-/* When building for TPF, set a generic default target that is 64 bits. Also
- enable TPF profiling support and the standard backchain by default. */
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_TPF_PROFILING | MASK_64BIT | MASK_ZARCH \
- | MASK_HARD_DFP | MASK_BACKCHAIN)
-
-/* Exception handling. */
-
-/* Select a format to encode pointers in exception handling data. */
-#undef ASM_PREFERRED_EH_DATA_FORMAT
-#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) DW_EH_PE_absptr
-
-/* TPF OS specific compiler settings. */
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("tpf"); \
- builtin_assert ("system=tpf"); \
- builtin_define ("__ELF__"); \
- } \
- while (0)
-
-
-#define EXTRA_SPECS \
- { "entry_spec", ENTRY_SPEC }
-
-/* Make TPF specific spec file settings here. */
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{mmain:crt0%O%s} crtbeginS%O%s crt3%O%s"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "crtendS%O%s"
-
-#undef CC1_SPEC
-#define CC1_SPEC "%{!fverbose-asm: -fverbose-asm}"
-
-/* The GNU C++ standard library requires that these macros be defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
-
-#undef ASM_SPEC
-#define ASM_SPEC "%{m31&m64}%{mesa&mzarch}%{march=*} \
- -alshd=%b.lst"
-
-/* It would be nice to get the system linker script define the ones that it
- needed. */
-#undef LIB_SPEC
-#define LIB_SPEC "-lCTIS -lCISO -lCLBM -lCTAL -lCFVS -lCTBX -lCTXO \
- -lCJ00 -lCTDF -lCOMX -lCOMS -lCTHD -lCTAD -lTPFSTUB"
-
-#undef TARGET_C99_FUNCTIONS
-#define TARGET_C99_FUNCTIONS 1
-
-#define ENTRY_SPEC "%{mmain:-entry=_start} \
- %{!mmain:-entry=0}"
-
-/* All linking is done shared on TPF-OS. */
-/* FIXME: When binutils patch for new emulation is committed
- then change emulation to elf64_s390_tpf. */
-#undef LINK_SPEC
-#define LINK_SPEC \
- "-m elf64_s390 \
- %{static:%estatic is not supported on TPF-OS} \
- %{shared: -shared} \
- %{!shared:-shared} \
- %(entry_spec)"
-
-/* IBM copies these libraries over with these names. */
-#define MATH_LIBRARY "CLBM"
-#define LIBSTDCXX "CPP1"
-#endif /* ! _TPF_H */
diff --git a/gcc-4.7/gcc/config/s390/tpf.md b/gcc-4.7/gcc/config/s390/tpf.md
deleted file mode 100644
index e1106a052..000000000
--- a/gcc-4.7/gcc/config/s390/tpf.md
+++ /dev/null
@@ -1,33 +0,0 @@
-;; S390 TPF-OS specific machine patterns
-;; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
-;;
-;; This file is part of GCC.
-;;
-;; GCC is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3, or (at your option)
-;; any later version.
-;;
-;; GCC is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-;;
-;; You should have received a copy of the GNU General Public License
-;; along with GCC; see the file COPYING3. If not see
-;; <http://www.gnu.org/licenses/>.
-
-(define_insn "prologue_tpf"
- [(unspec_volatile [(const_int 0)] UNSPECV_TPF_PROLOGUE)
- (clobber (reg:DI 1))]
- "TARGET_TPF_PROFILING"
- "larl\t%%r1,.+14\;tm\t4065,255\;bnz\t4064"
- [(set_attr "length" "14")])
-
-
-(define_insn "epilogue_tpf"
- [(unspec_volatile [(const_int 0)] UNSPECV_TPF_EPILOGUE)
- (clobber (reg:DI 1))]
- "TARGET_TPF_PROFILING"
- "larl\t%%r1,.+14\;tm\t4071,255\;bnz\t4070"
- [(set_attr "length" "14")])
diff --git a/gcc-4.7/gcc/config/s390/tpf.opt b/gcc-4.7/gcc/config/s390/tpf.opt
deleted file mode 100644
index c3cde22b6..000000000
--- a/gcc-4.7/gcc/config/s390/tpf.opt
+++ /dev/null
@@ -1,27 +0,0 @@
-; Options for the TPF-OS port of the compiler.
-
-; Copyright (C) 2005, 2007 Free Software Foundation, Inc.
-;
-; This file is part of GCC.
-;
-; GCC is free software; you can redistribute it and/or modify it under
-; the terms of the GNU General Public License as published by the Free
-; Software Foundation; either version 3, or (at your option) any later
-; version.
-;
-; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-; WARRANTY; without even the implied warranty of MERCHANTABILITY or
-; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-; for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with GCC; see the file COPYING3. If not see
-; <http://www.gnu.org/licenses/>.
-
-mtpf-trace
-Target Report Mask(TPF_PROFILING)
-Enable TPF-OS tracing code
-
-mmain
-Target Report
-Specify main object for TPF-OS