xref: /openbmc/qemu/tcg/s390x/tcg-target.c.inc (revision 994f8717ee063ec6101c5d49714e3fab2bb2f27c)
13704993fSRichard Henderson/*
23704993fSRichard Henderson * Tiny Code Generator for QEMU
33704993fSRichard Henderson *
43704993fSRichard Henderson * Copyright (c) 2009 Ulrich Hecht <uli@suse.de>
53704993fSRichard Henderson * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
63704993fSRichard Henderson * Copyright (c) 2010 Richard Henderson <rth@twiddle.net>
73704993fSRichard Henderson *
83704993fSRichard Henderson * Permission is hereby granted, free of charge, to any person obtaining a copy
93704993fSRichard Henderson * of this software and associated documentation files (the "Software"), to deal
103704993fSRichard Henderson * in the Software without restriction, including without limitation the rights
113704993fSRichard Henderson * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
123704993fSRichard Henderson * copies of the Software, and to permit persons to whom the Software is
133704993fSRichard Henderson * furnished to do so, subject to the following conditions:
143704993fSRichard Henderson *
153704993fSRichard Henderson * The above copyright notice and this permission notice shall be included in
163704993fSRichard Henderson * all copies or substantial portions of the Software.
173704993fSRichard Henderson *
183704993fSRichard Henderson * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
193704993fSRichard Henderson * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
203704993fSRichard Henderson * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
213704993fSRichard Henderson * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
223704993fSRichard Henderson * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
233704993fSRichard Henderson * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
243704993fSRichard Henderson * THE SOFTWARE.
253704993fSRichard Henderson */
263704993fSRichard Henderson
271cd49868SRichard Henderson#include "../tcg-ldst.c.inc"
283704993fSRichard Henderson#include "../tcg-pool.c.inc"
293704993fSRichard Henderson#include "elf.h"
303704993fSRichard Henderson
314134083fSRichard Henderson#define TCG_CT_CONST_S16        (1 << 8)
324134083fSRichard Henderson#define TCG_CT_CONST_S32        (1 << 9)
33cbaddf30SRichard Henderson#define TCG_CT_CONST_U32        (1 << 10)
344134083fSRichard Henderson#define TCG_CT_CONST_ZERO       (1 << 11)
354134083fSRichard Henderson#define TCG_CT_CONST_P32        (1 << 12)
364134083fSRichard Henderson#define TCG_CT_CONST_INV        (1 << 13)
374134083fSRichard Henderson#define TCG_CT_CONST_INVRISBG   (1 << 14)
38d95b51d3SRichard Henderson#define TCG_CT_CONST_CMP        (1 << 15)
393704993fSRichard Henderson#define TCG_CT_CONST_M1         (1 << 16)
403704993fSRichard Henderson
4134ef7676SRichard Henderson#define ALL_GENERAL_REGS     MAKE_64BIT_MASK(0, 16)
4234ef7676SRichard Henderson#define ALL_VECTOR_REGS      MAKE_64BIT_MASK(32, 32)
433704993fSRichard Henderson
443704993fSRichard Henderson/* Several places within the instruction set 0 means "no register"
453704993fSRichard Henderson   rather than TCG_REG_R0.  */
463704993fSRichard Henderson#define TCG_REG_NONE    0
473704993fSRichard Henderson
483704993fSRichard Henderson/* A scratch register that may be be used throughout the backend.  */
493704993fSRichard Henderson#define TCG_TMP0        TCG_REG_R1
503704993fSRichard Henderson#define TCG_VEC_TMP0    TCG_REG_V31
513704993fSRichard Henderson
523704993fSRichard Henderson#define TCG_GUEST_BASE_REG TCG_REG_R13
533704993fSRichard Henderson
543704993fSRichard Henderson/* All of the following instructions are prefixed with their instruction
553704993fSRichard Henderson   format, and are defined as 8- or 16-bit quantities, even when the two
563704993fSRichard Henderson   halves of the 16-bit quantity may appear 32 bits apart in the insn.
573704993fSRichard Henderson   This makes it easy to copy the values from the tables in Appendix B.  */
583704993fSRichard Hendersontypedef enum S390Opcode {
593704993fSRichard Henderson    RIL_AFI     = 0xc209,
603704993fSRichard Henderson    RIL_AGFI    = 0xc208,
613704993fSRichard Henderson    RIL_ALFI    = 0xc20b,
623704993fSRichard Henderson    RIL_ALGFI   = 0xc20a,
633704993fSRichard Henderson    RIL_BRASL   = 0xc005,
643704993fSRichard Henderson    RIL_BRCL    = 0xc004,
653704993fSRichard Henderson    RIL_CFI     = 0xc20d,
663704993fSRichard Henderson    RIL_CGFI    = 0xc20c,
673704993fSRichard Henderson    RIL_CLFI    = 0xc20f,
683704993fSRichard Henderson    RIL_CLGFI   = 0xc20e,
693704993fSRichard Henderson    RIL_CLRL    = 0xc60f,
703704993fSRichard Henderson    RIL_CLGRL   = 0xc60a,
713704993fSRichard Henderson    RIL_CRL     = 0xc60d,
723704993fSRichard Henderson    RIL_CGRL    = 0xc608,
733704993fSRichard Henderson    RIL_IIHF    = 0xc008,
743704993fSRichard Henderson    RIL_IILF    = 0xc009,
753704993fSRichard Henderson    RIL_LARL    = 0xc000,
763704993fSRichard Henderson    RIL_LGFI    = 0xc001,
773704993fSRichard Henderson    RIL_LGRL    = 0xc408,
783704993fSRichard Henderson    RIL_LLIHF   = 0xc00e,
793704993fSRichard Henderson    RIL_LLILF   = 0xc00f,
803704993fSRichard Henderson    RIL_LRL     = 0xc40d,
813704993fSRichard Henderson    RIL_MSFI    = 0xc201,
823704993fSRichard Henderson    RIL_MSGFI   = 0xc200,
833704993fSRichard Henderson    RIL_NIHF    = 0xc00a,
843704993fSRichard Henderson    RIL_NILF    = 0xc00b,
853704993fSRichard Henderson    RIL_OIHF    = 0xc00c,
863704993fSRichard Henderson    RIL_OILF    = 0xc00d,
873704993fSRichard Henderson    RIL_SLFI    = 0xc205,
883704993fSRichard Henderson    RIL_SLGFI   = 0xc204,
893704993fSRichard Henderson    RIL_XIHF    = 0xc006,
903704993fSRichard Henderson    RIL_XILF    = 0xc007,
913704993fSRichard Henderson
923704993fSRichard Henderson    RI_AGHI     = 0xa70b,
933704993fSRichard Henderson    RI_AHI      = 0xa70a,
943704993fSRichard Henderson    RI_BRC      = 0xa704,
953704993fSRichard Henderson    RI_CHI      = 0xa70e,
963704993fSRichard Henderson    RI_CGHI     = 0xa70f,
973704993fSRichard Henderson    RI_IIHH     = 0xa500,
983704993fSRichard Henderson    RI_IIHL     = 0xa501,
993704993fSRichard Henderson    RI_IILH     = 0xa502,
1003704993fSRichard Henderson    RI_IILL     = 0xa503,
1013704993fSRichard Henderson    RI_LGHI     = 0xa709,
1023704993fSRichard Henderson    RI_LLIHH    = 0xa50c,
1033704993fSRichard Henderson    RI_LLIHL    = 0xa50d,
1043704993fSRichard Henderson    RI_LLILH    = 0xa50e,
1053704993fSRichard Henderson    RI_LLILL    = 0xa50f,
1063704993fSRichard Henderson    RI_MGHI     = 0xa70d,
1073704993fSRichard Henderson    RI_MHI      = 0xa70c,
1083704993fSRichard Henderson    RI_NIHH     = 0xa504,
1093704993fSRichard Henderson    RI_NIHL     = 0xa505,
1103704993fSRichard Henderson    RI_NILH     = 0xa506,
1113704993fSRichard Henderson    RI_NILL     = 0xa507,
1123704993fSRichard Henderson    RI_OIHH     = 0xa508,
1133704993fSRichard Henderson    RI_OIHL     = 0xa509,
1141cd49868SRichard Henderson    RI_OILH     = 0xa50a,
115585b7a42SRichard Henderson    RI_OILL     = 0xa50b,
116585b7a42SRichard Henderson    RI_TMLL     = 0xa701,
117585b7a42SRichard Henderson    RI_TMLH     = 0xa700,
1183704993fSRichard Henderson    RI_TMHL     = 0xa703,
119d84ca804SRichard Henderson    RI_TMHH     = 0xa702,
120d84ca804SRichard Henderson
121d84ca804SRichard Henderson    RIEb_CGRJ    = 0xec64,
122d84ca804SRichard Henderson    RIEb_CLGRJ   = 0xec65,
123d84ca804SRichard Henderson    RIEb_CLRJ    = 0xec77,
124d84ca804SRichard Henderson    RIEb_CRJ     = 0xec76,
125d84ca804SRichard Henderson
126d84ca804SRichard Henderson    RIEc_CGIJ    = 0xec7c,
127d84ca804SRichard Henderson    RIEc_CIJ     = 0xec7e,
128d84ca804SRichard Henderson    RIEc_CLGIJ   = 0xec7d,
129d84ca804SRichard Henderson    RIEc_CLIJ    = 0xec7f,
130d84ca804SRichard Henderson
131d84ca804SRichard Henderson    RIEf_RISBG   = 0xec55,
1323704993fSRichard Henderson
1333704993fSRichard Henderson    RIEg_LOCGHI  = 0xec46,
1343704993fSRichard Henderson
1353704993fSRichard Henderson    RRE_AGR     = 0xb908,
1363704993fSRichard Henderson    RRE_ALGR    = 0xb90a,
1378b1b4597SRichard Henderson    RRE_ALCR    = 0xb998,
1383704993fSRichard Henderson    RRE_ALCGR   = 0xb988,
1393704993fSRichard Henderson    RRE_ALGFR   = 0xb91a,
1403704993fSRichard Henderson    RRE_CGR     = 0xb920,
1413704993fSRichard Henderson    RRE_CLGR    = 0xb921,
1423704993fSRichard Henderson    RRE_DLGR    = 0xb987,
1433704993fSRichard Henderson    RRE_DLR     = 0xb997,
1443704993fSRichard Henderson    RRE_DSGFR   = 0xb91d,
1453704993fSRichard Henderson    RRE_DSGR    = 0xb90d,
1463704993fSRichard Henderson    RRE_FLOGR   = 0xb983,
1473704993fSRichard Henderson    RRE_LGBR    = 0xb906,
1483704993fSRichard Henderson    RRE_LCGR    = 0xb903,
1493704993fSRichard Henderson    RRE_LGFR    = 0xb914,
1503704993fSRichard Henderson    RRE_LGHR    = 0xb907,
1513704993fSRichard Henderson    RRE_LGR     = 0xb904,
1523704993fSRichard Henderson    RRE_LLGCR   = 0xb984,
1533704993fSRichard Henderson    RRE_LLGFR   = 0xb916,
1543704993fSRichard Henderson    RRE_LLGHR   = 0xb985,
1553704993fSRichard Henderson    RRE_LRVR    = 0xb91f,
1563704993fSRichard Henderson    RRE_LRVGR   = 0xb90f,
1573704993fSRichard Henderson    RRE_LTGR    = 0xb902,
1583704993fSRichard Henderson    RRE_MLGR    = 0xb986,
1593704993fSRichard Henderson    RRE_MSGR    = 0xb90c,
1603704993fSRichard Henderson    RRE_MSR     = 0xb252,
1613704993fSRichard Henderson    RRE_NGR     = 0xb980,
1623704993fSRichard Henderson    RRE_OGR     = 0xb981,
1633704993fSRichard Henderson    RRE_SGR     = 0xb909,
1643704993fSRichard Henderson    RRE_SLGR    = 0xb90b,
1653704993fSRichard Henderson    RRE_SLBR    = 0xb999,
1663704993fSRichard Henderson    RRE_SLBGR   = 0xb989,
167668ce343SRichard Henderson    RRE_XGR     = 0xb982,
16892c89a07SRichard Henderson
16992c89a07SRichard Henderson    RRFa_MGRK   = 0xb9ec,
1706c9b5c0fSRichard Henderson    RRFa_MSRKC  = 0xb9fd,
1716c9b5c0fSRichard Henderson    RRFa_MSGRKC = 0xb9ed,
1726c9b5c0fSRichard Henderson    RRFa_NCRK   = 0xb9f5,
1736c9b5c0fSRichard Henderson    RRFa_NCGRK  = 0xb9e5,
1746c9b5c0fSRichard Henderson    RRFa_NNRK   = 0xb974,
1756c9b5c0fSRichard Henderson    RRFa_NNGRK  = 0xb964,
1761dd06b1aSRichard Henderson    RRFa_NORK   = 0xb976,
1771dd06b1aSRichard Henderson    RRFa_NOGRK  = 0xb966,
1786c9b5c0fSRichard Henderson    RRFa_NRK    = 0xb9f4,
1796c9b5c0fSRichard Henderson    RRFa_NGRK   = 0xb9e4,
1806c9b5c0fSRichard Henderson    RRFa_NXRK   = 0xb977,
1816c9b5c0fSRichard Henderson    RRFa_NXGRK  = 0xb967,
1821dd06b1aSRichard Henderson    RRFa_OCRK   = 0xb975,
1831dd06b1aSRichard Henderson    RRFa_OCGRK  = 0xb965,
1841dd06b1aSRichard Henderson    RRFa_ORK    = 0xb9f6,
1851dd06b1aSRichard Henderson    RRFa_OGRK   = 0xb9e6,
1861dd06b1aSRichard Henderson    RRFa_SRK    = 0xb9f9,
1871dd06b1aSRichard Henderson    RRFa_SGRK   = 0xb9e9,
1881dd06b1aSRichard Henderson    RRFa_SLRK   = 0xb9fb,
1891dd06b1aSRichard Henderson    RRFa_SLGRK  = 0xb9eb,
1901dd06b1aSRichard Henderson    RRFa_XRK    = 0xb9f7,
1910bbf0f7aSRichard Henderson    RRFa_XGRK   = 0xb9e7,
1920bbf0f7aSRichard Henderson
1931dd06b1aSRichard Henderson    RRFam_SELGR = 0xb9e3,
1941dd06b1aSRichard Henderson
19529a5ea73SRichard Henderson    RRFc_LOCR   = 0xb9f2,
1963704993fSRichard Henderson    RRFc_LOCGR  = 0xb9e2,
1973704993fSRichard Henderson    RRFc_POPCNT = 0xb9e1,
1983704993fSRichard Henderson
1993704993fSRichard Henderson    RR_AR       = 0x1a,
2003704993fSRichard Henderson    RR_ALR      = 0x1e,
2013704993fSRichard Henderson    RR_BASR     = 0x0d,
2023704993fSRichard Henderson    RR_BCR      = 0x07,
2033704993fSRichard Henderson    RR_CLR      = 0x15,
2043704993fSRichard Henderson    RR_CR       = 0x19,
2053704993fSRichard Henderson    RR_DR       = 0x1d,
2063704993fSRichard Henderson    RR_LCR      = 0x13,
2073704993fSRichard Henderson    RR_LR       = 0x18,
2083704993fSRichard Henderson    RR_LTR      = 0x12,
2093704993fSRichard Henderson    RR_NR       = 0x14,
2103704993fSRichard Henderson    RR_OR       = 0x16,
2113704993fSRichard Henderson    RR_SR       = 0x1b,
2123704993fSRichard Henderson    RR_SLR      = 0x1f,
2133704993fSRichard Henderson    RR_XR       = 0x17,
2143704993fSRichard Henderson
2153704993fSRichard Henderson    RSY_RLL     = 0xeb1d,
2163704993fSRichard Henderson    RSY_RLLG    = 0xeb1c,
2173704993fSRichard Henderson    RSY_SLLG    = 0xeb0d,
2183704993fSRichard Henderson    RSY_SLLK    = 0xebdf,
2193704993fSRichard Henderson    RSY_SRAG    = 0xeb0a,
2203704993fSRichard Henderson    RSY_SRAK    = 0xebdc,
2213704993fSRichard Henderson    RSY_SRLG    = 0xeb0c,
2223704993fSRichard Henderson    RSY_SRLK    = 0xebde,
2233704993fSRichard Henderson
2243704993fSRichard Henderson    RS_SLL      = 0x89,
2253704993fSRichard Henderson    RS_SRA      = 0x8a,
2263704993fSRichard Henderson    RS_SRL      = 0x88,
2273704993fSRichard Henderson
2283704993fSRichard Henderson    RXY_AG      = 0xe308,
2293704993fSRichard Henderson    RXY_AY      = 0xe35a,
2303704993fSRichard Henderson    RXY_CG      = 0xe320,
2313704993fSRichard Henderson    RXY_CLG     = 0xe321,
2323704993fSRichard Henderson    RXY_CLY     = 0xe355,
2333704993fSRichard Henderson    RXY_CY      = 0xe359,
2343704993fSRichard Henderson    RXY_LAY     = 0xe371,
2353704993fSRichard Henderson    RXY_LB      = 0xe376,
2363704993fSRichard Henderson    RXY_LG      = 0xe304,
2373704993fSRichard Henderson    RXY_LGB     = 0xe377,
2383704993fSRichard Henderson    RXY_LGF     = 0xe314,
2393704993fSRichard Henderson    RXY_LGH     = 0xe315,
2403704993fSRichard Henderson    RXY_LHY     = 0xe378,
2413704993fSRichard Henderson    RXY_LLGC    = 0xe390,
2423704993fSRichard Henderson    RXY_LLGF    = 0xe316,
2434caad79fSRichard Henderson    RXY_LLGH    = 0xe391,
2443704993fSRichard Henderson    RXY_LMG     = 0xeb04,
2453704993fSRichard Henderson    RXY_LPQ     = 0xe38f,
2463704993fSRichard Henderson    RXY_LRV     = 0xe31e,
2473704993fSRichard Henderson    RXY_LRVG    = 0xe30f,
2483704993fSRichard Henderson    RXY_LRVH    = 0xe31f,
2493704993fSRichard Henderson    RXY_LY      = 0xe358,
2503704993fSRichard Henderson    RXY_NG      = 0xe380,
2513704993fSRichard Henderson    RXY_OG      = 0xe381,
2523704993fSRichard Henderson    RXY_STCY    = 0xe372,
2533704993fSRichard Henderson    RXY_STG     = 0xe324,
2544caad79fSRichard Henderson    RXY_STHY    = 0xe370,
2553704993fSRichard Henderson    RXY_STMG    = 0xeb24,
2563704993fSRichard Henderson    RXY_STPQ    = 0xe38e,
2573704993fSRichard Henderson    RXY_STRV    = 0xe33e,
2583704993fSRichard Henderson    RXY_STRVG   = 0xe32f,
2593704993fSRichard Henderson    RXY_STRVH   = 0xe33f,
2603704993fSRichard Henderson    RXY_STY     = 0xe350,
2613704993fSRichard Henderson    RXY_XG      = 0xe382,
2623704993fSRichard Henderson
2633704993fSRichard Henderson    RX_A        = 0x5a,
2643704993fSRichard Henderson    RX_C        = 0x59,
2653704993fSRichard Henderson    RX_L        = 0x58,
2663704993fSRichard Henderson    RX_LA       = 0x41,
2673704993fSRichard Henderson    RX_LH       = 0x48,
2683704993fSRichard Henderson    RX_ST       = 0x50,
2693704993fSRichard Henderson    RX_STC      = 0x42,
27079cada86SRichard Henderson    RX_STH      = 0x40,
27179cada86SRichard Henderson
27279cada86SRichard Henderson    VRIa_VGBM   = 0xe744,
27379cada86SRichard Henderson    VRIa_VREPI  = 0xe745,
27479cada86SRichard Henderson    VRIb_VGM    = 0xe746,
275ae77bbe5SRichard Henderson    VRIc_VREP   = 0xe74d,
276ae77bbe5SRichard Henderson
277b33ce725SRichard Henderson    VRRa_VLC    = 0xe7de,
278a429ee29SRichard Henderson    VRRa_VLP    = 0xe7df,
279a429ee29SRichard Henderson    VRRa_VLR    = 0xe756,
280a429ee29SRichard Henderson    VRRc_VA     = 0xe7f3,
281a429ee29SRichard Henderson    VRRc_VCEQ   = 0xe7f8,   /* we leave the m5 cs field 0 */
28222cb37b4SRichard Henderson    VRRc_VCH    = 0xe7fb,   /* " */
28322cb37b4SRichard Henderson    VRRc_VCHL   = 0xe7f9,   /* " */
28422cb37b4SRichard Henderson    VRRc_VERLLV = 0xe773,
28522cb37b4SRichard Henderson    VRRc_VESLV  = 0xe770,
286479b61cbSRichard Henderson    VRRc_VESRAV = 0xe77a,
287220db7a6SRichard Henderson    VRRc_VESRLV = 0xe778,
288220db7a6SRichard Henderson    VRRc_VML    = 0xe7a2,
289220db7a6SRichard Henderson    VRRc_VMN    = 0xe7fe,
290220db7a6SRichard Henderson    VRRc_VMNL   = 0xe7fc,
291a429ee29SRichard Henderson    VRRc_VMX    = 0xe7ff,
292ae77bbe5SRichard Henderson    VRRc_VMXL   = 0xe7fd,
29321eab5bfSRichard Henderson    VRRc_VN     = 0xe768,
294ae77bbe5SRichard Henderson    VRRc_VNC    = 0xe769,
29521eab5bfSRichard Henderson    VRRc_VNN    = 0xe76e,
296a429ee29SRichard Henderson    VRRc_VNO    = 0xe76b,
297ae77bbe5SRichard Henderson    VRRc_VNX    = 0xe76c,
2984223c9c1SRichard Henderson    VRRc_VO     = 0xe76a,
299a429ee29SRichard Henderson    VRRc_VOC    = 0xe76f,
3004223c9c1SRichard Henderson    VRRc_VPKS   = 0xe797,   /* we leave the m5 cs field 0 */
3014223c9c1SRichard Henderson    VRRc_VS     = 0xe7f7,
302a429ee29SRichard Henderson    VRRa_VUPH   = 0xe7d7,
3039bca986dSRichard Henderson    VRRa_VUPL   = 0xe7d6,
30479cada86SRichard Henderson    VRRc_VX     = 0xe76d,
305b33ce725SRichard Henderson    VRRe_VSEL   = 0xe78d,
30622cb37b4SRichard Henderson    VRRf_VLVGP  = 0xe762,
30722cb37b4SRichard Henderson
30822cb37b4SRichard Henderson    VRSa_VERLL  = 0xe733,
30922cb37b4SRichard Henderson    VRSa_VESL   = 0xe730,
310b33ce725SRichard Henderson    VRSa_VESRA  = 0xe73a,
311b33ce725SRichard Henderson    VRSa_VESRL  = 0xe738,
312b33ce725SRichard Henderson    VRSb_VLVG   = 0xe722,
3132dabf742SRichard Henderson    VRSc_VLGV   = 0xe721,
3142dabf742SRichard Henderson
31579cada86SRichard Henderson    VRX_VL      = 0xe706,
3162dabf742SRichard Henderson    VRX_VLLEZ   = 0xe704,
3172dabf742SRichard Henderson    VRX_VLREP   = 0xe705,
3182dabf742SRichard Henderson    VRX_VST     = 0xe70e,
3192dabf742SRichard Henderson    VRX_VSTEF   = 0xe70b,
3203704993fSRichard Henderson    VRX_VSTEG   = 0xe70a,
3213704993fSRichard Henderson
3223704993fSRichard Henderson    NOP         = 0x0707,
3233704993fSRichard Henderson} S390Opcode;
3243704993fSRichard Henderson
3253704993fSRichard Henderson#ifdef CONFIG_DEBUG_TCG
32634ef7676SRichard Hendersonstatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
32734ef7676SRichard Henderson    "%r0",  "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
32834ef7676SRichard Henderson    "%r8",  "%r9",  "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
32934ef7676SRichard Henderson    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
33034ef7676SRichard Henderson    "%v0",  "%v1",  "%v2",  "%v3",  "%v4",  "%v5",  "%v6",  "%v7",
33134ef7676SRichard Henderson    "%v8",  "%v9",  "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
3323704993fSRichard Henderson    "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
3333704993fSRichard Henderson    "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
3343704993fSRichard Henderson};
3353704993fSRichard Henderson#endif
3363704993fSRichard Henderson
3373704993fSRichard Henderson/* Since R6 is a potential argument register, choose it last of the
3383704993fSRichard Henderson   call-saved registers.  Likewise prefer the call-clobbered registers
3393704993fSRichard Henderson   in reverse order to maximize the chance of avoiding the arguments.  */
3403704993fSRichard Hendersonstatic const int tcg_target_reg_alloc_order[] = {
3413704993fSRichard Henderson    /* Call saved registers.  */
3423704993fSRichard Henderson    TCG_REG_R13,
3433704993fSRichard Henderson    TCG_REG_R12,
3443704993fSRichard Henderson    TCG_REG_R11,
3453704993fSRichard Henderson    TCG_REG_R10,
3463704993fSRichard Henderson    TCG_REG_R9,
3473704993fSRichard Henderson    TCG_REG_R8,
3483704993fSRichard Henderson    TCG_REG_R7,
3493704993fSRichard Henderson    TCG_REG_R6,
3503704993fSRichard Henderson    /* Call clobbered registers.  */
3513704993fSRichard Henderson    TCG_REG_R14,
3523704993fSRichard Henderson    TCG_REG_R0,
3533704993fSRichard Henderson    TCG_REG_R1,
3543704993fSRichard Henderson    /* Argument registers, in reverse order of allocation.  */
3553704993fSRichard Henderson    TCG_REG_R5,
3563704993fSRichard Henderson    TCG_REG_R4,
35734ef7676SRichard Henderson    TCG_REG_R3,
35834ef7676SRichard Henderson    TCG_REG_R2,
35934ef7676SRichard Henderson
36034ef7676SRichard Henderson    /* V8-V15 are call saved, and omitted. */
36134ef7676SRichard Henderson    TCG_REG_V0,
36234ef7676SRichard Henderson    TCG_REG_V1,
36334ef7676SRichard Henderson    TCG_REG_V2,
36434ef7676SRichard Henderson    TCG_REG_V3,
36534ef7676SRichard Henderson    TCG_REG_V4,
36634ef7676SRichard Henderson    TCG_REG_V5,
36734ef7676SRichard Henderson    TCG_REG_V6,
36834ef7676SRichard Henderson    TCG_REG_V7,
36934ef7676SRichard Henderson    TCG_REG_V16,
37034ef7676SRichard Henderson    TCG_REG_V17,
37134ef7676SRichard Henderson    TCG_REG_V18,
37234ef7676SRichard Henderson    TCG_REG_V19,
37334ef7676SRichard Henderson    TCG_REG_V20,
37434ef7676SRichard Henderson    TCG_REG_V21,
37534ef7676SRichard Henderson    TCG_REG_V22,
37634ef7676SRichard Henderson    TCG_REG_V23,
37734ef7676SRichard Henderson    TCG_REG_V24,
37834ef7676SRichard Henderson    TCG_REG_V25,
37934ef7676SRichard Henderson    TCG_REG_V26,
38034ef7676SRichard Henderson    TCG_REG_V27,
38134ef7676SRichard Henderson    TCG_REG_V28,
38234ef7676SRichard Henderson    TCG_REG_V29,
3833704993fSRichard Henderson    TCG_REG_V30,
3843704993fSRichard Henderson    TCG_REG_V31,
3853704993fSRichard Henderson};
3863704993fSRichard Henderson
3873704993fSRichard Hendersonstatic const int tcg_target_call_iarg_regs[] = {
3883704993fSRichard Henderson    TCG_REG_R2,
3893704993fSRichard Henderson    TCG_REG_R3,
3903704993fSRichard Henderson    TCG_REG_R4,
3913704993fSRichard Henderson    TCG_REG_R5,
3923704993fSRichard Henderson    TCG_REG_R6,
3935e3d0c19SRichard Henderson};
3945e3d0c19SRichard Henderson
3955e3d0c19SRichard Hendersonstatic TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
3965e3d0c19SRichard Henderson{
3975e3d0c19SRichard Henderson    tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
3985e3d0c19SRichard Henderson    tcg_debug_assert(slot == 0);
3993704993fSRichard Henderson    return TCG_REG_R2;
4003704993fSRichard Henderson}
4013704993fSRichard Henderson
4023704993fSRichard Henderson#define S390_CC_EQ      8
4033704993fSRichard Henderson#define S390_CC_LT      4
4043704993fSRichard Henderson#define S390_CC_GT      2
4053704993fSRichard Henderson#define S390_CC_OV      1
4063704993fSRichard Henderson#define S390_CC_NE      (S390_CC_LT | S390_CC_GT)
4073704993fSRichard Henderson#define S390_CC_LE      (S390_CC_LT | S390_CC_EQ)
4083704993fSRichard Henderson#define S390_CC_GE      (S390_CC_GT | S390_CC_EQ)
4093704993fSRichard Henderson#define S390_CC_NEVER   0
410585b7a42SRichard Henderson#define S390_CC_ALWAYS  15
411585b7a42SRichard Henderson
412585b7a42SRichard Henderson#define S390_TM_EQ      8  /* CC == 0 */
4133704993fSRichard Henderson#define S390_TM_NE      7  /* CC in {1,2,3} */
414585b7a42SRichard Henderson
4153704993fSRichard Henderson/* Condition codes that result from a COMPARE and COMPARE LOGICAL.  */
4163704993fSRichard Hendersonstatic const uint8_t tcg_cond_to_s390_cond[16] = {
417585b7a42SRichard Henderson    [TCG_COND_EQ]  = S390_CC_EQ,
418585b7a42SRichard Henderson    [TCG_COND_NE]  = S390_CC_NE,
4193704993fSRichard Henderson    [TCG_COND_TSTEQ] = S390_CC_EQ,
4203704993fSRichard Henderson    [TCG_COND_TSTNE] = S390_CC_NE,
4213704993fSRichard Henderson    [TCG_COND_LT]  = S390_CC_LT,
4223704993fSRichard Henderson    [TCG_COND_LE]  = S390_CC_LE,
4233704993fSRichard Henderson    [TCG_COND_GT]  = S390_CC_GT,
4243704993fSRichard Henderson    [TCG_COND_GE]  = S390_CC_GE,
4253704993fSRichard Henderson    [TCG_COND_LTU] = S390_CC_LT,
4263704993fSRichard Henderson    [TCG_COND_LEU] = S390_CC_LE,
4273704993fSRichard Henderson    [TCG_COND_GTU] = S390_CC_GT,
4283704993fSRichard Henderson    [TCG_COND_GEU] = S390_CC_GE,
4293704993fSRichard Henderson};
4303704993fSRichard Henderson
4313704993fSRichard Henderson/* Condition codes that result from a LOAD AND TEST.  Here, we have no
432585b7a42SRichard Henderson   unsigned instruction variation, however since the test is vs zero we
4333704993fSRichard Henderson   can re-map the outcomes appropriately.  */
4343704993fSRichard Hendersonstatic const uint8_t tcg_cond_to_ltr_cond[16] = {
435585b7a42SRichard Henderson    [TCG_COND_EQ]  = S390_CC_EQ,
436585b7a42SRichard Henderson    [TCG_COND_NE]  = S390_CC_NE,
4373704993fSRichard Henderson    [TCG_COND_TSTEQ] = S390_CC_ALWAYS,
4383704993fSRichard Henderson    [TCG_COND_TSTNE] = S390_CC_NEVER,
4393704993fSRichard Henderson    [TCG_COND_LT]  = S390_CC_LT,
4403704993fSRichard Henderson    [TCG_COND_LE]  = S390_CC_LE,
4413704993fSRichard Henderson    [TCG_COND_GT]  = S390_CC_GT,
4423704993fSRichard Henderson    [TCG_COND_GE]  = S390_CC_GE,
4433704993fSRichard Henderson    [TCG_COND_LTU] = S390_CC_NEVER,
4443704993fSRichard Henderson    [TCG_COND_LEU] = S390_CC_EQ,
4453704993fSRichard Henderson    [TCG_COND_GTU] = S390_CC_NE,
4463704993fSRichard Henderson    [TCG_COND_GEU] = S390_CC_ALWAYS,
4473704993fSRichard Henderson};
44834ef7676SRichard Henderson
4493704993fSRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
4502dabf742SRichard Hendersonuint64_t s390_facilities[3];
4512dabf742SRichard Henderson
4522dabf742SRichard Hendersonstatic inline bool is_general_reg(TCGReg r)
4532dabf742SRichard Henderson{
4542dabf742SRichard Henderson    return r <= TCG_REG_R15;
4552dabf742SRichard Henderson}
4562dabf742SRichard Henderson
4572dabf742SRichard Hendersonstatic inline bool is_vector_reg(TCGReg r)
4582dabf742SRichard Henderson{
4592dabf742SRichard Henderson    return r >= TCG_REG_V0 && r <= TCG_REG_V31;
4603704993fSRichard Henderson}
4613704993fSRichard Henderson
4623704993fSRichard Hendersonstatic bool patch_reloc(tcg_insn_unit *src_rw, int type,
4633704993fSRichard Henderson                        intptr_t value, intptr_t addend)
4643704993fSRichard Henderson{
4653704993fSRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
4663704993fSRichard Henderson    intptr_t pcrel2;
4673704993fSRichard Henderson    uint32_t old;
4683704993fSRichard Henderson
4693704993fSRichard Henderson    value += addend;
4703704993fSRichard Henderson    pcrel2 = (tcg_insn_unit *)value - src_rx;
4713704993fSRichard Henderson
4723704993fSRichard Henderson    switch (type) {
4733704993fSRichard Henderson    case R_390_PC16DBL:
4743704993fSRichard Henderson        if (pcrel2 == (int16_t)pcrel2) {
4753704993fSRichard Henderson            tcg_patch16(src_rw, pcrel2);
4763704993fSRichard Henderson            return true;
4773704993fSRichard Henderson        }
4783704993fSRichard Henderson        break;
4793704993fSRichard Henderson    case R_390_PC32DBL:
4803704993fSRichard Henderson        if (pcrel2 == (int32_t)pcrel2) {
4813704993fSRichard Henderson            tcg_patch32(src_rw, pcrel2);
4823704993fSRichard Henderson            return true;
4833704993fSRichard Henderson        }
4843704993fSRichard Henderson        break;
4853704993fSRichard Henderson    case R_390_20:
4863704993fSRichard Henderson        if (value == sextract64(value, 0, 20)) {
4873704993fSRichard Henderson            old = *(uint32_t *)src_rw & 0xf00000ff;
4883704993fSRichard Henderson            old |= ((value & 0xfff) << 16) | ((value & 0xff000) >> 4);
4893704993fSRichard Henderson            tcg_patch32(src_rw, old);
4903704993fSRichard Henderson            return true;
4913704993fSRichard Henderson        }
4923704993fSRichard Henderson        break;
4933704993fSRichard Henderson    default:
4943704993fSRichard Henderson        g_assert_not_reached();
4953704993fSRichard Henderson    }
4963704993fSRichard Henderson    return false;
497b2509accSRichard Henderson}
498b2509accSRichard Henderson
499b2509accSRichard Hendersonstatic int is_const_p16(uint64_t val)
500b2509accSRichard Henderson{
501b2509accSRichard Henderson    for (int i = 0; i < 4; ++i) {
502b2509accSRichard Henderson        uint64_t mask = 0xffffull << (i * 16);
503b2509accSRichard Henderson        if ((val & ~mask) == 0) {
504b2509accSRichard Henderson            return i;
505b2509accSRichard Henderson        }
506b2509accSRichard Henderson    }
507b2509accSRichard Henderson    return -1;
508b2509accSRichard Henderson}
509b2509accSRichard Henderson
510b2509accSRichard Hendersonstatic int is_const_p32(uint64_t val)
511b2509accSRichard Henderson{
512b2509accSRichard Henderson    if ((val & 0xffffffff00000000ull) == 0) {
513b2509accSRichard Henderson        return 0;
514b2509accSRichard Henderson    }
515b2509accSRichard Henderson    if ((val & 0x00000000ffffffffull) == 0) {
516b2509accSRichard Henderson        return 1;
517b2509accSRichard Henderson    }
518b2509accSRichard Henderson    return -1;
5194134083fSRichard Henderson}
5204134083fSRichard Henderson
5214134083fSRichard Henderson/*
5224134083fSRichard Henderson * Accept bit patterns like these:
5234134083fSRichard Henderson *  0....01....1
5244134083fSRichard Henderson *  1....10....0
5254134083fSRichard Henderson *  1..10..01..1
5264134083fSRichard Henderson *  0..01..10..0
5274134083fSRichard Henderson * Copied from gcc sources.
5284134083fSRichard Henderson */
5294134083fSRichard Hendersonstatic bool risbg_mask(uint64_t c)
5304134083fSRichard Henderson{
5314134083fSRichard Henderson    uint64_t lsb;
5324134083fSRichard Henderson    /* We don't change the number of transitions by inverting,
5334134083fSRichard Henderson       so make sure we start with the LSB zero.  */
5344134083fSRichard Henderson    if (c & 1) {
5354134083fSRichard Henderson        c = ~c;
5364134083fSRichard Henderson    }
5374134083fSRichard Henderson    /* Reject all zeros or all ones.  */
5384134083fSRichard Henderson    if (c == 0) {
5394134083fSRichard Henderson        return false;
5404134083fSRichard Henderson    }
5414134083fSRichard Henderson    /* Find the first transition.  */
5424134083fSRichard Henderson    lsb = c & -c;
5434134083fSRichard Henderson    /* Invert to look for a second transition.  */
5444134083fSRichard Henderson    c = ~c;
5454134083fSRichard Henderson    /* Erase the first transition.  */
5464134083fSRichard Henderson    c &= -lsb;
5474134083fSRichard Henderson    /* Find the second transition, if any.  */
5484134083fSRichard Henderson    lsb = c & -c;
5494134083fSRichard Henderson    /* Match if all the bits are 1's, or if c is zero.  */
5504134083fSRichard Henderson    return c == -lsb;
5513704993fSRichard Henderson}
55221e9a8aeSRichard Henderson
55321e9a8aeSRichard Henderson/* Test if a constant matches the constraint. */
5543704993fSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct,
555585b7a42SRichard Henderson                                   TCGType type, TCGCond cond, int vece)
556585b7a42SRichard Henderson{
5573704993fSRichard Henderson    uint64_t uval = val;
558cbaddf30SRichard Henderson
5593704993fSRichard Henderson    if (ct & TCG_CT_CONST) {
5603704993fSRichard Henderson        return true;
561585b7a42SRichard Henderson    }
5623704993fSRichard Henderson    if (type == TCG_TYPE_I32) {
5633704993fSRichard Henderson        uval = (uint32_t)val;
5643704993fSRichard Henderson        val = (int32_t)val;
565d95b51d3SRichard Henderson    }
566*994f8717SPaolo Bonzini
567*994f8717SPaolo Bonzini    if (ct & TCG_CT_CONST_CMP) {
568*994f8717SPaolo Bonzini        if (is_tst_cond(cond)) {
569*994f8717SPaolo Bonzini            if (is_const_p16(uval) >= 0) {
570*994f8717SPaolo Bonzini                return true;  /* TMxx */
571*994f8717SPaolo Bonzini            }
572*994f8717SPaolo Bonzini            if (risbg_mask(uval)) {
573*994f8717SPaolo Bonzini                return true;  /* RISBG */
574*994f8717SPaolo Bonzini            }
575*994f8717SPaolo Bonzini            return false;
576*994f8717SPaolo Bonzini        }
577*994f8717SPaolo Bonzini
578*994f8717SPaolo Bonzini        if (type == TCG_TYPE_I32) {
579*994f8717SPaolo Bonzini            return true;
580d95b51d3SRichard Henderson        }
581d95b51d3SRichard Henderson
582d95b51d3SRichard Henderson        switch (cond) {
583d95b51d3SRichard Henderson        case TCG_COND_EQ:
584d95b51d3SRichard Henderson        case TCG_COND_NE:
585d95b51d3SRichard Henderson            ct |= TCG_CT_CONST_S32 | TCG_CT_CONST_U32;  /* CGFI or CLGFI */
586d95b51d3SRichard Henderson            break;
587d95b51d3SRichard Henderson        case TCG_COND_LT:
588d95b51d3SRichard Henderson        case TCG_COND_GE:
589d95b51d3SRichard Henderson        case TCG_COND_LE:
590d95b51d3SRichard Henderson        case TCG_COND_GT:
591d95b51d3SRichard Henderson            ct |= TCG_CT_CONST_S32;  /* CGFI */
592d95b51d3SRichard Henderson            break;
593d95b51d3SRichard Henderson        case TCG_COND_LTU:
594d95b51d3SRichard Henderson        case TCG_COND_GEU:
595d95b51d3SRichard Henderson        case TCG_COND_LEU:
596d95b51d3SRichard Henderson        case TCG_COND_GTU:
597585b7a42SRichard Henderson            ct |= TCG_CT_CONST_U32;  /* CLGFI */
598585b7a42SRichard Henderson            break;
599*994f8717SPaolo Bonzini        case TCG_COND_TSTNE:
600d95b51d3SRichard Henderson        case TCG_COND_TSTEQ:
601d95b51d3SRichard Henderson            /* checked above, fallthru */
602d95b51d3SRichard Henderson        default:
603d95b51d3SRichard Henderson            g_assert_not_reached();
604d95b51d3SRichard Henderson        }
605cbaddf30SRichard Henderson    }
606cbaddf30SRichard Henderson
607cbaddf30SRichard Henderson    if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
608cbaddf30SRichard Henderson        return true;
609cbaddf30SRichard Henderson    }
610cbaddf30SRichard Henderson    if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
611cbaddf30SRichard Henderson        return true;
612cbaddf30SRichard Henderson    }
613cbaddf30SRichard Henderson    if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
614cbaddf30SRichard Henderson        return true;
615cbaddf30SRichard Henderson    }
6163704993fSRichard Henderson    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
6173704993fSRichard Henderson        return true;
6184134083fSRichard Henderson    }
6194134083fSRichard Henderson    if ((ct & TCG_CT_CONST_M1) && val == -1) {
6204134083fSRichard Henderson        return true;
621b2509accSRichard Henderson    }
622b2509accSRichard Henderson
623b2509accSRichard Henderson    if (ct & TCG_CT_CONST_INV) {
6244134083fSRichard Henderson        val = ~val;
6254134083fSRichard Henderson    }
6264134083fSRichard Henderson    if ((ct & TCG_CT_CONST_P32) && is_const_p32(val) >= 0) {
627cbaddf30SRichard Henderson        return true;
6283704993fSRichard Henderson    }
6293704993fSRichard Henderson    if ((ct & TCG_CT_CONST_INVRISBG) && risbg_mask(~val)) {
6303704993fSRichard Henderson        return true;
6313704993fSRichard Henderson    }
6323704993fSRichard Henderson    return false;
6333704993fSRichard Henderson}
6343704993fSRichard Henderson
6353704993fSRichard Henderson/* Emit instructions according to the given instruction format.  */
6363704993fSRichard Henderson
6373704993fSRichard Hendersonstatic void tcg_out_insn_RR(TCGContext *s, S390Opcode op, TCGReg r1, TCGReg r2)
6383704993fSRichard Henderson{
6393704993fSRichard Henderson    tcg_out16(s, (op << 8) | (r1 << 4) | r2);
6403704993fSRichard Henderson}
6413704993fSRichard Henderson
6423704993fSRichard Hendersonstatic void tcg_out_insn_RRE(TCGContext *s, S390Opcode op,
6430bbf0f7aSRichard Henderson                             TCGReg r1, TCGReg r2)
6441dd06b1aSRichard Henderson{
6451dd06b1aSRichard Henderson    tcg_out32(s, (op << 16) | (r1 << 4) | r2);
6461dd06b1aSRichard Henderson}
6471dd06b1aSRichard Henderson
6481dd06b1aSRichard Henderson/* RRF-a without the m4 field */
6491dd06b1aSRichard Hendersonstatic void tcg_out_insn_RRFa(TCGContext *s, S390Opcode op,
6500bbf0f7aSRichard Henderson                              TCGReg r1, TCGReg r2, TCGReg r3)
6510bbf0f7aSRichard Henderson{
6520bbf0f7aSRichard Henderson    tcg_out32(s, (op << 16) | (r3 << 12) | (r1 << 4) | r2);
6530bbf0f7aSRichard Henderson}
6540bbf0f7aSRichard Henderson
6550bbf0f7aSRichard Henderson/* RRF-a with the m4 field */
6560bbf0f7aSRichard Hendersonstatic void tcg_out_insn_RRFam(TCGContext *s, S390Opcode op,
6571dd06b1aSRichard Henderson                               TCGReg r1, TCGReg r2, TCGReg r3, int m4)
6583704993fSRichard Henderson{
6593704993fSRichard Henderson    tcg_out32(s, (op << 16) | (r3 << 12) | (m4 << 8) | (r1 << 4) | r2);
6603704993fSRichard Henderson}
6613704993fSRichard Henderson
6623704993fSRichard Hendersonstatic void tcg_out_insn_RRFc(TCGContext *s, S390Opcode op,
6633704993fSRichard Henderson                              TCGReg r1, TCGReg r2, int m3)
6643704993fSRichard Henderson{
6653704993fSRichard Henderson    tcg_out32(s, (op << 16) | (m3 << 12) | (r1 << 4) | r2);
6663704993fSRichard Henderson}
6673704993fSRichard Henderson
668d84ca804SRichard Hendersonstatic void tcg_out_insn_RI(TCGContext *s, S390Opcode op, TCGReg r1, int i2)
6693704993fSRichard Henderson{
6703704993fSRichard Henderson    tcg_out32(s, (op << 16) | (r1 << 20) | (i2 & 0xffff));
6713704993fSRichard Henderson}
6723704993fSRichard Henderson
6733704993fSRichard Hendersonstatic void tcg_out_insn_RIEg(TCGContext *s, S390Opcode op, TCGReg r1,
6743704993fSRichard Henderson                             int i2, int m3)
6753704993fSRichard Henderson{
6763704993fSRichard Henderson    tcg_out16(s, (op & 0xff00) | (r1 << 4) | m3);
6773704993fSRichard Henderson    tcg_out32(s, (i2 << 16) | (op & 0xff));
6783704993fSRichard Henderson}
6793704993fSRichard Henderson
6803704993fSRichard Hendersonstatic void tcg_out_insn_RIL(TCGContext *s, S390Opcode op, TCGReg r1, int i2)
6813704993fSRichard Henderson{
6823704993fSRichard Henderson    tcg_out16(s, op | (r1 << 4));
6833704993fSRichard Henderson    tcg_out32(s, i2);
6843704993fSRichard Henderson}
6853704993fSRichard Henderson
6863704993fSRichard Hendersonstatic void tcg_out_insn_RS(TCGContext *s, S390Opcode op, TCGReg r1,
6873704993fSRichard Henderson                            TCGReg b2, TCGReg r3, int disp)
6883704993fSRichard Henderson{
6893704993fSRichard Henderson    tcg_out32(s, (op << 24) | (r1 << 20) | (r3 << 16) | (b2 << 12)
6903704993fSRichard Henderson              | (disp & 0xfff));
6913704993fSRichard Henderson}
6923704993fSRichard Henderson
6933704993fSRichard Hendersonstatic void tcg_out_insn_RSY(TCGContext *s, S390Opcode op, TCGReg r1,
6943704993fSRichard Henderson                             TCGReg b2, TCGReg r3, int disp)
6953704993fSRichard Henderson{
6963704993fSRichard Henderson    tcg_out16(s, (op & 0xff00) | (r1 << 4) | r3);
6973704993fSRichard Henderson    tcg_out32(s, (op & 0xff) | (b2 << 28)
6983704993fSRichard Henderson              | ((disp & 0xfff) << 16) | ((disp & 0xff000) >> 4));
6992dabf742SRichard Henderson}
7002dabf742SRichard Henderson
7012dabf742SRichard Henderson#define tcg_out_insn_RX   tcg_out_insn_RS
7022dabf742SRichard Henderson#define tcg_out_insn_RXY  tcg_out_insn_RSY
7032dabf742SRichard Henderson
7042dabf742SRichard Hendersonstatic int RXB(TCGReg v1, TCGReg v2, TCGReg v3, TCGReg v4)
7052dabf742SRichard Henderson{
7062dabf742SRichard Henderson    /*
7072dabf742SRichard Henderson     * Shift bit 4 of each regno to its corresponding bit of RXB.
7082dabf742SRichard Henderson     * RXB itself begins at bit 8 of the instruction so 8 - 4 = 4
7092dabf742SRichard Henderson     * is the left-shift of the 4th operand.
7102dabf742SRichard Henderson     */
7112dabf742SRichard Henderson    return ((v1 & 0x10) << (4 + 3))
71279cada86SRichard Henderson         | ((v2 & 0x10) << (4 + 2))
71379cada86SRichard Henderson         | ((v3 & 0x10) << (4 + 1))
71479cada86SRichard Henderson         | ((v4 & 0x10) << (4 + 0));
71579cada86SRichard Henderson}
71679cada86SRichard Henderson
71779cada86SRichard Hendersonstatic void tcg_out_insn_VRIa(TCGContext *s, S390Opcode op,
71879cada86SRichard Henderson                              TCGReg v1, uint16_t i2, int m3)
71979cada86SRichard Henderson{
72079cada86SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
72179cada86SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4));
72279cada86SRichard Henderson    tcg_out16(s, i2);
72379cada86SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, 0, 0, 0) | (m3 << 12));
72479cada86SRichard Henderson}
72579cada86SRichard Henderson
72679cada86SRichard Hendersonstatic void tcg_out_insn_VRIb(TCGContext *s, S390Opcode op,
72779cada86SRichard Henderson                              TCGReg v1, uint8_t i2, uint8_t i3, int m4)
72879cada86SRichard Henderson{
72979cada86SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
73079cada86SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4));
73179cada86SRichard Henderson    tcg_out16(s, (i2 << 8) | (i3 & 0xff));
73279cada86SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, 0, 0, 0) | (m4 << 12));
73379cada86SRichard Henderson}
73479cada86SRichard Henderson
73579cada86SRichard Hendersonstatic void tcg_out_insn_VRIc(TCGContext *s, S390Opcode op,
73679cada86SRichard Henderson                              TCGReg v1, uint16_t i2, TCGReg v3, int m4)
737c1ddc18fSRichard Henderson{
73879cada86SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
73979cada86SRichard Henderson    tcg_debug_assert(is_vector_reg(v3));
740b33ce725SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | (v3 & 0xf));
741b33ce725SRichard Henderson    tcg_out16(s, i2);
742b33ce725SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, v3, 0, 0) | (m4 << 12));
743b33ce725SRichard Henderson}
744b33ce725SRichard Henderson
745b33ce725SRichard Hendersonstatic void tcg_out_insn_VRRa(TCGContext *s, S390Opcode op,
746b33ce725SRichard Henderson                              TCGReg v1, TCGReg v2, int m3)
747b33ce725SRichard Henderson{
748b33ce725SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
749a429ee29SRichard Henderson    tcg_debug_assert(is_vector_reg(v2));
750a429ee29SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | (v2 & 0xf));
751a429ee29SRichard Henderson    tcg_out32(s, (op & 0x00ff) | RXB(v1, v2, 0, 0) | (m3 << 12));
752a429ee29SRichard Henderson}
753a429ee29SRichard Henderson
754a429ee29SRichard Hendersonstatic void tcg_out_insn_VRRc(TCGContext *s, S390Opcode op,
755a429ee29SRichard Henderson                              TCGReg v1, TCGReg v2, TCGReg v3, int m4)
756a429ee29SRichard Henderson{
757a429ee29SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
758a429ee29SRichard Henderson    tcg_debug_assert(is_vector_reg(v2));
759a429ee29SRichard Henderson    tcg_debug_assert(is_vector_reg(v3));
7609bca986dSRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | (v2 & 0xf));
7619bca986dSRichard Henderson    tcg_out16(s, v3 << 12);
7629bca986dSRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, v2, v3, 0) | (m4 << 12));
7639bca986dSRichard Henderson}
7649bca986dSRichard Henderson
7659bca986dSRichard Hendersonstatic void tcg_out_insn_VRRe(TCGContext *s, S390Opcode op,
7669bca986dSRichard Henderson                              TCGReg v1, TCGReg v2, TCGReg v3, TCGReg v4)
7679bca986dSRichard Henderson{
7689bca986dSRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
7699bca986dSRichard Henderson    tcg_debug_assert(is_vector_reg(v2));
7709bca986dSRichard Henderson    tcg_debug_assert(is_vector_reg(v3));
7719bca986dSRichard Henderson    tcg_debug_assert(is_vector_reg(v4));
77279cada86SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | (v2 & 0xf));
77379cada86SRichard Henderson    tcg_out16(s, v3 << 12);
77479cada86SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, v2, v3, v4) | (v4 << 12));
77579cada86SRichard Henderson}
77679cada86SRichard Henderson
77779cada86SRichard Hendersonstatic void tcg_out_insn_VRRf(TCGContext *s, S390Opcode op,
77879cada86SRichard Henderson                              TCGReg v1, TCGReg r2, TCGReg r3)
77979cada86SRichard Henderson{
78079cada86SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
78179cada86SRichard Henderson    tcg_debug_assert(is_general_reg(r2));
78279cada86SRichard Henderson    tcg_debug_assert(is_general_reg(r3));
78322cb37b4SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | r2);
78422cb37b4SRichard Henderson    tcg_out16(s, r3 << 12);
78522cb37b4SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, 0, 0, 0));
78622cb37b4SRichard Henderson}
78722cb37b4SRichard Henderson
78822cb37b4SRichard Hendersonstatic void tcg_out_insn_VRSa(TCGContext *s, S390Opcode op, TCGReg v1,
78922cb37b4SRichard Henderson                              intptr_t d2, TCGReg b2, TCGReg v3, int m4)
79022cb37b4SRichard Henderson{
79122cb37b4SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
792c1ddc18fSRichard Henderson    tcg_debug_assert(d2 >= 0 && d2 <= 0xfff);
79322cb37b4SRichard Henderson    tcg_debug_assert(is_general_reg(b2));
79422cb37b4SRichard Henderson    tcg_debug_assert(is_vector_reg(v3));
795b33ce725SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | (v3 & 0xf));
796b33ce725SRichard Henderson    tcg_out16(s, b2 << 12 | d2);
797b33ce725SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, v3, 0, 0) | (m4 << 12));
798b33ce725SRichard Henderson}
799b33ce725SRichard Henderson
800b33ce725SRichard Hendersonstatic void tcg_out_insn_VRSb(TCGContext *s, S390Opcode op, TCGReg v1,
801b33ce725SRichard Henderson                              intptr_t d2, TCGReg b2, TCGReg r3, int m4)
802b33ce725SRichard Henderson{
803b33ce725SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
804b33ce725SRichard Henderson    tcg_debug_assert(d2 >= 0 && d2 <= 0xfff);
805b33ce725SRichard Henderson    tcg_debug_assert(is_general_reg(b2));
806b33ce725SRichard Henderson    tcg_debug_assert(is_general_reg(r3));
807b33ce725SRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | r3);
808b33ce725SRichard Henderson    tcg_out16(s, b2 << 12 | d2);
809b33ce725SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, 0, 0, 0) | (m4 << 12));
810b33ce725SRichard Henderson}
811b33ce725SRichard Henderson
812b33ce725SRichard Hendersonstatic void tcg_out_insn_VRSc(TCGContext *s, S390Opcode op, TCGReg r1,
813b33ce725SRichard Henderson                              intptr_t d2, TCGReg b2, TCGReg v3, int m4)
814b33ce725SRichard Henderson{
815b33ce725SRichard Henderson    tcg_debug_assert(is_general_reg(r1));
816c1ddc18fSRichard Henderson    tcg_debug_assert(d2 >= 0 && d2 <= 0xfff);
817b33ce725SRichard Henderson    tcg_debug_assert(is_general_reg(b2));
818b33ce725SRichard Henderson    tcg_debug_assert(is_vector_reg(v3));
8192dabf742SRichard Henderson    tcg_out16(s, (op & 0xff00) | (r1 << 4) | (v3 & 0xf));
8202dabf742SRichard Henderson    tcg_out16(s, b2 << 12 | d2);
8212dabf742SRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(0, v3, 0, 0) | (m4 << 12));
8222dabf742SRichard Henderson}
8232dabf742SRichard Henderson
8242dabf742SRichard Hendersonstatic void tcg_out_insn_VRX(TCGContext *s, S390Opcode op, TCGReg v1,
8252dabf742SRichard Henderson                             TCGReg b2, TCGReg x2, intptr_t d2, int m3)
8262dabf742SRichard Henderson{
8272dabf742SRichard Henderson    tcg_debug_assert(is_vector_reg(v1));
8282dabf742SRichard Henderson    tcg_debug_assert(d2 >= 0 && d2 <= 0xfff);
8292dabf742SRichard Henderson    tcg_debug_assert(is_general_reg(x2));
8302dabf742SRichard Henderson    tcg_debug_assert(is_general_reg(b2));
8313704993fSRichard Henderson    tcg_out16(s, (op & 0xff00) | ((v1 & 0xf) << 4) | x2);
8323704993fSRichard Henderson    tcg_out16(s, (b2 << 12) | d2);
8333704993fSRichard Henderson    tcg_out16(s, (op & 0x00ff) | RXB(v1, 0, 0, 0) | (m3 << 12));
8343704993fSRichard Henderson}
8353704993fSRichard Henderson
8363704993fSRichard Henderson/* Emit an opcode with "type-checking" of the format.  */
8373704993fSRichard Henderson#define tcg_out_insn(S, FMT, OP, ...) \
8383704993fSRichard Henderson    glue(tcg_out_insn_,FMT)(S, glue(glue(FMT,_),OP), ## __VA_ARGS__)
8393704993fSRichard Henderson
8403704993fSRichard Henderson
8413704993fSRichard Henderson/* emit 64-bit shifts */
8423704993fSRichard Hendersonstatic void tcg_out_sh64(TCGContext* s, S390Opcode op, TCGReg dest,
8433704993fSRichard Henderson                         TCGReg src, TCGReg sh_reg, int sh_imm)
8443704993fSRichard Henderson{
8453704993fSRichard Henderson    tcg_out_insn_RSY(s, op, dest, sh_reg, src, sh_imm);
8463704993fSRichard Henderson}
8473704993fSRichard Henderson
8483704993fSRichard Henderson/* emit 32-bit shifts */
8493704993fSRichard Hendersonstatic void tcg_out_sh32(TCGContext* s, S390Opcode op, TCGReg dest,
8503704993fSRichard Henderson                         TCGReg sh_reg, int sh_imm)
8513704993fSRichard Henderson{
852b33ce725SRichard Henderson    tcg_out_insn_RS(s, op, dest, sh_reg, 0, sh_imm);
853b33ce725SRichard Henderson}
8543704993fSRichard Henderson
855b33ce725SRichard Hendersonstatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg dst, TCGReg src)
856b33ce725SRichard Henderson{
857b33ce725SRichard Henderson    if (src == dst) {
858b33ce725SRichard Henderson        return true;
859b33ce725SRichard Henderson    }
860b33ce725SRichard Henderson    switch (type) {
861b33ce725SRichard Henderson    case TCG_TYPE_I32:
862b33ce725SRichard Henderson        if (likely(is_general_reg(dst) && is_general_reg(src))) {
863b33ce725SRichard Henderson            tcg_out_insn(s, RR, LR, dst, src);
864b33ce725SRichard Henderson            break;
865b33ce725SRichard Henderson        }
866b33ce725SRichard Henderson        /* fallthru */
867b33ce725SRichard Henderson
868b33ce725SRichard Henderson    case TCG_TYPE_I64:
869b33ce725SRichard Henderson        if (likely(is_general_reg(dst))) {
870b33ce725SRichard Henderson            if (likely(is_general_reg(src))) {
871b33ce725SRichard Henderson                tcg_out_insn(s, RRE, LGR, dst, src);
872b33ce725SRichard Henderson            } else {
873b33ce725SRichard Henderson                tcg_out_insn(s, VRSc, VLGV, dst, 0, 0, src, 3);
874b33ce725SRichard Henderson            }
875b33ce725SRichard Henderson            break;
876b33ce725SRichard Henderson        } else if (is_general_reg(src)) {
877b33ce725SRichard Henderson            tcg_out_insn(s, VRSb, VLVG, dst, 0, 0, src, 3);
878b33ce725SRichard Henderson            break;
879b33ce725SRichard Henderson        }
880b33ce725SRichard Henderson        /* fallthru */
881b33ce725SRichard Henderson
882b33ce725SRichard Henderson    case TCG_TYPE_V64:
883b33ce725SRichard Henderson    case TCG_TYPE_V128:
8843704993fSRichard Henderson        tcg_out_insn(s, VRRa, VLR, dst, src, 0);
8853704993fSRichard Henderson        break;
8863704993fSRichard Henderson
8873704993fSRichard Henderson    default:
8881818c71bSRichard Henderson        g_assert_not_reached();
8893704993fSRichard Henderson    }
8903704993fSRichard Henderson    return true;
89190497e03SRichard Henderson}
89290497e03SRichard Henderson
89390497e03SRichard Hendersonstatic const S390Opcode li_insns[4] = {
8941818c71bSRichard Henderson    RI_LLILL, RI_LLILH, RI_LLIHL, RI_LLIHH
8951818c71bSRichard Henderson};
8961818c71bSRichard Hendersonstatic const S390Opcode oi_insns[4] = {
897585b7a42SRichard Henderson    RI_OILL, RI_OILH, RI_OIHL, RI_OIHH
898585b7a42SRichard Henderson};
899585b7a42SRichard Hendersonstatic const S390Opcode lif_insns[2] = {
9003704993fSRichard Henderson    RIL_LLILF, RIL_LLIHF,
9011818c71bSRichard Henderson};
9021818c71bSRichard Hendersonstatic const S390Opcode tm_insns[4] = {
9033704993fSRichard Henderson    RI_TMLL, RI_TMLH, RI_TMHL, RI_TMHH
9043704993fSRichard Henderson};
9053704993fSRichard Henderson
9061818c71bSRichard Henderson/* load a register with an immediate value */
9073704993fSRichard Hendersonstatic void tcg_out_movi(TCGContext *s, TCGType type,
9083704993fSRichard Henderson                         TCGReg ret, tcg_target_long sval)
9093704993fSRichard Henderson{
9103704993fSRichard Henderson    tcg_target_ulong uval = sval;
9113704993fSRichard Henderson    ptrdiff_t pc_off;
9123704993fSRichard Henderson    int i;
9133704993fSRichard Henderson
9143704993fSRichard Henderson    if (type == TCG_TYPE_I32) {
9153704993fSRichard Henderson        uval = (uint32_t)sval;
9163704993fSRichard Henderson        sval = (int32_t)sval;
9173704993fSRichard Henderson    }
9183704993fSRichard Henderson
9193704993fSRichard Henderson    /* Try all 32-bit insns that can load it in one go.  */
9201818c71bSRichard Henderson    if (sval >= -0x8000 && sval < 0x8000) {
9211818c71bSRichard Henderson        tcg_out_insn(s, RI, LGHI, ret, sval);
9221818c71bSRichard Henderson        return;
9231818c71bSRichard Henderson    }
9243704993fSRichard Henderson
9253704993fSRichard Henderson    i = is_const_p16(uval);
9263704993fSRichard Henderson    if (i >= 0) {
9273704993fSRichard Henderson        tcg_out_insn_RI(s, li_insns[i], ret, uval >> (i * 16));
9283704993fSRichard Henderson        return;
9293704993fSRichard Henderson    }
9303704993fSRichard Henderson
9311818c71bSRichard Henderson    /* Try all 48-bit insns that can load it in one go.  */
9321818c71bSRichard Henderson    if (sval == (int32_t)sval) {
9331818c71bSRichard Henderson        tcg_out_insn(s, RIL, LGFI, ret, sval);
9341818c71bSRichard Henderson        return;
9353704993fSRichard Henderson    }
9363704993fSRichard Henderson
9373704993fSRichard Henderson    i = is_const_p32(uval);
9381b74cf6eSRichard Henderson    if (i >= 0) {
9391b74cf6eSRichard Henderson        tcg_out_insn_RIL(s, lif_insns[i], ret, uval >> (i * 32));
9401b74cf6eSRichard Henderson        return;
9411b74cf6eSRichard Henderson    }
9421b74cf6eSRichard Henderson
9431b74cf6eSRichard Henderson    /* Try for PC-relative address load.  For odd addresses, add one. */
9443704993fSRichard Henderson    pc_off = tcg_pcrel_diff(s, (void *)sval) >> 1;
9451b74cf6eSRichard Henderson    if (pc_off == (int32_t)pc_off) {
9463704993fSRichard Henderson        tcg_out_insn(s, RIL, LARL, ret, pc_off);
9473704993fSRichard Henderson        if (sval & 1) {
94890497e03SRichard Henderson            tcg_out_insn(s, RI, AGHI, ret, 1);
94990497e03SRichard Henderson        }
95090497e03SRichard Henderson        return;
95190497e03SRichard Henderson    }
95290497e03SRichard Henderson
95390497e03SRichard Henderson    /* Otherwise, load it by parts. */
95490497e03SRichard Henderson    i = is_const_p16((uint32_t)uval);
95590497e03SRichard Henderson    if (i >= 0) {
95690497e03SRichard Henderson        tcg_out_insn_RI(s, li_insns[i], ret, uval >> (i * 16));
95790497e03SRichard Henderson    } else {
95890497e03SRichard Henderson        tcg_out_insn(s, RIL, LLILF, ret, uval);
95990497e03SRichard Henderson    }
96090497e03SRichard Henderson    uval >>= 32;
96190497e03SRichard Henderson    i = is_const_p16(uval);
9623704993fSRichard Henderson    if (i >= 0) {
9633704993fSRichard Henderson        tcg_out_insn_RI(s, oi_insns[i + 2], ret, uval >> (i * 16));
9643704993fSRichard Henderson    } else {
9653704993fSRichard Henderson        tcg_out_insn(s, RIL, OIHF, ret, uval);
9663704993fSRichard Henderson    }
9673704993fSRichard Henderson}
9683704993fSRichard Henderson
9693704993fSRichard Henderson/* Emit a load/store type instruction.  Inputs are:
9703704993fSRichard Henderson   DATA:     The register to be loaded or stored.
9713704993fSRichard Henderson   BASE+OFS: The effective address.
9723704993fSRichard Henderson   OPC_RX:   If the operation has an RX format opcode (e.g. STC), otherwise 0.
9733704993fSRichard Henderson   OPC_RXY:  The RXY format opcode for the operation (e.g. STCY).  */
9743704993fSRichard Henderson
9753704993fSRichard Hendersonstatic void tcg_out_mem(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy,
9763704993fSRichard Henderson                        TCGReg data, TCGReg base, TCGReg index,
9773704993fSRichard Henderson                        tcg_target_long ofs)
9783704993fSRichard Henderson{
9793704993fSRichard Henderson    if (ofs < -0x80000 || ofs >= 0x80000) {
9803704993fSRichard Henderson        /* Combine the low 20 bits of the offset with the actual load insn;
9813704993fSRichard Henderson           the high 44 bits must come from an immediate load.  */
9823704993fSRichard Henderson        tcg_target_long low = ((ofs & 0xfffff) ^ 0x80000) - 0x80000;
9833704993fSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - low);
9843704993fSRichard Henderson        ofs = low;
9853704993fSRichard Henderson
9863704993fSRichard Henderson        /* If we were already given an index register, add it in.  */
9873704993fSRichard Henderson        if (index != TCG_REG_NONE) {
9883704993fSRichard Henderson            tcg_out_insn(s, RRE, AGR, TCG_TMP0, index);
9893704993fSRichard Henderson        }
9903704993fSRichard Henderson        index = TCG_TMP0;
9913704993fSRichard Henderson    }
9923704993fSRichard Henderson
9933704993fSRichard Henderson    if (opc_rx && ofs >= 0 && ofs < 0x1000) {
9943704993fSRichard Henderson        tcg_out_insn_RX(s, opc_rx, data, base, index, ofs);
9952dabf742SRichard Henderson    } else {
9962dabf742SRichard Henderson        tcg_out_insn_RXY(s, opc_rxy, data, base, index, ofs);
9972dabf742SRichard Henderson    }
9982dabf742SRichard Henderson}
9992dabf742SRichard Henderson
10002dabf742SRichard Hendersonstatic void tcg_out_vrx_mem(TCGContext *s, S390Opcode opc_vrx,
10012dabf742SRichard Henderson                            TCGReg data, TCGReg base, TCGReg index,
10022dabf742SRichard Henderson                            tcg_target_long ofs, int m3)
10032dabf742SRichard Henderson{
10042dabf742SRichard Henderson    if (ofs < 0 || ofs >= 0x1000) {
10052dabf742SRichard Henderson        if (ofs >= -0x80000 && ofs < 0x80000) {
10062dabf742SRichard Henderson            tcg_out_insn(s, RXY, LAY, TCG_TMP0, base, index, ofs);
10072dabf742SRichard Henderson            base = TCG_TMP0;
10082dabf742SRichard Henderson            index = TCG_REG_NONE;
10092dabf742SRichard Henderson            ofs = 0;
10102dabf742SRichard Henderson        } else {
10112dabf742SRichard Henderson            tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs);
10122dabf742SRichard Henderson            if (index != TCG_REG_NONE) {
10132dabf742SRichard Henderson                tcg_out_insn(s, RRE, AGR, TCG_TMP0, index);
10142dabf742SRichard Henderson            }
10152dabf742SRichard Henderson            index = TCG_TMP0;
10163704993fSRichard Henderson            ofs = 0;
10173704993fSRichard Henderson        }
10182dabf742SRichard Henderson    }
10193704993fSRichard Henderson    tcg_out_insn_VRX(s, opc_vrx, data, base, index, ofs, m3);
10203704993fSRichard Henderson}
10212dabf742SRichard Henderson
10222dabf742SRichard Henderson/* load data without address translation or endianness conversion */
10232dabf742SRichard Hendersonstatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data,
10243704993fSRichard Henderson                       TCGReg base, intptr_t ofs)
10252dabf742SRichard Henderson{
10262dabf742SRichard Henderson    switch (type) {
10272dabf742SRichard Henderson    case TCG_TYPE_I32:
10282dabf742SRichard Henderson        if (likely(is_general_reg(data))) {
10292dabf742SRichard Henderson            tcg_out_mem(s, RX_L, RXY_LY, data, base, TCG_REG_NONE, ofs);
10302dabf742SRichard Henderson            break;
10312dabf742SRichard Henderson        }
10323704993fSRichard Henderson        tcg_out_vrx_mem(s, VRX_VLLEZ, data, base, TCG_REG_NONE, ofs, MO_32);
10332dabf742SRichard Henderson        break;
10342dabf742SRichard Henderson
10352dabf742SRichard Henderson    case TCG_TYPE_I64:
10362dabf742SRichard Henderson        if (likely(is_general_reg(data))) {
10372dabf742SRichard Henderson            tcg_out_mem(s, 0, RXY_LG, data, base, TCG_REG_NONE, ofs);
10382dabf742SRichard Henderson            break;
10392dabf742SRichard Henderson        }
10402dabf742SRichard Henderson        /* fallthru */
10412dabf742SRichard Henderson
10422dabf742SRichard Henderson    case TCG_TYPE_V64:
10432dabf742SRichard Henderson        tcg_out_vrx_mem(s, VRX_VLLEZ, data, base, TCG_REG_NONE, ofs, MO_64);
10442dabf742SRichard Henderson        break;
10452dabf742SRichard Henderson
10462dabf742SRichard Henderson    case TCG_TYPE_V128:
10472dabf742SRichard Henderson        /* Hint quadword aligned.  */
10483704993fSRichard Henderson        tcg_out_vrx_mem(s, VRX_VL, data, base, TCG_REG_NONE, ofs, 4);
10493704993fSRichard Henderson        break;
10503704993fSRichard Henderson
10512dabf742SRichard Henderson    default:
10523704993fSRichard Henderson        g_assert_not_reached();
10533704993fSRichard Henderson    }
10542dabf742SRichard Henderson}
10552dabf742SRichard Henderson
10562dabf742SRichard Hendersonstatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
10573704993fSRichard Henderson                       TCGReg base, intptr_t ofs)
10583704993fSRichard Henderson{
10592dabf742SRichard Henderson    switch (type) {
10602dabf742SRichard Henderson    case TCG_TYPE_I32:
10612dabf742SRichard Henderson        if (likely(is_general_reg(data))) {
10622dabf742SRichard Henderson            tcg_out_mem(s, RX_ST, RXY_STY, data, base, TCG_REG_NONE, ofs);
10632dabf742SRichard Henderson        } else {
10642dabf742SRichard Henderson            tcg_out_vrx_mem(s, VRX_VSTEF, data, base, TCG_REG_NONE, ofs, 1);
10653704993fSRichard Henderson        }
10662dabf742SRichard Henderson        break;
10672dabf742SRichard Henderson
10682dabf742SRichard Henderson    case TCG_TYPE_I64:
10692dabf742SRichard Henderson        if (likely(is_general_reg(data))) {
10702dabf742SRichard Henderson            tcg_out_mem(s, 0, RXY_STG, data, base, TCG_REG_NONE, ofs);
10712dabf742SRichard Henderson            break;
10722dabf742SRichard Henderson        }
10732dabf742SRichard Henderson        /* fallthru */
10742dabf742SRichard Henderson
10752dabf742SRichard Henderson    case TCG_TYPE_V64:
10762dabf742SRichard Henderson        tcg_out_vrx_mem(s, VRX_VSTEG, data, base, TCG_REG_NONE, ofs, 0);
10772dabf742SRichard Henderson        break;
10782dabf742SRichard Henderson
10792dabf742SRichard Henderson    case TCG_TYPE_V128:
10802dabf742SRichard Henderson        /* Hint quadword aligned.  */
10813704993fSRichard Henderson        tcg_out_vrx_mem(s, VRX_VST, data, base, TCG_REG_NONE, ofs, 4);
10823704993fSRichard Henderson        break;
10833704993fSRichard Henderson
10843704993fSRichard Henderson    default:
10853704993fSRichard Henderson        g_assert_not_reached();
10863704993fSRichard Henderson    }
10873704993fSRichard Henderson}
10883704993fSRichard Henderson
10893704993fSRichard Hendersonstatic inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1090767c2503SRichard Henderson                               TCGReg base, intptr_t ofs)
1091767c2503SRichard Henderson{
1092767c2503SRichard Henderson    return false;
1093767c2503SRichard Henderson}
1094767c2503SRichard Henderson
10956a6d772eSRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
10966a6d772eSRichard Henderson{
10976a6d772eSRichard Henderson    return false;
10986a6d772eSRichard Henderson}
10996a6d772eSRichard Henderson
11006a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
11016a6d772eSRichard Henderson                             tcg_target_long imm)
11023704993fSRichard Henderson{
11033704993fSRichard Henderson    /* This function is only used for passing structs by reference. */
11043704993fSRichard Henderson    tcg_out_mem(s, RX_LA, RXY_LAY, rd, rs, TCG_REG_NONE, imm);
11053704993fSRichard Henderson}
1106d84ca804SRichard Henderson
11073704993fSRichard Hendersonstatic inline void tcg_out_risbg(TCGContext *s, TCGReg dest, TCGReg src,
1108d84ca804SRichard Henderson                                 int msb, int lsb, int ofs, int z)
11093704993fSRichard Henderson{
11103704993fSRichard Henderson    /* Format RIE-f */
1111678155b2SRichard Henderson    tcg_out16(s, (RIEf_RISBG & 0xff00) | (dest << 4) | src);
11123704993fSRichard Henderson    tcg_out16(s, (msb << 8) | (z << 7) | lsb);
11133704993fSRichard Henderson    tcg_out16(s, (ofs << 8) | (RIEf_RISBG & 0xff));
11143704993fSRichard Henderson}
11153704993fSRichard Henderson
1116d0e66c89SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
11173704993fSRichard Henderson{
11183704993fSRichard Henderson    tcg_out_insn(s, RRE, LGBR, dest, src);
11193704993fSRichard Henderson}
11203704993fSRichard Henderson
1121753e42eaSRichard Hendersonstatic void tcg_out_ext8u(TCGContext *s, TCGReg dest, TCGReg src)
11223704993fSRichard Henderson{
11233704993fSRichard Henderson    tcg_out_insn(s, RRE, LLGCR, dest, src);
11243704993fSRichard Henderson}
11253704993fSRichard Henderson
1126379afdffSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
11273704993fSRichard Henderson{
11283704993fSRichard Henderson    tcg_out_insn(s, RRE, LGHR, dest, src);
11293704993fSRichard Henderson}
11303704993fSRichard Henderson
113152bf3398SRichard Hendersonstatic void tcg_out_ext16u(TCGContext *s, TCGReg dest, TCGReg src)
11323704993fSRichard Henderson{
11333704993fSRichard Henderson    tcg_out_insn(s, RRE, LLGHR, dest, src);
11343704993fSRichard Henderson}
11353704993fSRichard Henderson
11369ecf5f61SRichard Hendersonstatic void tcg_out_ext32s(TCGContext *s, TCGReg dest, TCGReg src)
11373704993fSRichard Henderson{
11383704993fSRichard Henderson    tcg_out_insn(s, RRE, LGFR, dest, src);
11393704993fSRichard Henderson}
11403704993fSRichard Henderson
11419c6aa274SRichard Hendersonstatic void tcg_out_ext32u(TCGContext *s, TCGReg dest, TCGReg src)
11429c6aa274SRichard Henderson{
11439c6aa274SRichard Henderson    tcg_out_insn(s, RRE, LLGFR, dest, src);
11449c6aa274SRichard Henderson}
11459c6aa274SRichard Henderson
1146b9bfe000SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg dest, TCGReg src)
1147b9bfe000SRichard Henderson{
1148b9bfe000SRichard Henderson    tcg_out_ext32s(s, dest, src);
1149b9bfe000SRichard Henderson}
1150b9bfe000SRichard Henderson
1151b8b94ac6SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg dest, TCGReg src)
1152b8b94ac6SRichard Henderson{
1153b8b94ac6SRichard Henderson    tcg_out_ext32u(s, dest, src);
1154b8b94ac6SRichard Henderson}
1155b8b94ac6SRichard Henderson
11563704993fSRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg dest, TCGReg src)
11573704993fSRichard Henderson{
11583704993fSRichard Henderson    tcg_out_mov(s, TCG_TYPE_I32, dest, src);
11593704993fSRichard Henderson}
11603704993fSRichard Henderson
11613704993fSRichard Hendersonstatic void tgen_andi_risbg(TCGContext *s, TCGReg out, TCGReg in, uint64_t val)
11623704993fSRichard Henderson{
11633704993fSRichard Henderson    int msb, lsb;
11643704993fSRichard Henderson    if ((val & 0x8000000000000001ull) == 0x8000000000000001ull) {
11653704993fSRichard Henderson        /* Achieve wraparound by swapping msb and lsb.  */
11663704993fSRichard Henderson        msb = 64 - ctz64(~val);
11673704993fSRichard Henderson        lsb = clz64(~val) - 1;
11683704993fSRichard Henderson    } else {
11693704993fSRichard Henderson        msb = clz64(val);
11703704993fSRichard Henderson        lsb = 63 - ctz64(val);
11713704993fSRichard Henderson    }
11723704993fSRichard Henderson    tcg_out_risbg(s, out, in, msb, lsb, 0, 1);
11733704993fSRichard Henderson}
11743704993fSRichard Henderson
11753704993fSRichard Hendersonstatic void tgen_andi(TCGContext *s, TCGType type, TCGReg dest, uint64_t val)
11763704993fSRichard Henderson{
11773704993fSRichard Henderson    static const S390Opcode ni_insns[4] = {
11783704993fSRichard Henderson        RI_NILL, RI_NILH, RI_NIHL, RI_NIHH
11793704993fSRichard Henderson    };
11803704993fSRichard Henderson    static const S390Opcode nif_insns[2] = {
11813704993fSRichard Henderson        RIL_NILF, RIL_NIHF
11823704993fSRichard Henderson    };
11839ecf5f61SRichard Henderson    uint64_t valid = (type == TCG_TYPE_I32 ? 0xffffffffull : -1ull);
11843704993fSRichard Henderson    int i;
11853704993fSRichard Henderson
11863704993fSRichard Henderson    /* Look for the zero-extensions.  */
1187d0e66c89SRichard Henderson    if ((val & valid) == 0xffffffff) {
11883704993fSRichard Henderson        tcg_out_ext32u(s, dest, dest);
11893704993fSRichard Henderson        return;
11903704993fSRichard Henderson    }
1191379afdffSRichard Henderson    if ((val & valid) == 0xff) {
11923704993fSRichard Henderson        tcg_out_ext8u(s, dest, dest);
11933704993fSRichard Henderson        return;
11943704993fSRichard Henderson    }
11954134083fSRichard Henderson    if ((val & valid) == 0xffff) {
11964134083fSRichard Henderson        tcg_out_ext16u(s, dest, dest);
11974134083fSRichard Henderson        return;
11983704993fSRichard Henderson    }
11993704993fSRichard Henderson
12003704993fSRichard Henderson    i = is_const_p16(~val & valid);
12014134083fSRichard Henderson    if (i >= 0) {
12024134083fSRichard Henderson        tcg_out_insn_RI(s, ni_insns[i], dest, val >> (i * 16));
12034134083fSRichard Henderson        return;
12044134083fSRichard Henderson    }
12053704993fSRichard Henderson
12063704993fSRichard Henderson    i = is_const_p32(~val & valid);
12074134083fSRichard Henderson    tcg_debug_assert(i == 0 || type != TCG_TYPE_I32);
12089c3bfb79SRichard Henderson    if (i >= 0) {
12093704993fSRichard Henderson        tcg_out_insn_RIL(s, nif_insns[i], dest, val >> (i * 32));
12103704993fSRichard Henderson        return;
12113704993fSRichard Henderson    }
12123704993fSRichard Henderson
12134134083fSRichard Henderson    if (risbg_mask(val)) {
12143704993fSRichard Henderson        tgen_andi_risbg(s, dest, dest, val);
12153704993fSRichard Henderson        return;
1216b2509accSRichard Henderson    }
12173704993fSRichard Henderson
12183704993fSRichard Henderson    g_assert_not_reached();
12193704993fSRichard Henderson}
12203704993fSRichard Henderson
12213704993fSRichard Hendersonstatic void tgen_ori(TCGContext *s, TCGReg dest, uint64_t val)
12223704993fSRichard Henderson{
12233704993fSRichard Henderson    static const S390Opcode oif_insns[2] = {
1224b2509accSRichard Henderson        RIL_OILF, RIL_OIHF
1225b2509accSRichard Henderson    };
1226b2509accSRichard Henderson
12273704993fSRichard Henderson    int i;
12283704993fSRichard Henderson
12293704993fSRichard Henderson    i = is_const_p16(val);
1230b2509accSRichard Henderson    if (i >= 0) {
1231b2509accSRichard Henderson        tcg_out_insn_RI(s, oi_insns[i], dest, val >> (i * 16));
1232b2509accSRichard Henderson        return;
12333704993fSRichard Henderson    }
12343704993fSRichard Henderson
1235b2509accSRichard Henderson    i = is_const_p32(val);
1236b2509accSRichard Henderson    if (i >= 0) {
12373704993fSRichard Henderson        tcg_out_insn_RIL(s, oif_insns[i], dest, val >> (i * 32));
12383704993fSRichard Henderson        return;
1239b2509accSRichard Henderson    }
12403704993fSRichard Henderson
1241b2509accSRichard Henderson    g_assert_not_reached();
1242b2509accSRichard Henderson}
12433704993fSRichard Henderson
1244b2509accSRichard Hendersonstatic void tgen_xori(TCGContext *s, TCGReg dest, uint64_t val)
1245b2509accSRichard Henderson{
12463704993fSRichard Henderson    switch (is_const_p32(val)) {
1247b2509accSRichard Henderson    case 0:
1248b2509accSRichard Henderson        tcg_out_insn(s, RIL, XILF, dest, val);
1249b2509accSRichard Henderson        break;
12503704993fSRichard Henderson    case 1:
12513704993fSRichard Henderson        tcg_out_insn(s, RIL, XIHF, dest, val >> 32);
12523704993fSRichard Henderson        break;
12535c837bbcSRichard Henderson    default:
12545c837bbcSRichard Henderson        g_assert_not_reached();
12553704993fSRichard Henderson    }
12563704993fSRichard Henderson}
12575c837bbcSRichard Henderson
12583704993fSRichard Hendersonstatic int tgen_cmp2(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
12593704993fSRichard Henderson                     TCGArg c2, bool c2const, bool need_carry, int *inv_cc)
1260585b7a42SRichard Henderson{
1261585b7a42SRichard Henderson    bool is_unsigned = is_unsigned_cond(c);
1262585b7a42SRichard Henderson    TCGCond inv_c = tcg_invert_cond(c);
1263585b7a42SRichard Henderson    S390Opcode op;
1264585b7a42SRichard Henderson
1265585b7a42SRichard Henderson    if (is_tst_cond(c)) {
1266585b7a42SRichard Henderson        tcg_debug_assert(!need_carry);
1267585b7a42SRichard Henderson
1268585b7a42SRichard Henderson        if (!c2const) {
1269585b7a42SRichard Henderson            if (type == TCG_TYPE_I32) {
1270585b7a42SRichard Henderson                tcg_out_insn(s, RRFa, NRK, TCG_REG_R0, r1, c2);
1271585b7a42SRichard Henderson            } else {
1272585b7a42SRichard Henderson                tcg_out_insn(s, RRFa, NGRK, TCG_REG_R0, r1, c2);
1273585b7a42SRichard Henderson            }
1274585b7a42SRichard Henderson            goto exit;
1275585b7a42SRichard Henderson        }
1276585b7a42SRichard Henderson
1277585b7a42SRichard Henderson        if (type == TCG_TYPE_I32) {
1278585b7a42SRichard Henderson            c2 = (uint32_t)c2;
1279585b7a42SRichard Henderson        }
1280585b7a42SRichard Henderson
1281585b7a42SRichard Henderson        int i = is_const_p16(c2);
1282585b7a42SRichard Henderson        if (i >= 0) {
1283585b7a42SRichard Henderson            tcg_out_insn_RI(s, tm_insns[i], r1, c2 >> (i * 16));
1284585b7a42SRichard Henderson            *inv_cc = c == TCG_COND_TSTEQ ? S390_TM_NE : S390_TM_EQ;
1285585b7a42SRichard Henderson            return *inv_cc ^ 15;
1286585b7a42SRichard Henderson        }
1287585b7a42SRichard Henderson
1288585b7a42SRichard Henderson        if (risbg_mask(c2)) {
1289585b7a42SRichard Henderson            tgen_andi_risbg(s, TCG_REG_R0, r1, c2);
12903704993fSRichard Henderson            goto exit;
12913704993fSRichard Henderson        }
12923704993fSRichard Henderson        g_assert_not_reached();
12933704993fSRichard Henderson    }
12943704993fSRichard Henderson
12953704993fSRichard Henderson    if (c2const) {
12963704993fSRichard Henderson        if (c2 == 0) {
12973704993fSRichard Henderson            if (!(is_unsigned && need_carry)) {
12985c837bbcSRichard Henderson                if (type == TCG_TYPE_I32) {
12993704993fSRichard Henderson                    tcg_out_insn(s, RR, LTR, r1, r1);
13003704993fSRichard Henderson                } else {
13013704993fSRichard Henderson                    tcg_out_insn(s, RRE, LTGR, r1, r1);
13023704993fSRichard Henderson                }
13033704993fSRichard Henderson                *inv_cc = tcg_cond_to_ltr_cond[inv_c];
13043704993fSRichard Henderson                return tcg_cond_to_ltr_cond[c];
13053704993fSRichard Henderson            }
13063704993fSRichard Henderson        }
13073704993fSRichard Henderson
13083704993fSRichard Henderson        if (!is_unsigned && c2 == (int16_t)c2) {
13093704993fSRichard Henderson            op = (type == TCG_TYPE_I32 ? RI_CHI : RI_CGHI);
13103704993fSRichard Henderson            tcg_out_insn_RI(s, op, r1, c2);
13113704993fSRichard Henderson            goto exit;
13123704993fSRichard Henderson        }
13133e25f7daSRichard Henderson
131432c256edSRichard Henderson        if (type == TCG_TYPE_I32) {
1315d95b51d3SRichard Henderson            op = (is_unsigned ? RIL_CLFI : RIL_CFI);
1316d95b51d3SRichard Henderson            tcg_out_insn_RIL(s, op, r1, c2);
1317d95b51d3SRichard Henderson            goto exit;
1318d95b51d3SRichard Henderson        }
1319d95b51d3SRichard Henderson
1320d95b51d3SRichard Henderson        /* Should match TCG_CT_CONST_CMP. */
1321d95b51d3SRichard Henderson        switch (c) {
1322d95b51d3SRichard Henderson        case TCG_COND_LT:
1323d95b51d3SRichard Henderson        case TCG_COND_GE:
1324d95b51d3SRichard Henderson        case TCG_COND_LE:
1325d95b51d3SRichard Henderson        case TCG_COND_GT:
1326d95b51d3SRichard Henderson            tcg_debug_assert(c2 == (int32_t)c2);
1327d95b51d3SRichard Henderson            op = RIL_CGFI;
1328d95b51d3SRichard Henderson            break;
1329d95b51d3SRichard Henderson        case TCG_COND_EQ:
1330d95b51d3SRichard Henderson        case TCG_COND_NE:
1331d95b51d3SRichard Henderson            if (c2 == (int32_t)c2) {
1332d95b51d3SRichard Henderson                op = RIL_CGFI;
1333d95b51d3SRichard Henderson                break;
1334d95b51d3SRichard Henderson            }
1335d95b51d3SRichard Henderson            /* fall through */
1336d95b51d3SRichard Henderson        case TCG_COND_LTU:
1337d95b51d3SRichard Henderson        case TCG_COND_GEU:
1338d95b51d3SRichard Henderson        case TCG_COND_LEU:
1339d95b51d3SRichard Henderson        case TCG_COND_GTU:
1340d95b51d3SRichard Henderson            tcg_debug_assert(c2 == (uint32_t)c2);
13413704993fSRichard Henderson            op = RIL_CLGFI;
1342d95b51d3SRichard Henderson            break;
13433704993fSRichard Henderson        default:
13443704993fSRichard Henderson            g_assert_not_reached();
13453704993fSRichard Henderson        }
13463704993fSRichard Henderson        tcg_out_insn_RIL(s, op, r1, c2);
13473704993fSRichard Henderson    } else if (type == TCG_TYPE_I32) {
13483704993fSRichard Henderson        op = (is_unsigned ? RR_CLR : RR_CR);
13493704993fSRichard Henderson        tcg_out_insn_RR(s, op, r1, c2);
13503704993fSRichard Henderson    } else {
13515c837bbcSRichard Henderson        op = (is_unsigned ? RRE_CLGR : RRE_CGR);
13523704993fSRichard Henderson        tcg_out_insn_RRE(s, op, r1, c2);
13533704993fSRichard Henderson    }
13543704993fSRichard Henderson
13555c837bbcSRichard Henderson exit:
13565c837bbcSRichard Henderson    *inv_cc = tcg_cond_to_s390_cond[inv_c];
13575c837bbcSRichard Henderson    return tcg_cond_to_s390_cond[c];
13585c837bbcSRichard Henderson}
13595c837bbcSRichard Henderson
13605c837bbcSRichard Hendersonstatic int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
13615c837bbcSRichard Henderson                    TCGArg c2, bool c2const, bool need_carry)
13623704993fSRichard Henderson{
1363128c7d51SRichard Henderson    int inv_cc;
1364128c7d51SRichard Henderson    return tgen_cmp2(s, type, c, r1, c2, c2const, need_carry, &inv_cc);
13653704993fSRichard Henderson}
13663704993fSRichard Henderson
13673704993fSRichard Hendersonstatic void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
13683704993fSRichard Henderson                         TCGReg dest, TCGReg c1, TCGArg c2,
1369748b7f3eSRichard Henderson                         bool c2const, bool neg)
13703704993fSRichard Henderson{
13713704993fSRichard Henderson    int cc;
13723704993fSRichard Henderson
1373128c7d51SRichard Henderson    /* With LOC2, we can always emit the minimum 3 insns.  */
13743704993fSRichard Henderson    if (HAVE_FACILITY(LOAD_ON_COND2)) {
13753704993fSRichard Henderson        /* Emit: d = 0, d = (cc ? 1 : d).  */
13763704993fSRichard Henderson        cc = tgen_cmp(s, type, cond, c1, c2, c2const, false);
1377128c7d51SRichard Henderson        tcg_out_movi(s, TCG_TYPE_I64, dest, 0);
1378128c7d51SRichard Henderson        tcg_out_insn(s, RIEg, LOCGHI, dest, neg ? -1 : 1, cc);
1379128c7d51SRichard Henderson        return;
1380128c7d51SRichard Henderson    }
1381128c7d51SRichard Henderson
1382128c7d51SRichard Henderson    switch (cond) {
1383128c7d51SRichard Henderson    case TCG_COND_GEU:
1384128c7d51SRichard Henderson    case TCG_COND_LTU:
1385128c7d51SRichard Henderson    case TCG_COND_LT:
1386128c7d51SRichard Henderson    case TCG_COND_GE:
1387128c7d51SRichard Henderson        /* Swap operands so that we can use LEU/GTU/GT/LE.  */
1388128c7d51SRichard Henderson        if (!c2const) {
1389128c7d51SRichard Henderson            TCGReg t = c1;
1390128c7d51SRichard Henderson            c1 = c2;
1391128c7d51SRichard Henderson            c2 = t;
1392128c7d51SRichard Henderson            cond = tcg_swap_cond(cond);
1393128c7d51SRichard Henderson        }
13943704993fSRichard Henderson        break;
13953704993fSRichard Henderson    default:
13963704993fSRichard Henderson        break;
13973704993fSRichard Henderson    }
13983704993fSRichard Henderson
13993704993fSRichard Henderson    switch (cond) {
14003704993fSRichard Henderson    case TCG_COND_NE:
14013704993fSRichard Henderson        /* X != 0 is X > 0.  */
14023704993fSRichard Henderson        if (c2const && c2 == 0) {
14033704993fSRichard Henderson            cond = TCG_COND_GTU;
14043704993fSRichard Henderson        } else {
14053704993fSRichard Henderson            break;
1406128c7d51SRichard Henderson        }
1407128c7d51SRichard Henderson        /* fallthru */
1408128c7d51SRichard Henderson
1409128c7d51SRichard Henderson    case TCG_COND_GTU:
14103704993fSRichard Henderson    case TCG_COND_GT:
14113704993fSRichard Henderson        /*
14123704993fSRichard Henderson         * The result of a compare has CC=2 for GT and CC=3 unused.
1413128c7d51SRichard Henderson         * ADD LOGICAL WITH CARRY considers (CC & 2) the carry bit.
1414128c7d51SRichard Henderson         */
1415128c7d51SRichard Henderson        tgen_cmp(s, type, cond, c1, c2, c2const, true);
1416128c7d51SRichard Henderson        tcg_out_movi(s, type, dest, 0);
1417128c7d51SRichard Henderson        tcg_out_insn(s, RRE, ALCGR, dest, dest);
1418128c7d51SRichard Henderson        if (neg) {
1419128c7d51SRichard Henderson            if (type == TCG_TYPE_I32) {
14203704993fSRichard Henderson                tcg_out_insn(s, RR, LCR, dest, dest);
14213704993fSRichard Henderson            } else {
14223704993fSRichard Henderson                tcg_out_insn(s, RRE, LCGR, dest, dest);
14233704993fSRichard Henderson            }
14243704993fSRichard Henderson        }
14253704993fSRichard Henderson        return;
14263704993fSRichard Henderson
14273704993fSRichard Henderson    case TCG_COND_EQ:
14283704993fSRichard Henderson        /* X == 0 is X <= 0.  */
14293704993fSRichard Henderson        if (c2const && c2 == 0) {
14303704993fSRichard Henderson            cond = TCG_COND_LEU;
14313704993fSRichard Henderson        } else {
14323704993fSRichard Henderson            break;
1433128c7d51SRichard Henderson        }
1434128c7d51SRichard Henderson        /* fallthru */
1435128c7d51SRichard Henderson
1436128c7d51SRichard Henderson    case TCG_COND_LEU:
1437128c7d51SRichard Henderson    case TCG_COND_LE:
14383704993fSRichard Henderson        /*
14393704993fSRichard Henderson         * As above, but we're looking for borrow, or !carry.
1440128c7d51SRichard Henderson         * The second insn computes d - d - borrow, or -1 for true
14413704993fSRichard Henderson         * and 0 for false.  So we must mask to 1 bit afterward.
1442c68d5b7aSRichard Henderson         */
1443128c7d51SRichard Henderson        tgen_cmp(s, type, cond, c1, c2, c2const, true);
14443704993fSRichard Henderson        tcg_out_insn(s, RRE, SLBGR, dest, dest);
14453704993fSRichard Henderson        if (!neg) {
14463704993fSRichard Henderson            tgen_andi(s, type, dest, 1);
14473704993fSRichard Henderson        }
14483704993fSRichard Henderson        return;
14493704993fSRichard Henderson
14503704993fSRichard Henderson    default:
14513704993fSRichard Henderson        g_assert_not_reached();
1452128c7d51SRichard Henderson    }
14531dd06b1aSRichard Henderson
14543704993fSRichard Henderson    cc = tgen_cmp(s, type, cond, c1, c2, c2const, false);
14553704993fSRichard Henderson    /* Emit: d = 0, t = 1, d = (cc ? t : d).  */
145623d1394aSRichard Henderson    tcg_out_movi(s, TCG_TYPE_I64, dest, 0);
145723d1394aSRichard Henderson    tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, neg ? -1 : 1);
145823d1394aSRichard Henderson    tcg_out_insn(s, RRFc, LOCGR, dest, TCG_TMP0, cc);
145923d1394aSRichard Henderson}
146023d1394aSRichard Henderson
146123d1394aSRichard Hendersonstatic void tgen_movcond_int(TCGContext *s, TCGType type, TCGReg dest,
146223d1394aSRichard Henderson                             TCGArg v3, int v3const, TCGReg v4,
146323d1394aSRichard Henderson                             int cc, int inv_cc)
146423d1394aSRichard Henderson{
146523d1394aSRichard Henderson    TCGReg src;
146623d1394aSRichard Henderson
146723d1394aSRichard Henderson    if (v3const) {
146823d1394aSRichard Henderson        if (dest == v4) {
146923d1394aSRichard Henderson            if (HAVE_FACILITY(LOAD_ON_COND2)) {
147023d1394aSRichard Henderson                /* Emit: if (cc) dest = v3. */
147123d1394aSRichard Henderson                tcg_out_insn(s, RIEg, LOCGHI, dest, v3, cc);
147223d1394aSRichard Henderson                return;
147323d1394aSRichard Henderson            }
147423d1394aSRichard Henderson            tcg_out_insn(s, RI, LGHI, TCG_TMP0, v3);
147523d1394aSRichard Henderson            src = TCG_TMP0;
147623d1394aSRichard Henderson        } else {
147723d1394aSRichard Henderson            /* LGR+LOCGHI is larger than LGHI+LOCGR. */
14780bbf0f7aSRichard Henderson            tcg_out_insn(s, RI, LGHI, dest, v3);
14790bbf0f7aSRichard Henderson            cc = inv_cc;
14800bbf0f7aSRichard Henderson            src = v4;
14810bbf0f7aSRichard Henderson        }
14820bbf0f7aSRichard Henderson    } else {
148323d1394aSRichard Henderson        if (HAVE_FACILITY(MISC_INSN_EXT3)) {
148423d1394aSRichard Henderson            /* Emit: dest = cc ? v3 : v4. */
148523d1394aSRichard Henderson            tcg_out_insn(s, RRFam, SELGR, dest, v3, v4, cc);
148623d1394aSRichard Henderson            return;
148723d1394aSRichard Henderson        }
148823d1394aSRichard Henderson        if (dest == v4) {
148923d1394aSRichard Henderson            src = v3;
149023d1394aSRichard Henderson        } else {
149123d1394aSRichard Henderson            tcg_out_mov(s, type, dest, v3);
149223d1394aSRichard Henderson            cc = inv_cc;
149323d1394aSRichard Henderson            src = v4;
149423d1394aSRichard Henderson        }
149523d1394aSRichard Henderson    }
14963704993fSRichard Henderson
14973704993fSRichard Henderson    /* Emit: if (cc) dest = src. */
149823d1394aSRichard Henderson    tcg_out_insn(s, RRFc, LOCGR, dest, src, cc);
14993704993fSRichard Henderson}
15005c837bbcSRichard Henderson
15015c837bbcSRichard Hendersonstatic void tgen_movcond(TCGContext *s, TCGType type, TCGCond c, TCGReg dest,
15025c837bbcSRichard Henderson                         TCGReg c1, TCGArg c2, int c2const,
150323d1394aSRichard Henderson                         TCGArg v3, int v3const, TCGReg v4)
15043704993fSRichard Henderson{
15053704993fSRichard Henderson    int cc, inv_cc;
15063704993fSRichard Henderson
15073704993fSRichard Henderson    cc = tgen_cmp2(s, type, c, c1, c2, c2const, false, &inv_cc);
15083704993fSRichard Henderson    tgen_movcond_int(s, type, dest, v3, v3const, v4, cc, inv_cc);
15093704993fSRichard Henderson}
15103704993fSRichard Henderson
15113704993fSRichard Hendersonstatic void tgen_clz(TCGContext *s, TCGReg dest, TCGReg a1,
15123704993fSRichard Henderson                     TCGArg a2, int a2const)
15133704993fSRichard Henderson{
15143704993fSRichard Henderson    /* Since this sets both R and R+1, we have no choice but to store the
15153704993fSRichard Henderson       result into R0, allowing R1 == TCG_TMP0 to be clobbered as well.  */
1516bfff8518SRichard Henderson    QEMU_BUILD_BUG_ON(TCG_TMP0 != TCG_REG_R1);
15173704993fSRichard Henderson    tcg_out_insn(s, RRE, FLOGR, TCG_REG_R0, a1);
1518bfff8518SRichard Henderson
1519bfff8518SRichard Henderson    if (a2const && a2 == 64) {
1520bfff8518SRichard Henderson        tcg_out_mov(s, TCG_TYPE_I64, dest, TCG_REG_R0);
1521bfff8518SRichard Henderson        return;
1522bfff8518SRichard Henderson    }
1523bfff8518SRichard Henderson
1524bfff8518SRichard Henderson    /*
15253704993fSRichard Henderson     * Conditions from FLOGR are:
15263704993fSRichard Henderson     *   2 -> one bit found
152729a5ea73SRichard Henderson     *   8 -> no one bit found
152829a5ea73SRichard Henderson     */
152929a5ea73SRichard Henderson    tgen_movcond_int(s, TCG_TYPE_I64, dest, a2, a2const, TCG_REG_R0, 8, 2);
153029a5ea73SRichard Henderson}
153129a5ea73SRichard Henderson
15329ecf5f61SRichard Hendersonstatic void tgen_ctpop(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
153329a5ea73SRichard Henderson{
153429a5ea73SRichard Henderson    /* With MIE3, and bit 0 of m4 set, we get the complete result. */
153529a5ea73SRichard Henderson    if (HAVE_FACILITY(MISC_INSN_EXT3)) {
153629a5ea73SRichard Henderson        if (type == TCG_TYPE_I32) {
153729a5ea73SRichard Henderson            tcg_out_ext32u(s, dest, src);
153829a5ea73SRichard Henderson            src = dest;
153929a5ea73SRichard Henderson        }
154029a5ea73SRichard Henderson        tcg_out_insn(s, RRFc, POPCNT, dest, src, 8);
154129a5ea73SRichard Henderson        return;
154229a5ea73SRichard Henderson    }
154329a5ea73SRichard Henderson
154429a5ea73SRichard Henderson    /* Without MIE3, each byte gets the count of bits for the byte. */
154529a5ea73SRichard Henderson    tcg_out_insn(s, RRFc, POPCNT, dest, src, 0);
154629a5ea73SRichard Henderson
154729a5ea73SRichard Henderson    /* Multiply to sum each byte at the top of the word. */
154829a5ea73SRichard Henderson    if (type == TCG_TYPE_I32) {
154929a5ea73SRichard Henderson        tcg_out_insn(s, RIL, MSFI, dest, 0x01010101);
155029a5ea73SRichard Henderson        tcg_out_sh32(s, RS_SRL, dest, TCG_REG_NONE, 24);
155129a5ea73SRichard Henderson    } else {
155229a5ea73SRichard Henderson        tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, 0x0101010101010101ull);
15533704993fSRichard Henderson        tcg_out_insn(s, RRE, MSGR, dest, TCG_TMP0);
15543704993fSRichard Henderson        tcg_out_sh64(s, RSY_SRLG, dest, dest, TCG_REG_NONE, 56);
15553704993fSRichard Henderson    }
15563704993fSRichard Henderson}
15573704993fSRichard Henderson
15583704993fSRichard Hendersonstatic void tgen_deposit(TCGContext *s, TCGReg dest, TCGReg src,
15593704993fSRichard Henderson                         int ofs, int len, int z)
15603704993fSRichard Henderson{
15613704993fSRichard Henderson    int lsb = (63 - ofs);
15623704993fSRichard Henderson    int msb = lsb - (len - 1);
15633704993fSRichard Henderson    tcg_out_risbg(s, dest, src, msb, lsb, ofs, z);
15643704993fSRichard Henderson}
15653704993fSRichard Henderson
15663704993fSRichard Hendersonstatic void tgen_extract(TCGContext *s, TCGReg dest, TCGReg src,
15673704993fSRichard Henderson                         int ofs, int len)
15683704993fSRichard Henderson{
15693704993fSRichard Henderson    tcg_out_risbg(s, dest, src, 64 - len, 63, 64 - ofs, 1);
15703704993fSRichard Henderson}
15713704993fSRichard Henderson
15723704993fSRichard Hendersonstatic void tgen_gotoi(TCGContext *s, int cc, const tcg_insn_unit *dest)
15733704993fSRichard Henderson{
15743704993fSRichard Henderson    ptrdiff_t off = tcg_pcrel_diff(s, dest) >> 1;
15753704993fSRichard Henderson    if (off == (int16_t)off) {
15763704993fSRichard Henderson        tcg_out_insn(s, RI, BRC, cc, off);
15773704993fSRichard Henderson    } else if (off == (int32_t)off) {
15783704993fSRichard Henderson        tcg_out_insn(s, RIL, BRCL, cc, off);
15793704993fSRichard Henderson    } else {
15803704993fSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)dest);
15813704993fSRichard Henderson        tcg_out_insn(s, RR, BCR, cc, TCG_TMP0);
15823704993fSRichard Henderson    }
15833704993fSRichard Henderson}
15843704993fSRichard Henderson
15853704993fSRichard Hendersonstatic void tgen_branch(TCGContext *s, int cc, TCGLabel *l)
15863704993fSRichard Henderson{
15873704993fSRichard Henderson    if (l->has_value) {
15883704993fSRichard Henderson        tgen_gotoi(s, cc, l->u.value_ptr);
15893704993fSRichard Henderson    } else {
15903704993fSRichard Henderson        tcg_out16(s, RI_BRC | (cc << 4));
15913704993fSRichard Henderson        tcg_out_reloc(s, s->code_ptr, R_390_PC16DBL, l, 2);
15923704993fSRichard Henderson        s->code_ptr += 1;
15933704993fSRichard Henderson    }
15943704993fSRichard Henderson}
1595d84ca804SRichard Henderson
15963704993fSRichard Hendersonstatic void tgen_compare_branch(TCGContext *s, S390Opcode opc, int cc,
15973704993fSRichard Henderson                                TCGReg r1, TCGReg r2, TCGLabel *l)
15983704993fSRichard Henderson{
15993704993fSRichard Henderson    tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
16003704993fSRichard Henderson    /* Format RIE-b */
16013704993fSRichard Henderson    tcg_out16(s, (opc & 0xff00) | (r1 << 4) | r2);
16023704993fSRichard Henderson    tcg_out16(s, 0);
16033704993fSRichard Henderson    tcg_out16(s, cc << 12 | (opc & 0xff));
16043704993fSRichard Henderson}
1605d84ca804SRichard Henderson
16063704993fSRichard Hendersonstatic void tgen_compare_imm_branch(TCGContext *s, S390Opcode opc, int cc,
16073704993fSRichard Henderson                                    TCGReg r1, int i2, TCGLabel *l)
16083704993fSRichard Henderson{
16093704993fSRichard Henderson    tcg_out_reloc(s, s->code_ptr + 1, R_390_PC16DBL, l, 2);
16103704993fSRichard Henderson    /* Format RIE-c */
16113704993fSRichard Henderson    tcg_out16(s, (opc & 0xff00) | (r1 << 4) | cc);
16123704993fSRichard Henderson    tcg_out16(s, 0);
16133704993fSRichard Henderson    tcg_out16(s, (i2 << 8) | (opc & 0xff));
16143704993fSRichard Henderson}
1615585b7a42SRichard Henderson
1616585b7a42SRichard Hendersonstatic void tgen_brcond(TCGContext *s, TCGType type, TCGCond c,
16173704993fSRichard Henderson                        TCGReg r1, TCGArg c2, int c2const, TCGLabel *l)
16183704993fSRichard Henderson{
16193704993fSRichard Henderson    int cc;
16203704993fSRichard Henderson
16213704993fSRichard Henderson    if (!is_tst_cond(c)) {
16223704993fSRichard Henderson        bool is_unsigned = is_unsigned_cond(c);
16233704993fSRichard Henderson        bool in_range;
16243704993fSRichard Henderson        S390Opcode opc;
1625d84ca804SRichard Henderson
1626d84ca804SRichard Henderson        cc = tcg_cond_to_s390_cond[c];
16273704993fSRichard Henderson
16283704993fSRichard Henderson        if (!c2const) {
16293704993fSRichard Henderson            opc = (type == TCG_TYPE_I32
16303704993fSRichard Henderson                   ? (is_unsigned ? RIEb_CLRJ : RIEb_CRJ)
16319c3bfb79SRichard Henderson                   : (is_unsigned ? RIEb_CLGRJ : RIEb_CGRJ));
16329c3bfb79SRichard Henderson            tgen_compare_branch(s, opc, cc, r1, c2, l);
16339c3bfb79SRichard Henderson            return;
16349c3bfb79SRichard Henderson        }
16359c3bfb79SRichard Henderson
16369c3bfb79SRichard Henderson        /*
16373704993fSRichard Henderson         * COMPARE IMMEDIATE AND BRANCH RELATIVE has an 8-bit immediate field.
16383704993fSRichard Henderson         * If the immediate we've been given does not fit that range, we'll
1639d84ca804SRichard Henderson         * fall back to separate compare and branch instructions using the
16403704993fSRichard Henderson         * larger comparison range afforded by COMPARE IMMEDIATE.
16413704993fSRichard Henderson         */
1642d84ca804SRichard Henderson        if (type == TCG_TYPE_I32) {
16433704993fSRichard Henderson            if (is_unsigned) {
16443704993fSRichard Henderson                opc = RIEc_CLIJ;
16453704993fSRichard Henderson                in_range = (uint32_t)c2 == (uint8_t)c2;
16463704993fSRichard Henderson            } else {
1647d84ca804SRichard Henderson                opc = RIEc_CIJ;
16483704993fSRichard Henderson                in_range = (int32_t)c2 == (int8_t)c2;
16493704993fSRichard Henderson            }
1650d84ca804SRichard Henderson        } else {
16513704993fSRichard Henderson            if (is_unsigned) {
16523704993fSRichard Henderson                opc = RIEc_CLGIJ;
16533704993fSRichard Henderson                in_range = (uint64_t)c2 == (uint8_t)c2;
16543704993fSRichard Henderson            } else {
16553704993fSRichard Henderson                opc = RIEc_CGIJ;
16563704993fSRichard Henderson                in_range = (int64_t)c2 == (int8_t)c2;
16573704993fSRichard Henderson            }
1658585b7a42SRichard Henderson        }
16593704993fSRichard Henderson        if (in_range) {
16603704993fSRichard Henderson            tgen_compare_imm_branch(s, opc, cc, r1, c2, l);
16613704993fSRichard Henderson            return;
16623704993fSRichard Henderson        }
16633704993fSRichard Henderson    }
1664cee44b03SRichard Henderson
16653704993fSRichard Henderson    cc = tgen_cmp(s, type, c, r1, c2, c2const, false);
16663704993fSRichard Henderson    tgen_branch(s, cc, l);
16673704993fSRichard Henderson}
16683704993fSRichard Henderson
16693704993fSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *dest)
16703704993fSRichard Henderson{
16713704993fSRichard Henderson    ptrdiff_t off = tcg_pcrel_diff(s, dest) >> 1;
16723704993fSRichard Henderson    if (off == (int32_t)off) {
16733704993fSRichard Henderson        tcg_out_insn(s, RIL, BRASL, TCG_REG_R14, off);
16743704993fSRichard Henderson    } else {
1675cee44b03SRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)dest);
1676cee44b03SRichard Henderson        tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_TMP0);
1677cee44b03SRichard Henderson    }
1678cee44b03SRichard Henderson}
1679cee44b03SRichard Henderson
1680cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *dest,
168103654748SRichard Henderson                         const TCGHelperInfo *info)
168203654748SRichard Henderson{
168303654748SRichard Henderson    tcg_out_call_int(s, dest);
168403654748SRichard Henderson}
168500406e6dSRichard Henderson
168603654748SRichard Hendersontypedef struct {
168703654748SRichard Henderson    TCGReg base;
16887b880107SRichard Henderson    TCGReg index;
16897b880107SRichard Henderson    int disp;
16904caad79fSRichard Henderson    TCGAtomAlign aa;
16914caad79fSRichard Henderson} HostAddress;
16924caad79fSRichard Henderson
16937b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
16947b880107SRichard Henderson{
16957b880107SRichard Henderson    TCGAtomAlign aa;
16964caad79fSRichard Henderson
16974caad79fSRichard Henderson    if ((memop & MO_SIZE) <= MO_64) {
16984caad79fSRichard Henderson        return true;
16994caad79fSRichard Henderson    }
17004caad79fSRichard Henderson
17014caad79fSRichard Henderson    /*
17024caad79fSRichard Henderson     * Reject 16-byte memop with 16-byte atomicity,
17034caad79fSRichard Henderson     * but do allow a pair of 64-bit operations.
17043704993fSRichard Henderson     */
170503654748SRichard Henderson    aa = atom_and_align_for_opc(tcg_ctx, memop, MO_ATOM_IFALIGN, true);
17063704993fSRichard Henderson    return aa.atom <= MO_64;
17073704993fSRichard Henderson}
17083704993fSRichard Henderson
170903654748SRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg data,
17103704993fSRichard Henderson                                   HostAddress h)
17113704993fSRichard Henderson{
171203654748SRichard Henderson    switch (opc & (MO_SSIZE | MO_BSWAP)) {
17133704993fSRichard Henderson    case MO_UB:
17143704993fSRichard Henderson        tcg_out_insn(s, RXY, LLGC, data, h.base, h.index, h.disp);
17153704993fSRichard Henderson        break;
17163704993fSRichard Henderson    case MO_SB:
171703654748SRichard Henderson        tcg_out_insn(s, RXY, LGB, data, h.base, h.index, h.disp);
1718379afdffSRichard Henderson        break;
17193704993fSRichard Henderson
17203704993fSRichard Henderson    case MO_UW | MO_BSWAP:
172103654748SRichard Henderson        /* swapped unsigned halfword load with upper bits zeroed */
17223704993fSRichard Henderson        tcg_out_insn(s, RXY, LRVH, data, h.base, h.index, h.disp);
17233704993fSRichard Henderson        tcg_out_ext16u(s, data, data);
17243704993fSRichard Henderson        break;
17253704993fSRichard Henderson    case MO_UW:
172603654748SRichard Henderson        tcg_out_insn(s, RXY, LLGH, data, h.base, h.index, h.disp);
1727753e42eaSRichard Henderson        break;
17283704993fSRichard Henderson
17293704993fSRichard Henderson    case MO_SW | MO_BSWAP:
173003654748SRichard Henderson        /* swapped sign-extended halfword load */
17313704993fSRichard Henderson        tcg_out_insn(s, RXY, LRVH, data, h.base, h.index, h.disp);
17323704993fSRichard Henderson        tcg_out_ext16s(s, TCG_TYPE_REG, data, data);
17333704993fSRichard Henderson        break;
17343704993fSRichard Henderson    case MO_SW:
173503654748SRichard Henderson        tcg_out_insn(s, RXY, LGH, data, h.base, h.index, h.disp);
17369ecf5f61SRichard Henderson        break;
17373704993fSRichard Henderson
17383704993fSRichard Henderson    case MO_UL | MO_BSWAP:
173903654748SRichard Henderson        /* swapped unsigned int load with upper bits zeroed */
17403704993fSRichard Henderson        tcg_out_insn(s, RXY, LRV, data, h.base, h.index, h.disp);
17413704993fSRichard Henderson        tcg_out_ext32u(s, data, data);
17423704993fSRichard Henderson        break;
17433704993fSRichard Henderson    case MO_UL:
174403654748SRichard Henderson        tcg_out_insn(s, RXY, LLGF, data, h.base, h.index, h.disp);
174552bf3398SRichard Henderson        break;
17463704993fSRichard Henderson
17473704993fSRichard Henderson    case MO_SL | MO_BSWAP:
174803654748SRichard Henderson        /* swapped sign-extended int load */
17493704993fSRichard Henderson        tcg_out_insn(s, RXY, LRV, data, h.base, h.index, h.disp);
17503704993fSRichard Henderson        tcg_out_ext32s(s, data, data);
1751fc313c64SFrédéric Pétrot        break;
175203654748SRichard Henderson    case MO_SL:
17533704993fSRichard Henderson        tcg_out_insn(s, RXY, LGF, data, h.base, h.index, h.disp);
1754fc313c64SFrédéric Pétrot        break;
175503654748SRichard Henderson
17563704993fSRichard Henderson    case MO_UQ | MO_BSWAP:
17573704993fSRichard Henderson        tcg_out_insn(s, RXY, LRVG, data, h.base, h.index, h.disp);
17583704993fSRichard Henderson        break;
1759732e89f4SRichard Henderson    case MO_UQ:
17603704993fSRichard Henderson        tcg_out_insn(s, RXY, LG, data, h.base, h.index, h.disp);
17613704993fSRichard Henderson        break;
17623704993fSRichard Henderson
17633704993fSRichard Henderson    default:
176403654748SRichard Henderson        g_assert_not_reached();
17653704993fSRichard Henderson    }
17663704993fSRichard Henderson}
17673704993fSRichard Henderson
176803654748SRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg data,
176903654748SRichard Henderson                                   HostAddress h)
17703704993fSRichard Henderson{
177103654748SRichard Henderson    switch (opc & (MO_SIZE | MO_BSWAP)) {
17723704993fSRichard Henderson    case MO_UB:
17733704993fSRichard Henderson        if (h.disp >= 0 && h.disp < 0x1000) {
17743704993fSRichard Henderson            tcg_out_insn(s, RX, STC, data, h.base, h.index, h.disp);
17753704993fSRichard Henderson        } else {
177603654748SRichard Henderson            tcg_out_insn(s, RXY, STCY, data, h.base, h.index, h.disp);
17773704993fSRichard Henderson        }
17783704993fSRichard Henderson        break;
177903654748SRichard Henderson
178003654748SRichard Henderson    case MO_UW | MO_BSWAP:
17813704993fSRichard Henderson        tcg_out_insn(s, RXY, STRVH, data, h.base, h.index, h.disp);
178203654748SRichard Henderson        break;
17833704993fSRichard Henderson    case MO_UW:
17843704993fSRichard Henderson        if (h.disp >= 0 && h.disp < 0x1000) {
17853704993fSRichard Henderson            tcg_out_insn(s, RX, STH, data, h.base, h.index, h.disp);
17863704993fSRichard Henderson        } else {
178703654748SRichard Henderson            tcg_out_insn(s, RXY, STHY, data, h.base, h.index, h.disp);
17883704993fSRichard Henderson        }
17893704993fSRichard Henderson        break;
179003654748SRichard Henderson
179103654748SRichard Henderson    case MO_UL | MO_BSWAP:
17923704993fSRichard Henderson        tcg_out_insn(s, RXY, STRV, data, h.base, h.index, h.disp);
179303654748SRichard Henderson        break;
17943704993fSRichard Henderson    case MO_UL:
17953704993fSRichard Henderson        if (h.disp >= 0 && h.disp < 0x1000) {
17963704993fSRichard Henderson            tcg_out_insn(s, RX, ST, data, h.base, h.index, h.disp);
1797fc313c64SFrédéric Pétrot        } else {
179803654748SRichard Henderson            tcg_out_insn(s, RXY, STY, data, h.base, h.index, h.disp);
17993704993fSRichard Henderson        }
1800fc313c64SFrédéric Pétrot        break;
180103654748SRichard Henderson
18023704993fSRichard Henderson    case MO_UQ | MO_BSWAP:
18033704993fSRichard Henderson        tcg_out_insn(s, RXY, STRVG, data, h.base, h.index, h.disp);
18043704993fSRichard Henderson        break;
1805732e89f4SRichard Henderson    case MO_UQ:
18063704993fSRichard Henderson        tcg_out_insn(s, RXY, STG, data, h.base, h.index, h.disp);
18073704993fSRichard Henderson        break;
18083704993fSRichard Henderson
1809eb491329SRichard Henderson    default:
1810eb491329SRichard Henderson        g_assert_not_reached();
1811eb491329SRichard Henderson    }
1812eb491329SRichard Henderson}
18133704993fSRichard Henderson
18143704993fSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
1815eb491329SRichard Henderson    .ntmp = 1, .tmp = { TCG_TMP0 }
18163704993fSRichard Henderson};
18173704993fSRichard Henderson
18183704993fSRichard Hendersonstatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
18193704993fSRichard Henderson{
18203704993fSRichard Henderson    MemOp opc = get_memop(lb->oi);
18213704993fSRichard Henderson
1822eb491329SRichard Henderson    if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
18230cadc1edSRichard Henderson                     (intptr_t)tcg_splitwx_to_rx(s->code_ptr), 2)) {
1824eb491329SRichard Henderson        return false;
18253704993fSRichard Henderson    }
18263704993fSRichard Henderson
18273704993fSRichard Henderson    tcg_out_ld_helper_args(s, lb, &ldst_helper_param);
18283704993fSRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SIZE]);
18293704993fSRichard Henderson    tcg_out_ld_helper_ret(s, lb, false, &ldst_helper_param);
18303704993fSRichard Henderson
18313704993fSRichard Henderson    tgen_gotoi(s, S390_CC_ALWAYS, lb->raddr);
1832eb491329SRichard Henderson    return true;
18333704993fSRichard Henderson}
18343704993fSRichard Henderson
18353704993fSRichard Hendersonstatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
18363704993fSRichard Henderson{
18373704993fSRichard Henderson    MemOp opc = get_memop(lb->oi);
18383704993fSRichard Henderson
1839eb491329SRichard Henderson    if (!patch_reloc(lb->label_ptr[0], R_390_PC16DBL,
18400cadc1edSRichard Henderson                     (intptr_t)tcg_splitwx_to_rx(s->code_ptr), 2)) {
18413704993fSRichard Henderson        return false;
18423704993fSRichard Henderson    }
18433704993fSRichard Henderson
18443704993fSRichard Henderson    tcg_out_st_helper_args(s, lb, &ldst_helper_param);
18451cd49868SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE]);
1846d0a9bb5eSRichard Henderson
1847d0a9bb5eSRichard Henderson    tgen_gotoi(s, S390_CC_ALWAYS, lb->raddr);
1848d0a9bb5eSRichard Henderson    return true;
18490741b25eSRichard Henderson}
18507893e42dSPhilippe Mathieu-Daudé
18517893e42dSPhilippe Mathieu-Daudé/* We're expecting to use a 20-bit negative offset on the tlb memory ops.  */
18520741b25eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -(1 << 19)
18530741b25eSRichard Henderson
18540741b25eSRichard Henderson/*
18550741b25eSRichard Henderson * For system-mode, perform the TLB load and compare.
18560741b25eSRichard Henderson * For user-mode, perform any required alignment tests.
18570741b25eSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
18583704993fSRichard Henderson * is required and fill in @h with the host address for the fast path.
1859d588946bSRichard Henderson */
18600741b25eSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
18610741b25eSRichard Henderson                                           TCGReg addr_reg, MemOpIdx oi,
18624caad79fSRichard Henderson                                           bool is_ld)
186300406e6dSRichard Henderson{
186400406e6dSRichard Henderson    TCGType addr_type = s->addr_type;
18654caad79fSRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
186600406e6dSRichard Henderson    MemOp opc = get_memop(oi);
186703654748SRichard Henderson    MemOp s_bits = opc & MO_SIZE;
18682e486b59SRichard Henderson    unsigned a_mask;
18690741b25eSRichard Henderson
18700741b25eSRichard Henderson    h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, s_bits == MO_128);
1871d0a9bb5eSRichard Henderson    a_mask = (1 << h->aa.align) - 1;
18720741b25eSRichard Henderson
18730741b25eSRichard Henderson    if (tcg_use_softmmu) {
18740741b25eSRichard Henderson        unsigned s_mask = (1 << s_bits) - 1;
18750741b25eSRichard Henderson        int mem_index = get_mmuidx(oi);
18760741b25eSRichard Henderson        int fast_off = tlb_mask_table_ofs(s, mem_index);
18770741b25eSRichard Henderson        int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
18780741b25eSRichard Henderson        int table_off = fast_off + offsetof(CPUTLBDescFast, table);
18790741b25eSRichard Henderson        int ofs, a_off;
18800741b25eSRichard Henderson        uint64_t tlb_mask;
18810741b25eSRichard Henderson
188294901422SRichard Henderson        ldst = new_ldst_label(s);
1883aece72b7SRichard Henderson        ldst->is_ld = is_ld;
18840741b25eSRichard Henderson        ldst->oi = oi;
188594901422SRichard Henderson        ldst->addrlo_reg = addr_reg;
188694901422SRichard Henderson
18870741b25eSRichard Henderson        tcg_out_sh64(s, RSY_SRLG, TCG_TMP0, addr_reg, TCG_REG_NONE,
18880741b25eSRichard Henderson                     s->page_bits - CPU_TLB_ENTRY_BITS);
18892e486b59SRichard Henderson
18902e486b59SRichard Henderson        tcg_out_insn(s, RXY, NG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, mask_off);
18912e486b59SRichard Henderson        tcg_out_insn(s, RXY, AG, TCG_TMP0, TCG_AREG0, TCG_REG_NONE, table_off);
18922e486b59SRichard Henderson
18930741b25eSRichard Henderson        /*
189400406e6dSRichard Henderson         * For aligned accesses, we check the first byte and include the
1895aece72b7SRichard Henderson         * alignment bits within the address.  For unaligned access, we
18960741b25eSRichard Henderson         * check that we don't cross pages using the address of the last
189794901422SRichard Henderson         * byte of the access.
18980741b25eSRichard Henderson         */
189994901422SRichard Henderson        a_off = (a_mask >= s_mask ? 0 : s_mask - a_mask);
1900d588946bSRichard Henderson        tlb_mask = (uint64_t)s->page_mask | a_mask;
19010741b25eSRichard Henderson        if (a_off == 0) {
19020741b25eSRichard Henderson            tgen_andi_risbg(s, TCG_REG_R0, addr_reg, tlb_mask);
19030741b25eSRichard Henderson        } else {
19040741b25eSRichard Henderson            tcg_out_insn(s, RX, LA, TCG_REG_R0, addr_reg, TCG_REG_NONE, a_off);
19050741b25eSRichard Henderson            tgen_andi(s, addr_type, TCG_REG_R0, tlb_mask);
19060741b25eSRichard Henderson        }
19070741b25eSRichard Henderson
1908d588946bSRichard Henderson        if (is_ld) {
1909238f4380SRichard Henderson            ofs = offsetof(CPUTLBEntry, addr_read);
191094901422SRichard Henderson        } else {
19110741b25eSRichard Henderson            ofs = offsetof(CPUTLBEntry, addr_write);
191294901422SRichard Henderson        }
19130741b25eSRichard Henderson        if (addr_type == TCG_TYPE_I32) {
19140741b25eSRichard Henderson            ofs += HOST_BIG_ENDIAN * 4;
19150741b25eSRichard Henderson            tcg_out_insn(s, RX, C, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
19160741b25eSRichard Henderson        } else {
19170741b25eSRichard Henderson            tcg_out_insn(s, RXY, CG, TCG_REG_R0, TCG_TMP0, TCG_REG_NONE, ofs);
191894901422SRichard Henderson        }
191994901422SRichard Henderson
19200741b25eSRichard Henderson        tcg_out16(s, RI_BRC | (S390_CC_NE << 4));
19210741b25eSRichard Henderson        ldst->label_ptr[0] = s->code_ptr++;
1922d588946bSRichard Henderson
19238b1b4597SRichard Henderson        h->index = TCG_TMP0;
19248b1b4597SRichard Henderson        tcg_out_insn(s, RXY, LG, h->index, TCG_TMP0, TCG_REG_NONE,
19258b1b4597SRichard Henderson                     offsetof(CPUTLBEntry, addend));
19268b1b4597SRichard Henderson
19270741b25eSRichard Henderson        if (addr_type == TCG_TYPE_I32) {
19280741b25eSRichard Henderson            tcg_out_insn(s, RRE, ALGFR, h->index, addr_reg);
19292e486b59SRichard Henderson            h->base = TCG_REG_NONE;
19300741b25eSRichard Henderson        } else {
19310741b25eSRichard Henderson            h->base = addr_reg;
19320741b25eSRichard Henderson        }
19330741b25eSRichard Henderson        h->disp = 0;
19340741b25eSRichard Henderson    } else {
19350741b25eSRichard Henderson        if (a_mask) {
193600406e6dSRichard Henderson            ldst = new_ldst_label(s);
19370741b25eSRichard Henderson            ldst->is_ld = is_ld;
19380741b25eSRichard Henderson            ldst->oi = oi;
1939585b7a42SRichard Henderson            ldst->addrlo_reg = addr_reg;
19400741b25eSRichard Henderson
19410741b25eSRichard Henderson            tcg_debug_assert(a_mask <= 0xffff);
19420741b25eSRichard Henderson            tcg_out_insn(s, RI, TMLL, addr_reg, a_mask);
19430741b25eSRichard Henderson
1944d588946bSRichard Henderson            tcg_out16(s, RI_BRC | (S390_TM_NE << 4));
194503654748SRichard Henderson            ldst->label_ptr[0] = s->code_ptr++;
19460741b25eSRichard Henderson        }
19473704993fSRichard Henderson
19483704993fSRichard Henderson        h->base = addr_reg;
19490741b25eSRichard Henderson        if (addr_type == TCG_TYPE_I32) {
19500741b25eSRichard Henderson            tcg_out_ext32u(s, TCG_TMP0, addr_reg);
19513704993fSRichard Henderson            h->base = TCG_TMP0;
19520741b25eSRichard Henderson        }
19530741b25eSRichard Henderson        if (guest_base < 0x80000) {
19543704993fSRichard Henderson            h->index = TCG_REG_NONE;
19552e486b59SRichard Henderson            h->disp = guest_base;
19560741b25eSRichard Henderson        } else {
19570741b25eSRichard Henderson            h->index = TCG_GUEST_BASE_REG;
19583704993fSRichard Henderson            h->disp = 0;
19593704993fSRichard Henderson        }
19603704993fSRichard Henderson    }
196101a3b5deSRichard Henderson
19623704993fSRichard Henderson    return ldst;
19630741b25eSRichard Henderson}
196403654748SRichard Henderson
196503654748SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext* s, TCGReg data_reg, TCGReg addr_reg,
19660741b25eSRichard Henderson                            MemOpIdx oi, TCGType data_type)
19670741b25eSRichard Henderson{
19683704993fSRichard Henderson    TCGLabelQemuLdst *ldst;
19690741b25eSRichard Henderson    HostAddress h;
19700741b25eSRichard Henderson
19710741b25eSRichard Henderson    ldst = prepare_host_addr(s, &h, addr_reg, oi, true);
19720741b25eSRichard Henderson    tcg_out_qemu_ld_direct(s, get_memop(oi), data_reg, h);
19731cd49868SRichard Henderson
19743704993fSRichard Henderson    if (ldst) {
19753704993fSRichard Henderson        ldst->type = data_type;
19763704993fSRichard Henderson        ldst->datalo_reg = data_reg;
197701a3b5deSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
19783704993fSRichard Henderson    }
19790741b25eSRichard Henderson}
198003654748SRichard Henderson
198103654748SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg,
19820741b25eSRichard Henderson                            MemOpIdx oi, TCGType data_type)
19830741b25eSRichard Henderson{
19843704993fSRichard Henderson    TCGLabelQemuLdst *ldst;
19850741b25eSRichard Henderson    HostAddress h;
19860741b25eSRichard Henderson
19870741b25eSRichard Henderson    ldst = prepare_host_addr(s, &h, addr_reg, oi, false);
19880741b25eSRichard Henderson    tcg_out_qemu_st_direct(s, get_memop(oi), data_reg, h);
19891cd49868SRichard Henderson
19903704993fSRichard Henderson    if (ldst) {
19913704993fSRichard Henderson        ldst->type = data_type;
19924caad79fSRichard Henderson        ldst->datalo_reg = data_reg;
19934caad79fSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
19944caad79fSRichard Henderson    }
19954caad79fSRichard Henderson}
19964caad79fSRichard Henderson
19974caad79fSRichard Hendersonstatic void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg datalo, TCGReg datahi,
19984caad79fSRichard Henderson                                   TCGReg addr_reg, MemOpIdx oi, bool is_ld)
19994caad79fSRichard Henderson{
20004caad79fSRichard Henderson    TCGLabel *l1 = NULL, *l2 = NULL;
20014caad79fSRichard Henderson    TCGLabelQemuLdst *ldst;
20024caad79fSRichard Henderson    HostAddress h;
20034caad79fSRichard Henderson    bool need_bswap;
20044caad79fSRichard Henderson    bool use_pair;
20054caad79fSRichard Henderson    S390Opcode insn;
20064caad79fSRichard Henderson
20074caad79fSRichard Henderson    ldst = prepare_host_addr(s, &h, addr_reg, oi, is_ld);
20084caad79fSRichard Henderson
20094caad79fSRichard Henderson    use_pair = h.aa.atom < MO_128;
20104caad79fSRichard Henderson    need_bswap = get_memop(oi) & MO_BSWAP;
20114caad79fSRichard Henderson
20124caad79fSRichard Henderson    if (!use_pair) {
20134caad79fSRichard Henderson        /*
20144caad79fSRichard Henderson         * Atomicity requires we use LPQ.  If we've already checked for
20154caad79fSRichard Henderson         * 16-byte alignment, that's all we need.  If we arrive with
20164caad79fSRichard Henderson         * lesser alignment, we have determined that less than 16-byte
20174caad79fSRichard Henderson         * alignment can be satisfied with two 8-byte loads.
20184caad79fSRichard Henderson         */
20194caad79fSRichard Henderson        if (h.aa.align < MO_128) {
2020585b7a42SRichard Henderson            use_pair = true;
20214caad79fSRichard Henderson            l1 = gen_new_label();
20224caad79fSRichard Henderson            l2 = gen_new_label();
20234caad79fSRichard Henderson
20244caad79fSRichard Henderson            tcg_out_insn(s, RI, TMLL, addr_reg, 15);
20254caad79fSRichard Henderson            tgen_branch(s, S390_TM_NE, l1);
20264caad79fSRichard Henderson        }
20274caad79fSRichard Henderson
20284caad79fSRichard Henderson        tcg_debug_assert(!need_bswap);
20294caad79fSRichard Henderson        tcg_debug_assert(datalo & 1);
20304caad79fSRichard Henderson        tcg_debug_assert(datahi == datalo - 1);
20314caad79fSRichard Henderson        insn = is_ld ? RXY_LPQ : RXY_STPQ;
20324caad79fSRichard Henderson        tcg_out_insn_RXY(s, insn, datahi, h.base, h.index, h.disp);
20334caad79fSRichard Henderson
20344caad79fSRichard Henderson        if (use_pair) {
20354caad79fSRichard Henderson            tgen_branch(s, S390_CC_ALWAYS, l2);
20364caad79fSRichard Henderson            tcg_out_label(s, l1);
20374caad79fSRichard Henderson        }
20384caad79fSRichard Henderson    }
20394caad79fSRichard Henderson    if (use_pair) {
20404caad79fSRichard Henderson        TCGReg d1, d2;
20414caad79fSRichard Henderson
20424caad79fSRichard Henderson        if (need_bswap) {
20434caad79fSRichard Henderson            d1 = datalo, d2 = datahi;
20444caad79fSRichard Henderson            insn = is_ld ? RXY_LRVG : RXY_STRVG;
20454caad79fSRichard Henderson        } else {
20464caad79fSRichard Henderson            d1 = datahi, d2 = datalo;
20474caad79fSRichard Henderson            insn = is_ld ? RXY_LG : RXY_STG;
20484caad79fSRichard Henderson        }
20494caad79fSRichard Henderson
20504caad79fSRichard Henderson        if (h.base == d1 || h.index == d1) {
20514caad79fSRichard Henderson            tcg_out_insn(s, RXY, LAY, TCG_TMP0, h.base, h.index, h.disp);
20524caad79fSRichard Henderson            h.base = TCG_TMP0;
20534caad79fSRichard Henderson            h.index = TCG_REG_NONE;
20544caad79fSRichard Henderson            h.disp = 0;
20554caad79fSRichard Henderson        }
20564caad79fSRichard Henderson        tcg_out_insn_RXY(s, insn, d1, h.base, h.index, h.disp);
20574caad79fSRichard Henderson        tcg_out_insn_RXY(s, insn, d2, h.base, h.index, h.disp + 8);
20584caad79fSRichard Henderson    }
20594caad79fSRichard Henderson    if (l2) {
20604caad79fSRichard Henderson        tcg_out_label(s, l2);
20614caad79fSRichard Henderson    }
20624caad79fSRichard Henderson
20634caad79fSRichard Henderson    if (ldst) {
20644caad79fSRichard Henderson        ldst->type = TCG_TYPE_I128;
20654caad79fSRichard Henderson        ldst->datalo_reg = datalo;
2066b55a8d9dSRichard Henderson        ldst->datahi_reg = datahi;
2067b55a8d9dSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
2068b55a8d9dSRichard Henderson    }
2069b55a8d9dSRichard Henderson}
2070b55a8d9dSRichard Henderson
2071b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
2072b55a8d9dSRichard Henderson{
2073b55a8d9dSRichard Henderson    /* Reuse the zeroing that exists for goto_ptr.  */
2074b55a8d9dSRichard Henderson    if (a0 == 0) {
2075b55a8d9dSRichard Henderson        tgen_gotoi(s, S390_CC_ALWAYS, tcg_code_gen_epilogue);
2076b55a8d9dSRichard Henderson    } else {
2077cf7d6b8eSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, a0);
2078cf7d6b8eSRichard Henderson        tgen_gotoi(s, S390_CC_ALWAYS, tb_ret_addr);
2079cf7d6b8eSRichard Henderson    }
2080cf7d6b8eSRichard Henderson}
2081cf7d6b8eSRichard Henderson
2082cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
2083cf7d6b8eSRichard Henderson{
2084cf7d6b8eSRichard Henderson    /*
2085cf7d6b8eSRichard Henderson     * Branch displacement must be aligned for atomic patching;
2086cf7d6b8eSRichard Henderson     * see if we need to add extra nop before branch
2087cf7d6b8eSRichard Henderson     */
2088cf7d6b8eSRichard Henderson    if (!QEMU_PTR_IS_ALIGNED(s->code_ptr + 1, 4)) {
2089cf7d6b8eSRichard Henderson        tcg_out16(s, NOP);
2090cf7d6b8eSRichard Henderson    }
2091cf7d6b8eSRichard Henderson    tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4));
20920fe1c98dSRichard Henderson    set_jmp_insn_offset(s, which);
20930fe1c98dSRichard Henderson    s->code_ptr += 2;
20940fe1c98dSRichard Henderson    set_jmp_reset_offset(s, which);
20952fd2e78dSRichard Henderson}
20962fd2e78dSRichard Henderson
20972fd2e78dSRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
20980fe1c98dSRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
20990fe1c98dSRichard Henderson{
21000fe1c98dSRichard Henderson    if (!HAVE_FACILITY(GEN_INST_EXT)) {
21010fe1c98dSRichard Henderson        return;
21020fe1c98dSRichard Henderson    }
21030fe1c98dSRichard Henderson    /* patch the branch destination */
21040fe1c98dSRichard Henderson    uintptr_t addr = tb->jmp_target_addr[n];
21053704993fSRichard Henderson    intptr_t disp = addr - (jmp_rx - 2);
21063704993fSRichard Henderson    qatomic_set((int32_t *)jmp_rw, disp / 2);
21073704993fSRichard Henderson    /* no need to flush icache explicitly */
21083704993fSRichard Henderson}
21093704993fSRichard Henderson
21103704993fSRichard Henderson# define OP_32_64(x) \
21113704993fSRichard Henderson        case glue(glue(INDEX_op_,x),_i32): \
21123704993fSRichard Henderson        case glue(glue(INDEX_op_,x),_i64)
21133704993fSRichard Henderson
21143704993fSRichard Hendersonstatic inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
21153704993fSRichard Henderson                              const TCGArg args[TCG_MAX_OP_ARGS],
21163704993fSRichard Henderson                              const int const_args[TCG_MAX_OP_ARGS])
21173704993fSRichard Henderson{
21183704993fSRichard Henderson    S390Opcode op, op2;
21193704993fSRichard Henderson    TCGArg a0, a1, a2;
21203704993fSRichard Henderson
21213704993fSRichard Henderson    switch (opc) {
21223704993fSRichard Henderson    case INDEX_op_goto_ptr:
21233704993fSRichard Henderson        a0 = args[0];
21243704993fSRichard Henderson        tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, a0);
21253704993fSRichard Henderson        break;
21263704993fSRichard Henderson
21273704993fSRichard Henderson    OP_32_64(ld8u):
21283704993fSRichard Henderson        /* ??? LLC (RXY format) is only present with the extended-immediate
21293704993fSRichard Henderson           facility, whereas LLGC is always present.  */
21303704993fSRichard Henderson        tcg_out_mem(s, 0, RXY_LLGC, args[0], args[1], TCG_REG_NONE, args[2]);
21313704993fSRichard Henderson        break;
21323704993fSRichard Henderson
21333704993fSRichard Henderson    OP_32_64(ld8s):
21343704993fSRichard Henderson        /* ??? LB is no smaller than LGB, so no point to using it.  */
21353704993fSRichard Henderson        tcg_out_mem(s, 0, RXY_LGB, args[0], args[1], TCG_REG_NONE, args[2]);
21363704993fSRichard Henderson        break;
21373704993fSRichard Henderson
21383704993fSRichard Henderson    OP_32_64(ld16u):
21393704993fSRichard Henderson        /* ??? LLH (RXY format) is only present with the extended-immediate
21403704993fSRichard Henderson           facility, whereas LLGH is always present.  */
21413704993fSRichard Henderson        tcg_out_mem(s, 0, RXY_LLGH, args[0], args[1], TCG_REG_NONE, args[2]);
21423704993fSRichard Henderson        break;
21433704993fSRichard Henderson
21443704993fSRichard Henderson    case INDEX_op_ld16s_i32:
21453704993fSRichard Henderson        tcg_out_mem(s, RX_LH, RXY_LHY, args[0], args[1], TCG_REG_NONE, args[2]);
21463704993fSRichard Henderson        break;
21473704993fSRichard Henderson
21483704993fSRichard Henderson    case INDEX_op_ld_i32:
21493704993fSRichard Henderson        tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
21503704993fSRichard Henderson        break;
21513704993fSRichard Henderson
21523704993fSRichard Henderson    OP_32_64(st8):
21533704993fSRichard Henderson        tcg_out_mem(s, RX_STC, RXY_STCY, args[0], args[1],
21543704993fSRichard Henderson                    TCG_REG_NONE, args[2]);
21553704993fSRichard Henderson        break;
21563704993fSRichard Henderson
21573704993fSRichard Henderson    OP_32_64(st16):
21583704993fSRichard Henderson        tcg_out_mem(s, RX_STH, RXY_STHY, args[0], args[1],
21593704993fSRichard Henderson                    TCG_REG_NONE, args[2]);
21603704993fSRichard Henderson        break;
21613704993fSRichard Henderson
21623704993fSRichard Henderson    case INDEX_op_st_i32:
21633704993fSRichard Henderson        tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
21643704993fSRichard Henderson        break;
21653704993fSRichard Henderson
21663704993fSRichard Henderson    case INDEX_op_add_i32:
21673704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
21683704993fSRichard Henderson        if (const_args[2]) {
21693704993fSRichard Henderson        do_addi_32:
21703704993fSRichard Henderson            if (a0 == a1) {
21713704993fSRichard Henderson                if (a2 == (int16_t)a2) {
21723704993fSRichard Henderson                    tcg_out_insn(s, RI, AHI, a0, a2);
21733704993fSRichard Henderson                    break;
21743704993fSRichard Henderson                }
21753704993fSRichard Henderson                tcg_out_insn(s, RIL, AFI, a0, a2);
21763704993fSRichard Henderson                break;
21773704993fSRichard Henderson            }
21783704993fSRichard Henderson            tcg_out_mem(s, RX_LA, RXY_LAY, a0, a1, TCG_REG_NONE, a2);
21793704993fSRichard Henderson        } else if (a0 == a1) {
21803704993fSRichard Henderson            tcg_out_insn(s, RR, AR, a0, a2);
21813704993fSRichard Henderson        } else {
21823704993fSRichard Henderson            tcg_out_insn(s, RX, LA, a0, a1, a2, 0);
21833704993fSRichard Henderson        }
21843704993fSRichard Henderson        break;
21853704993fSRichard Henderson    case INDEX_op_sub_i32:
21863704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
21873704993fSRichard Henderson        if (const_args[2]) {
21881dd06b1aSRichard Henderson            a2 = -a2;
21893704993fSRichard Henderson            goto do_addi_32;
21903704993fSRichard Henderson        } else if (a0 == a1) {
21913704993fSRichard Henderson            tcg_out_insn(s, RR, SR, a0, a2);
21923704993fSRichard Henderson        } else {
21933704993fSRichard Henderson            tcg_out_insn(s, RRFa, SRK, a0, a1, a2);
21943704993fSRichard Henderson        }
21953704993fSRichard Henderson        break;
21963704993fSRichard Henderson
21973704993fSRichard Henderson    case INDEX_op_and_i32:
21983704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (uint32_t)args[2];
21993704993fSRichard Henderson        if (const_args[2]) {
22001dd06b1aSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
22013704993fSRichard Henderson            tgen_andi(s, TCG_TYPE_I32, a0, a2);
22023704993fSRichard Henderson        } else if (a0 == a1) {
22033704993fSRichard Henderson            tcg_out_insn(s, RR, NR, a0, a2);
22043704993fSRichard Henderson        } else {
22053704993fSRichard Henderson            tcg_out_insn(s, RRFa, NRK, a0, a1, a2);
22063704993fSRichard Henderson        }
2207b2509accSRichard Henderson        break;
22083704993fSRichard Henderson    case INDEX_op_or_i32:
22093704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (uint32_t)args[2];
22103704993fSRichard Henderson        if (const_args[2]) {
22111dd06b1aSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
22123704993fSRichard Henderson            tgen_ori(s, a0, a2);
22133704993fSRichard Henderson        } else if (a0 == a1) {
22143704993fSRichard Henderson            tcg_out_insn(s, RR, OR, a0, a2);
22153704993fSRichard Henderson        } else {
22163704993fSRichard Henderson            tcg_out_insn(s, RRFa, ORK, a0, a1, a2);
22173704993fSRichard Henderson        }
2218a0332acaSRichard Henderson        break;
22193704993fSRichard Henderson    case INDEX_op_xor_i32:
22203704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (uint32_t)args[2];
22213704993fSRichard Henderson        if (const_args[2]) {
22221dd06b1aSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
22233704993fSRichard Henderson            tcg_out_insn(s, RIL, XILF, a0, a2);
22243704993fSRichard Henderson        } else if (a0 == a1) {
22253704993fSRichard Henderson            tcg_out_insn(s, RR, XR, args[0], args[2]);
22266c9b5c0fSRichard Henderson        } else {
22276c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, XRK, a0, a1, a2);
22286c9b5c0fSRichard Henderson        }
22296c9b5c0fSRichard Henderson        break;
22306c9b5c0fSRichard Henderson
22316c9b5c0fSRichard Henderson    case INDEX_op_andc_i32:
22326c9b5c0fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (uint32_t)args[2];
22336c9b5c0fSRichard Henderson        if (const_args[2]) {
22346c9b5c0fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
22356c9b5c0fSRichard Henderson            tgen_andi(s, TCG_TYPE_I32, a0, (uint32_t)~a2);
22366c9b5c0fSRichard Henderson	} else {
22376c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, NCRK, a0, a1, a2);
22386c9b5c0fSRichard Henderson	}
22396c9b5c0fSRichard Henderson        break;
22406c9b5c0fSRichard Henderson    case INDEX_op_orc_i32:
22416c9b5c0fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (uint32_t)args[2];
22426c9b5c0fSRichard Henderson        if (const_args[2]) {
22436c9b5c0fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
22446c9b5c0fSRichard Henderson            tgen_ori(s, a0, (uint32_t)~a2);
22456c9b5c0fSRichard Henderson        } else {
22466c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, OCRK, a0, a1, a2);
22476c9b5c0fSRichard Henderson        }
22486c9b5c0fSRichard Henderson        break;
22496c9b5c0fSRichard Henderson    case INDEX_op_eqv_i32:
22506c9b5c0fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (uint32_t)args[2];
22516c9b5c0fSRichard Henderson        if (const_args[2]) {
22526c9b5c0fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
22536c9b5c0fSRichard Henderson            tcg_out_insn(s, RIL, XILF, a0, ~a2);
22546c9b5c0fSRichard Henderson        } else {
22556c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, NXRK, a0, a1, a2);
22566c9b5c0fSRichard Henderson        }
22576c9b5c0fSRichard Henderson        break;
22586c9b5c0fSRichard Henderson    case INDEX_op_nand_i32:
22596c9b5c0fSRichard Henderson        tcg_out_insn(s, RRFa, NNRK, args[0], args[1], args[2]);
22603704993fSRichard Henderson        break;
22613704993fSRichard Henderson    case INDEX_op_nor_i32:
22623704993fSRichard Henderson        tcg_out_insn(s, RRFa, NORK, args[0], args[1], args[2]);
22636c9b5c0fSRichard Henderson        break;
22646c9b5c0fSRichard Henderson
22656c9b5c0fSRichard Henderson    case INDEX_op_neg_i32:
22663704993fSRichard Henderson        tcg_out_insn(s, RR, LCR, args[0], args[1]);
22673704993fSRichard Henderson        break;
226892c89a07SRichard Henderson    case INDEX_op_not_i32:
22693704993fSRichard Henderson        tcg_out_insn(s, RRFa, NORK, args[0], args[1], args[1]);
227092c89a07SRichard Henderson        break;
227192c89a07SRichard Henderson
227292c89a07SRichard Henderson    case INDEX_op_mul_i32:
22733704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
227492c89a07SRichard Henderson        if (const_args[2]) {
22753704993fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I32, a0, a1);
227692c89a07SRichard Henderson            if (a2 == (int16_t)a2) {
227792c89a07SRichard Henderson                tcg_out_insn(s, RI, MHI, a0, a2);
22783704993fSRichard Henderson            } else {
227992c89a07SRichard Henderson                tcg_out_insn(s, RIL, MSFI, a0, a2);
22803704993fSRichard Henderson            }
22813704993fSRichard Henderson        } else if (a0 == a1) {
22823704993fSRichard Henderson            tcg_out_insn(s, RRE, MSR, a0, a2);
22833704993fSRichard Henderson        } else {
22844143f78dSRichard Henderson            tcg_out_insn(s, RRFa, MSRKC, a0, a1, a2);
22854143f78dSRichard Henderson        }
22864143f78dSRichard Henderson        break;
22874143f78dSRichard Henderson
22884143f78dSRichard Henderson    case INDEX_op_div2_i32:
22893704993fSRichard Henderson        tcg_debug_assert(args[0] == args[2]);
22903704993fSRichard Henderson        tcg_debug_assert(args[1] == args[3]);
22914143f78dSRichard Henderson        tcg_debug_assert((args[1] & 1) == 0);
22924143f78dSRichard Henderson        tcg_debug_assert(args[0] == args[1] + 1);
22934143f78dSRichard Henderson        tcg_out_insn(s, RR, DR, args[1], args[4]);
22944143f78dSRichard Henderson        break;
22954143f78dSRichard Henderson    case INDEX_op_divu2_i32:
22963704993fSRichard Henderson        tcg_debug_assert(args[0] == args[2]);
22973704993fSRichard Henderson        tcg_debug_assert(args[1] == args[3]);
22983704993fSRichard Henderson        tcg_debug_assert((args[1] & 1) == 0);
22993704993fSRichard Henderson        tcg_debug_assert(args[0] == args[1] + 1);
23003704993fSRichard Henderson        tcg_out_insn(s, RRE, DLR, args[1], args[4]);
23013704993fSRichard Henderson        break;
23023704993fSRichard Henderson
23033704993fSRichard Henderson    case INDEX_op_shl_i32:
23043704993fSRichard Henderson        op = RS_SLL;
23053704993fSRichard Henderson        op2 = RSY_SLLK;
23063704993fSRichard Henderson    do_shift32:
23073704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = (int32_t)args[2];
23083704993fSRichard Henderson        if (a0 == a1) {
23093704993fSRichard Henderson            if (const_args[2]) {
23103704993fSRichard Henderson                tcg_out_sh32(s, op, a0, TCG_REG_NONE, a2);
23113704993fSRichard Henderson            } else {
23123704993fSRichard Henderson                tcg_out_sh32(s, op, a0, a2, 0);
23133704993fSRichard Henderson            }
23143704993fSRichard Henderson        } else {
23153704993fSRichard Henderson            /* Using tcg_out_sh64 here for the format; it is a 32-bit shift.  */
23163704993fSRichard Henderson            if (const_args[2]) {
23173704993fSRichard Henderson                tcg_out_sh64(s, op2, a0, a1, TCG_REG_NONE, a2);
23183704993fSRichard Henderson            } else {
23193704993fSRichard Henderson                tcg_out_sh64(s, op2, a0, a1, a2, 0);
23203704993fSRichard Henderson            }
23213704993fSRichard Henderson        }
23223704993fSRichard Henderson        break;
23233704993fSRichard Henderson    case INDEX_op_shr_i32:
23243704993fSRichard Henderson        op = RS_SRL;
23253704993fSRichard Henderson        op2 = RSY_SRLK;
23263704993fSRichard Henderson        goto do_shift32;
23273704993fSRichard Henderson    case INDEX_op_sar_i32:
23283704993fSRichard Henderson        op = RS_SRA;
23293704993fSRichard Henderson        op2 = RSY_SRAK;
23303704993fSRichard Henderson        goto do_shift32;
23313704993fSRichard Henderson
23323704993fSRichard Henderson    case INDEX_op_rotl_i32:
23333704993fSRichard Henderson        /* ??? Using tcg_out_sh64 here for the format; it is a 32-bit rol.  */
23343704993fSRichard Henderson        if (const_args[2]) {
23353704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_REG_NONE, args[2]);
23363704993fSRichard Henderson        } else {
23373704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLL, args[0], args[1], args[2], 0);
23383704993fSRichard Henderson        }
23393704993fSRichard Henderson        break;
23403704993fSRichard Henderson    case INDEX_op_rotr_i32:
23413704993fSRichard Henderson        if (const_args[2]) {
23423704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLL, args[0], args[1],
23433704993fSRichard Henderson                         TCG_REG_NONE, (32 - args[2]) & 31);
23443704993fSRichard Henderson        } else {
23453704993fSRichard Henderson            tcg_out_insn(s, RR, LCR, TCG_TMP0, args[2]);
23463704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_TMP0, 0);
23473704993fSRichard Henderson        }
23483704993fSRichard Henderson        break;
23493704993fSRichard Henderson
23503704993fSRichard Henderson    case INDEX_op_bswap16_i32:
23513704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
23523704993fSRichard Henderson        tcg_out_insn(s, RRE, LRVR, a0, a1);
23533704993fSRichard Henderson        if (a2 & TCG_BSWAP_OS) {
23543704993fSRichard Henderson            tcg_out_sh32(s, RS_SRA, a0, TCG_REG_NONE, 16);
23553704993fSRichard Henderson        } else {
23563704993fSRichard Henderson            tcg_out_sh32(s, RS_SRL, a0, TCG_REG_NONE, 16);
23573704993fSRichard Henderson        }
23583704993fSRichard Henderson        break;
23593704993fSRichard Henderson    case INDEX_op_bswap16_i64:
23603704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
23613704993fSRichard Henderson        tcg_out_insn(s, RRE, LRVGR, a0, a1);
23623704993fSRichard Henderson        if (a2 & TCG_BSWAP_OS) {
23633704993fSRichard Henderson            tcg_out_sh64(s, RSY_SRAG, a0, a0, TCG_REG_NONE, 48);
23643704993fSRichard Henderson        } else {
23653704993fSRichard Henderson            tcg_out_sh64(s, RSY_SRLG, a0, a0, TCG_REG_NONE, 48);
23663704993fSRichard Henderson        }
23673704993fSRichard Henderson        break;
23683704993fSRichard Henderson
23693704993fSRichard Henderson    case INDEX_op_bswap32_i32:
23703704993fSRichard Henderson        tcg_out_insn(s, RRE, LRVR, args[0], args[1]);
237152bf3398SRichard Henderson        break;
23723704993fSRichard Henderson    case INDEX_op_bswap32_i64:
23739ecf5f61SRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
23743704993fSRichard Henderson        tcg_out_insn(s, RRE, LRVR, a0, a1);
23753704993fSRichard Henderson        if (a2 & TCG_BSWAP_OS) {
23763704993fSRichard Henderson            tcg_out_ext32s(s, a0, a0);
23773704993fSRichard Henderson        } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
23783704993fSRichard Henderson            tcg_out_ext32u(s, a0, a0);
23793704993fSRichard Henderson        }
23803704993fSRichard Henderson        break;
23813704993fSRichard Henderson
23823704993fSRichard Henderson    case INDEX_op_add2_i32:
23833704993fSRichard Henderson        if (const_args[4]) {
23843704993fSRichard Henderson            tcg_out_insn(s, RIL, ALFI, args[0], args[4]);
23853704993fSRichard Henderson        } else {
23863704993fSRichard Henderson            tcg_out_insn(s, RR, ALR, args[0], args[4]);
23873704993fSRichard Henderson        }
23883704993fSRichard Henderson        tcg_out_insn(s, RRE, ALCR, args[1], args[5]);
23893704993fSRichard Henderson        break;
23903704993fSRichard Henderson    case INDEX_op_sub2_i32:
23913704993fSRichard Henderson        if (const_args[4]) {
23923704993fSRichard Henderson            tcg_out_insn(s, RIL, SLFI, args[0], args[4]);
23933704993fSRichard Henderson        } else {
23943704993fSRichard Henderson            tcg_out_insn(s, RR, SLR, args[0], args[4]);
23953704993fSRichard Henderson        }
23963704993fSRichard Henderson        tcg_out_insn(s, RRE, SLBR, args[1], args[5]);
23973704993fSRichard Henderson        break;
23983704993fSRichard Henderson
23993704993fSRichard Henderson    case INDEX_op_br:
24003704993fSRichard Henderson        tgen_branch(s, S390_CC_ALWAYS, arg_label(args[0]));
24013704993fSRichard Henderson        break;
24023704993fSRichard Henderson
24033704993fSRichard Henderson    case INDEX_op_brcond_i32:
2404128c7d51SRichard Henderson        tgen_brcond(s, TCG_TYPE_I32, args[2], args[0],
2405128c7d51SRichard Henderson                    args[1], const_args[1], arg_label(args[3]));
2406128c7d51SRichard Henderson        break;
2407128c7d51SRichard Henderson    case INDEX_op_setcond_i32:
2408128c7d51SRichard Henderson        tgen_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1],
24093704993fSRichard Henderson                     args[2], const_args[2], false);
24103704993fSRichard Henderson        break;
24113704993fSRichard Henderson    case INDEX_op_negsetcond_i32:
241223d1394aSRichard Henderson        tgen_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1],
24133704993fSRichard Henderson                     args[2], const_args[2], true);
24143704993fSRichard Henderson        break;
2415fecccfccSRichard Henderson    case INDEX_op_movcond_i32:
2416fecccfccSRichard Henderson        tgen_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1],
241701a3b5deSRichard Henderson                     args[2], const_args[2], args[3], const_args[3], args[4]);
241801a3b5deSRichard Henderson        break;
2419fecccfccSRichard Henderson
2420fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
242101a3b5deSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
24223704993fSRichard Henderson        tcg_out_qemu_ld(s, args[0], args[1], args[2], TCG_TYPE_I32);
2423fecccfccSRichard Henderson        break;
2424fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
242501a3b5deSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
242601a3b5deSRichard Henderson        tcg_out_qemu_ld(s, args[0], args[1], args[2], TCG_TYPE_I64);
2427fecccfccSRichard Henderson        break;
2428fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
242901a3b5deSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
24303704993fSRichard Henderson        tcg_out_qemu_st(s, args[0], args[1], args[2], TCG_TYPE_I32);
24314caad79fSRichard Henderson        break;
24324caad79fSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
24334caad79fSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
24344caad79fSRichard Henderson        tcg_out_qemu_st(s, args[0], args[1], args[2], TCG_TYPE_I64);
24354caad79fSRichard Henderson        break;
24364caad79fSRichard Henderson    case INDEX_op_qemu_ld_a32_i128:
24374caad79fSRichard Henderson    case INDEX_op_qemu_ld_a64_i128:
24384caad79fSRichard Henderson        tcg_out_qemu_ldst_i128(s, args[0], args[1], args[2], args[3], true);
24393704993fSRichard Henderson        break;
24403704993fSRichard Henderson    case INDEX_op_qemu_st_a32_i128:
24413704993fSRichard Henderson    case INDEX_op_qemu_st_a64_i128:
24423704993fSRichard Henderson        tcg_out_qemu_ldst_i128(s, args[0], args[1], args[2], args[3], false);
24433704993fSRichard Henderson        break;
24443704993fSRichard Henderson
24453704993fSRichard Henderson    case INDEX_op_ld16s_i64:
24463704993fSRichard Henderson        tcg_out_mem(s, 0, RXY_LGH, args[0], args[1], TCG_REG_NONE, args[2]);
24473704993fSRichard Henderson        break;
24483704993fSRichard Henderson    case INDEX_op_ld32u_i64:
24493704993fSRichard Henderson        tcg_out_mem(s, 0, RXY_LLGF, args[0], args[1], TCG_REG_NONE, args[2]);
24503704993fSRichard Henderson        break;
24513704993fSRichard Henderson    case INDEX_op_ld32s_i64:
24523704993fSRichard Henderson        tcg_out_mem(s, 0, RXY_LGF, args[0], args[1], TCG_REG_NONE, args[2]);
24533704993fSRichard Henderson        break;
24543704993fSRichard Henderson    case INDEX_op_ld_i64:
24553704993fSRichard Henderson        tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
24563704993fSRichard Henderson        break;
24573704993fSRichard Henderson
24583704993fSRichard Henderson    case INDEX_op_st32_i64:
24593704993fSRichard Henderson        tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
24603704993fSRichard Henderson        break;
24613704993fSRichard Henderson    case INDEX_op_st_i64:
24623704993fSRichard Henderson        tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
24633704993fSRichard Henderson        break;
24643704993fSRichard Henderson
24653704993fSRichard Henderson    case INDEX_op_add_i64:
24663704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
24673704993fSRichard Henderson        if (const_args[2]) {
24683704993fSRichard Henderson        do_addi_64:
24693704993fSRichard Henderson            if (a0 == a1) {
24703704993fSRichard Henderson                if (a2 == (int16_t)a2) {
24713704993fSRichard Henderson                    tcg_out_insn(s, RI, AGHI, a0, a2);
24723e25f7daSRichard Henderson                    break;
24733e25f7daSRichard Henderson                }
24743704993fSRichard Henderson                if (a2 == (int32_t)a2) {
24753704993fSRichard Henderson                    tcg_out_insn(s, RIL, AGFI, a0, a2);
24763e25f7daSRichard Henderson                    break;
24773e25f7daSRichard Henderson                }
24783704993fSRichard Henderson                if (a2 == (uint32_t)a2) {
24793704993fSRichard Henderson                    tcg_out_insn(s, RIL, ALGFI, a0, a2);
24803704993fSRichard Henderson                    break;
24813704993fSRichard Henderson                }
24823704993fSRichard Henderson                if (-a2 == (uint32_t)-a2) {
24833704993fSRichard Henderson                    tcg_out_insn(s, RIL, SLGFI, a0, -a2);
24843704993fSRichard Henderson                    break;
24853704993fSRichard Henderson                }
24863704993fSRichard Henderson            }
24873704993fSRichard Henderson            tcg_out_mem(s, RX_LA, RXY_LAY, a0, a1, TCG_REG_NONE, a2);
24883704993fSRichard Henderson        } else if (a0 == a1) {
24893704993fSRichard Henderson            tcg_out_insn(s, RRE, AGR, a0, a2);
24903704993fSRichard Henderson        } else {
24913704993fSRichard Henderson            tcg_out_insn(s, RX, LA, a0, a1, a2, 0);
24923704993fSRichard Henderson        }
24933704993fSRichard Henderson        break;
24943704993fSRichard Henderson    case INDEX_op_sub_i64:
24951dd06b1aSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
24963704993fSRichard Henderson        if (const_args[2]) {
24973704993fSRichard Henderson            a2 = -a2;
24983704993fSRichard Henderson            goto do_addi_64;
24993704993fSRichard Henderson        } else {
25003704993fSRichard Henderson            tcg_out_insn(s, RRFa, SGRK, a0, a1, a2);
25013704993fSRichard Henderson        }
25023704993fSRichard Henderson        break;
25033704993fSRichard Henderson
25043704993fSRichard Henderson    case INDEX_op_and_i64:
25051dd06b1aSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
25063704993fSRichard Henderson        if (const_args[2]) {
25073704993fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I64, a0, a1);
25083704993fSRichard Henderson            tgen_andi(s, TCG_TYPE_I64, args[0], args[2]);
25093704993fSRichard Henderson        } else {
25103704993fSRichard Henderson            tcg_out_insn(s, RRFa, NGRK, a0, a1, a2);
25113704993fSRichard Henderson        }
2512b2509accSRichard Henderson        break;
25133704993fSRichard Henderson    case INDEX_op_or_i64:
25141dd06b1aSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
25153704993fSRichard Henderson        if (const_args[2]) {
25163704993fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I64, a0, a1);
25173704993fSRichard Henderson            tgen_ori(s, a0, a2);
25183704993fSRichard Henderson        } else {
25193704993fSRichard Henderson            tcg_out_insn(s, RRFa, OGRK, a0, a1, a2);
25203704993fSRichard Henderson        }
2521b2509accSRichard Henderson        break;
25223704993fSRichard Henderson    case INDEX_op_xor_i64:
25231dd06b1aSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
25243704993fSRichard Henderson        if (const_args[2]) {
25253704993fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I64, a0, a1);
25263704993fSRichard Henderson            tgen_xori(s, a0, a2);
25276c9b5c0fSRichard Henderson        } else {
25286c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, XGRK, a0, a1, a2);
25296c9b5c0fSRichard Henderson        }
25306c9b5c0fSRichard Henderson        break;
25316c9b5c0fSRichard Henderson
25326c9b5c0fSRichard Henderson    case INDEX_op_andc_i64:
25336c9b5c0fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
25346c9b5c0fSRichard Henderson        if (const_args[2]) {
25356c9b5c0fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I64, a0, a1);
25366c9b5c0fSRichard Henderson            tgen_andi(s, TCG_TYPE_I64, a0, ~a2);
25376c9b5c0fSRichard Henderson        } else {
25386c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, NCGRK, a0, a1, a2);
25396c9b5c0fSRichard Henderson        }
25406c9b5c0fSRichard Henderson        break;
25416c9b5c0fSRichard Henderson    case INDEX_op_orc_i64:
25426c9b5c0fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
25436c9b5c0fSRichard Henderson        if (const_args[2]) {
25446c9b5c0fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I64, a0, a1);
25456c9b5c0fSRichard Henderson            tgen_ori(s, a0, ~a2);
25466c9b5c0fSRichard Henderson        } else {
25476c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, OCGRK, a0, a1, a2);
25486c9b5c0fSRichard Henderson        }
25496c9b5c0fSRichard Henderson        break;
25506c9b5c0fSRichard Henderson    case INDEX_op_eqv_i64:
25516c9b5c0fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
25526c9b5c0fSRichard Henderson        if (const_args[2]) {
25536c9b5c0fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I64, a0, a1);
25546c9b5c0fSRichard Henderson            tgen_xori(s, a0, ~a2);
25556c9b5c0fSRichard Henderson        } else {
25566c9b5c0fSRichard Henderson            tcg_out_insn(s, RRFa, NXGRK, a0, a1, a2);
25576c9b5c0fSRichard Henderson        }
25586c9b5c0fSRichard Henderson        break;
25596c9b5c0fSRichard Henderson    case INDEX_op_nand_i64:
25606c9b5c0fSRichard Henderson        tcg_out_insn(s, RRFa, NNGRK, args[0], args[1], args[2]);
25613704993fSRichard Henderson        break;
25623704993fSRichard Henderson    case INDEX_op_nor_i64:
25633704993fSRichard Henderson        tcg_out_insn(s, RRFa, NOGRK, args[0], args[1], args[2]);
25646c9b5c0fSRichard Henderson        break;
25656c9b5c0fSRichard Henderson
25666c9b5c0fSRichard Henderson    case INDEX_op_neg_i64:
25673704993fSRichard Henderson        tcg_out_insn(s, RRE, LCGR, args[0], args[1]);
25683704993fSRichard Henderson        break;
25693704993fSRichard Henderson    case INDEX_op_not_i64:
25703704993fSRichard Henderson        tcg_out_insn(s, RRFa, NOGRK, args[0], args[1], args[1]);
25713704993fSRichard Henderson        break;
257292c89a07SRichard Henderson    case INDEX_op_bswap64_i64:
25733704993fSRichard Henderson        tcg_out_insn(s, RRE, LRVGR, args[0], args[1]);
257492c89a07SRichard Henderson        break;
257592c89a07SRichard Henderson
257692c89a07SRichard Henderson    case INDEX_op_mul_i64:
25773704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
257892c89a07SRichard Henderson        if (const_args[2]) {
25793704993fSRichard Henderson            tcg_out_mov(s, TCG_TYPE_I64, a0, a1);
258092c89a07SRichard Henderson            if (a2 == (int16_t)a2) {
258192c89a07SRichard Henderson                tcg_out_insn(s, RI, MGHI, a0, a2);
25823704993fSRichard Henderson            } else {
258392c89a07SRichard Henderson                tcg_out_insn(s, RIL, MSGFI, a0, a2);
25843704993fSRichard Henderson            }
25853704993fSRichard Henderson        } else if (a0 == a1) {
25863704993fSRichard Henderson            tcg_out_insn(s, RRE, MSGR, a0, a2);
25873704993fSRichard Henderson        } else {
25884143f78dSRichard Henderson            tcg_out_insn(s, RRFa, MSGRKC, a0, a1, a2);
25894143f78dSRichard Henderson        }
25904143f78dSRichard Henderson        break;
25914143f78dSRichard Henderson
25924143f78dSRichard Henderson    case INDEX_op_div2_i64:
25934143f78dSRichard Henderson        /*
25944143f78dSRichard Henderson         * ??? We get an unnecessary sign-extension of the dividend
25954143f78dSRichard Henderson         * into op0 with this definition, but as we do in fact always
25964143f78dSRichard Henderson         * produce both quotient and remainder using INDEX_op_div_i64
25974143f78dSRichard Henderson         * instead requires jumping through even more hoops.
25984143f78dSRichard Henderson         */
25993704993fSRichard Henderson        tcg_debug_assert(args[0] == args[2]);
26003704993fSRichard Henderson        tcg_debug_assert(args[1] == args[3]);
26014143f78dSRichard Henderson        tcg_debug_assert((args[1] & 1) == 0);
26024143f78dSRichard Henderson        tcg_debug_assert(args[0] == args[1] + 1);
26034143f78dSRichard Henderson        tcg_out_insn(s, RRE, DSGR, args[1], args[4]);
26044143f78dSRichard Henderson        break;
26054143f78dSRichard Henderson    case INDEX_op_divu2_i64:
26063704993fSRichard Henderson        tcg_debug_assert(args[0] == args[2]);
26073704993fSRichard Henderson        tcg_debug_assert(args[1] == args[3]);
26084143f78dSRichard Henderson        tcg_debug_assert((args[1] & 1) == 0);
26094143f78dSRichard Henderson        tcg_debug_assert(args[0] == args[1] + 1);
26104143f78dSRichard Henderson        tcg_out_insn(s, RRE, DLGR, args[1], args[4]);
26114143f78dSRichard Henderson        break;
26123704993fSRichard Henderson    case INDEX_op_mulu2_i64:
2613668ce343SRichard Henderson        tcg_debug_assert(args[0] == args[2]);
2614668ce343SRichard Henderson        tcg_debug_assert((args[1] & 1) == 0);
2615668ce343SRichard Henderson        tcg_debug_assert(args[0] == args[1] + 1);
2616668ce343SRichard Henderson        tcg_out_insn(s, RRE, MLGR, args[1], args[3]);
2617668ce343SRichard Henderson        break;
26183704993fSRichard Henderson    case INDEX_op_muls2_i64:
26193704993fSRichard Henderson        tcg_debug_assert((args[1] & 1) == 0);
26203704993fSRichard Henderson        tcg_debug_assert(args[0] == args[1] + 1);
26213704993fSRichard Henderson        tcg_out_insn(s, RRFa, MGRK, args[1], args[2], args[3]);
26223704993fSRichard Henderson        break;
26233704993fSRichard Henderson
26243704993fSRichard Henderson    case INDEX_op_shl_i64:
26253704993fSRichard Henderson        op = RSY_SLLG;
26263704993fSRichard Henderson    do_shift64:
26273704993fSRichard Henderson        if (const_args[2]) {
26283704993fSRichard Henderson            tcg_out_sh64(s, op, args[0], args[1], TCG_REG_NONE, args[2]);
26293704993fSRichard Henderson        } else {
26303704993fSRichard Henderson            tcg_out_sh64(s, op, args[0], args[1], args[2], 0);
26313704993fSRichard Henderson        }
26323704993fSRichard Henderson        break;
26333704993fSRichard Henderson    case INDEX_op_shr_i64:
26343704993fSRichard Henderson        op = RSY_SRLG;
26353704993fSRichard Henderson        goto do_shift64;
26363704993fSRichard Henderson    case INDEX_op_sar_i64:
26373704993fSRichard Henderson        op = RSY_SRAG;
26383704993fSRichard Henderson        goto do_shift64;
26393704993fSRichard Henderson
26403704993fSRichard Henderson    case INDEX_op_rotl_i64:
26413704993fSRichard Henderson        if (const_args[2]) {
26423704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
26433704993fSRichard Henderson                         TCG_REG_NONE, args[2]);
26443704993fSRichard Henderson        } else {
26453704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLLG, args[0], args[1], args[2], 0);
26463704993fSRichard Henderson        }
26473704993fSRichard Henderson        break;
26483704993fSRichard Henderson    case INDEX_op_rotr_i64:
26493704993fSRichard Henderson        if (const_args[2]) {
26503704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
26513704993fSRichard Henderson                         TCG_REG_NONE, (64 - args[2]) & 63);
26523704993fSRichard Henderson        } else {
26533704993fSRichard Henderson            /* We can use the smaller 32-bit negate because only the
26543704993fSRichard Henderson               low 6 bits are examined for the rotate.  */
26553704993fSRichard Henderson            tcg_out_insn(s, RR, LCR, TCG_TMP0, args[2]);
26563704993fSRichard Henderson            tcg_out_sh64(s, RSY_RLLG, args[0], args[1], TCG_TMP0, 0);
26573704993fSRichard Henderson        }
26583704993fSRichard Henderson        break;
26593704993fSRichard Henderson
26603704993fSRichard Henderson    case INDEX_op_add2_i64:
26613704993fSRichard Henderson        if (const_args[4]) {
26623704993fSRichard Henderson            if ((int64_t)args[4] >= 0) {
26633704993fSRichard Henderson                tcg_out_insn(s, RIL, ALGFI, args[0], args[4]);
26643704993fSRichard Henderson            } else {
26653704993fSRichard Henderson                tcg_out_insn(s, RIL, SLGFI, args[0], -args[4]);
26663704993fSRichard Henderson            }
26673704993fSRichard Henderson        } else {
26683704993fSRichard Henderson            tcg_out_insn(s, RRE, ALGR, args[0], args[4]);
26693704993fSRichard Henderson        }
26703704993fSRichard Henderson        tcg_out_insn(s, RRE, ALCGR, args[1], args[5]);
26713704993fSRichard Henderson        break;
26723704993fSRichard Henderson    case INDEX_op_sub2_i64:
26733704993fSRichard Henderson        if (const_args[4]) {
26743704993fSRichard Henderson            if ((int64_t)args[4] >= 0) {
26753704993fSRichard Henderson                tcg_out_insn(s, RIL, SLGFI, args[0], args[4]);
26763704993fSRichard Henderson            } else {
26773704993fSRichard Henderson                tcg_out_insn(s, RIL, ALGFI, args[0], -args[4]);
26783704993fSRichard Henderson            }
26793704993fSRichard Henderson        } else {
26803704993fSRichard Henderson            tcg_out_insn(s, RRE, SLGR, args[0], args[4]);
26813704993fSRichard Henderson        }
26823704993fSRichard Henderson        tcg_out_insn(s, RRE, SLBGR, args[1], args[5]);
26833704993fSRichard Henderson        break;
26843704993fSRichard Henderson
26853704993fSRichard Henderson    case INDEX_op_brcond_i64:
2686128c7d51SRichard Henderson        tgen_brcond(s, TCG_TYPE_I64, args[2], args[0],
2687128c7d51SRichard Henderson                    args[1], const_args[1], arg_label(args[3]));
2688128c7d51SRichard Henderson        break;
2689128c7d51SRichard Henderson    case INDEX_op_setcond_i64:
2690128c7d51SRichard Henderson        tgen_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1],
26913704993fSRichard Henderson                     args[2], const_args[2], false);
26923704993fSRichard Henderson        break;
26933704993fSRichard Henderson    case INDEX_op_negsetcond_i64:
269423d1394aSRichard Henderson        tgen_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1],
26953704993fSRichard Henderson                     args[2], const_args[2], true);
26963704993fSRichard Henderson        break;
26973704993fSRichard Henderson    case INDEX_op_movcond_i64:
26983704993fSRichard Henderson        tgen_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1],
26993704993fSRichard Henderson                     args[2], const_args[2], args[3], const_args[3], args[4]);
27003704993fSRichard Henderson        break;
27013704993fSRichard Henderson
27023704993fSRichard Henderson    OP_32_64(deposit):
27033704993fSRichard Henderson        a0 = args[0], a1 = args[1], a2 = args[2];
27043704993fSRichard Henderson        if (const_args[1]) {
27053704993fSRichard Henderson            tgen_deposit(s, a0, a2, args[3], args[4], 1);
27063704993fSRichard Henderson        } else {
27073704993fSRichard Henderson            /* Since we can't support "0Z" as a constraint, we allow a1 in
27083704993fSRichard Henderson               any register.  Fix things up as if a matching constraint.  */
27093704993fSRichard Henderson            if (a0 != a1) {
27103704993fSRichard Henderson                TCGType type = (opc == INDEX_op_deposit_i64);
27113704993fSRichard Henderson                if (a0 == a2) {
27123704993fSRichard Henderson                    tcg_out_mov(s, type, TCG_TMP0, a2);
27133704993fSRichard Henderson                    a2 = TCG_TMP0;
27143704993fSRichard Henderson                }
27153704993fSRichard Henderson                tcg_out_mov(s, type, a0, a1);
27163704993fSRichard Henderson            }
27173704993fSRichard Henderson            tgen_deposit(s, a0, a2, args[3], args[4], 0);
27183704993fSRichard Henderson        }
27193704993fSRichard Henderson        break;
27203704993fSRichard Henderson
27213704993fSRichard Henderson    OP_32_64(extract):
27223704993fSRichard Henderson        tgen_extract(s, args[0], args[1], args[2], args[3]);
27233704993fSRichard Henderson        break;
272429a5ea73SRichard Henderson
272529a5ea73SRichard Henderson    case INDEX_op_clz_i64:
272629a5ea73SRichard Henderson        tgen_clz(s, args[0], args[1], args[2], const_args[2]);
272729a5ea73SRichard Henderson        break;
272829a5ea73SRichard Henderson
272929a5ea73SRichard Henderson    case INDEX_op_ctpop_i32:
273029a5ea73SRichard Henderson        tgen_ctpop(s, TCG_TYPE_I32, args[0], args[1]);
27313704993fSRichard Henderson        break;
27323704993fSRichard Henderson    case INDEX_op_ctpop_i64:
27333704993fSRichard Henderson        tgen_ctpop(s, TCG_TYPE_I64, args[0], args[1]);
27343704993fSRichard Henderson        break;
2735e62d5752SRichard Henderson
2736e62d5752SRichard Henderson    case INDEX_op_mb:
27373704993fSRichard Henderson        /* The host memory model is quite strong, we simply need to
27383704993fSRichard Henderson           serialize the instruction stream.  */
27393704993fSRichard Henderson        if (args[0] & TCG_MO_ST_LD) {
27403704993fSRichard Henderson            /* fast-bcr-serialization facility (45) is present */
27413704993fSRichard Henderson            tcg_out_insn(s, RR, BCR, 14, 0);
27423704993fSRichard Henderson        }
2743b55a8d9dSRichard Henderson        break;
2744cf7d6b8eSRichard Henderson
2745678155b2SRichard Henderson    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2746678155b2SRichard Henderson    case INDEX_op_mov_i64:
2747d0e66c89SRichard Henderson    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2748d0e66c89SRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2749753e42eaSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2750753e42eaSRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2751379afdffSRichard Henderson    case INDEX_op_ext8s_i64:
2752379afdffSRichard Henderson    case INDEX_op_ext8u_i32:
275352bf3398SRichard Henderson    case INDEX_op_ext8u_i64:
27549ecf5f61SRichard Henderson    case INDEX_op_ext16s_i32:
27559c6aa274SRichard Henderson    case INDEX_op_ext16s_i64:
2756b9bfe000SRichard Henderson    case INDEX_op_ext16u_i32:
2757b8b94ac6SRichard Henderson    case INDEX_op_ext16u_i64:
27583704993fSRichard Henderson    case INDEX_op_ext32s_i64:
2759732e89f4SRichard Henderson    case INDEX_op_ext32u_i64:
27603704993fSRichard Henderson    case INDEX_op_ext_i32_i64:
27613704993fSRichard Henderson    case INDEX_op_extu_i32_i64:
27623704993fSRichard Henderson    case INDEX_op_extrl_i64_i32:
276334ef7676SRichard Henderson    default:
276434ef7676SRichard Henderson        g_assert_not_reached();
276534ef7676SRichard Henderson    }
276679cada86SRichard Henderson}
276779cada86SRichard Henderson
276879cada86SRichard Hendersonstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
276979cada86SRichard Henderson                            TCGReg dst, TCGReg src)
277079cada86SRichard Henderson{
277179cada86SRichard Henderson    if (is_general_reg(src)) {
27726e591a85SRichard Henderson        /* Replicate general register into two MO_64. */
277379cada86SRichard Henderson        tcg_out_insn(s, VRRf, VLVGP, dst, src, src);
277479cada86SRichard Henderson        if (vece == MO_64) {
277579cada86SRichard Henderson            return true;
277679cada86SRichard Henderson        }
277779cada86SRichard Henderson        src = dst;
277879cada86SRichard Henderson    }
277979cada86SRichard Henderson
278079cada86SRichard Henderson    /*
278134ef7676SRichard Henderson     * Recall that the "standard" integer, within a vector, is the
278234ef7676SRichard Henderson     * rightmost element of the leftmost doubleword, a-la VLLEZ.
278334ef7676SRichard Henderson     */
278434ef7676SRichard Henderson    tcg_out_insn(s, VRIc, VREP, dst, (8 >> vece) - 1, src, vece);
278534ef7676SRichard Henderson    return true;
278679cada86SRichard Henderson}
278779cada86SRichard Henderson
278834ef7676SRichard Hendersonstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
278934ef7676SRichard Henderson                             TCGReg dst, TCGReg base, intptr_t offset)
279034ef7676SRichard Henderson{
279134ef7676SRichard Henderson    tcg_out_vrx_mem(s, VRX_VLREP, dst, base, TCG_REG_NONE, offset, vece);
279234ef7676SRichard Henderson    return true;
279379cada86SRichard Henderson}
279479cada86SRichard Henderson
279579cada86SRichard Hendersonstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
279679cada86SRichard Henderson                             TCGReg dst, int64_t val)
279779cada86SRichard Henderson{
279879cada86SRichard Henderson    int i, mask, msb, lsb;
279979cada86SRichard Henderson
280079cada86SRichard Henderson    /* Look for int16_t elements.  */
280179cada86SRichard Henderson    if (vece <= MO_16 ||
280279cada86SRichard Henderson        (vece == MO_32 ? (int32_t)val : val) == (int16_t)val) {
280379cada86SRichard Henderson        tcg_out_insn(s, VRIa, VREPI, dst, val, vece);
280479cada86SRichard Henderson        return;
280579cada86SRichard Henderson    }
280679cada86SRichard Henderson
280779cada86SRichard Henderson    /* Look for bit masks.  */
280879cada86SRichard Henderson    if (vece == MO_32) {
280979cada86SRichard Henderson        if (risbg_mask((int32_t)val)) {
281079cada86SRichard Henderson            /* Handle wraparound by swapping msb and lsb.  */
281179cada86SRichard Henderson            if ((val & 0x80000001u) == 0x80000001u) {
281279cada86SRichard Henderson                msb = 32 - ctz32(~val);
2813a66669c9SRichard Henderson                lsb = clz32(~val) - 1;
281479cada86SRichard Henderson            } else {
281579cada86SRichard Henderson                msb = clz32(val);
281679cada86SRichard Henderson                lsb = 31 - ctz32(val);
281779cada86SRichard Henderson            }
281879cada86SRichard Henderson            tcg_out_insn(s, VRIb, VGM, dst, msb, lsb, MO_32);
281979cada86SRichard Henderson            return;
282079cada86SRichard Henderson        }
282179cada86SRichard Henderson    } else {
282279cada86SRichard Henderson        if (risbg_mask(val)) {
282379cada86SRichard Henderson            /* Handle wraparound by swapping msb and lsb.  */
282479cada86SRichard Henderson            if ((val & 0x8000000000000001ull) == 0x8000000000000001ull) {
282579cada86SRichard Henderson                /* Handle wraparound by swapping msb and lsb.  */
282679cada86SRichard Henderson                msb = 64 - ctz64(~val);
2827a66669c9SRichard Henderson                lsb = clz64(~val) - 1;
282879cada86SRichard Henderson            } else {
282979cada86SRichard Henderson                msb = clz64(val);
283079cada86SRichard Henderson                lsb = 63 - ctz64(val);
283179cada86SRichard Henderson            }
283279cada86SRichard Henderson            tcg_out_insn(s, VRIb, VGM, dst, msb, lsb, MO_64);
283379cada86SRichard Henderson            return;
283479cada86SRichard Henderson        }
283579cada86SRichard Henderson    }
283679cada86SRichard Henderson
283779cada86SRichard Henderson    /* Look for all bytes 0x00 or 0xff.  */
283879cada86SRichard Henderson    for (i = mask = 0; i < 8; i++) {
283979cada86SRichard Henderson        uint8_t byte = val >> (i * 8);
284079cada86SRichard Henderson        if (byte == 0xff) {
284179cada86SRichard Henderson            mask |= 1 << i;
284279cada86SRichard Henderson        } else if (byte != 0) {
284379cada86SRichard Henderson            break;
284479cada86SRichard Henderson        }
284579cada86SRichard Henderson    }
284679cada86SRichard Henderson    if (i == 8) {
284779cada86SRichard Henderson        tcg_out_insn(s, VRIa, VGBM, dst, mask * 0x0101, 0);
284879cada86SRichard Henderson        return;
284979cada86SRichard Henderson    }
285034ef7676SRichard Henderson
285134ef7676SRichard Henderson    /* Otherwise, stuff it in the constant pool.  */
285234ef7676SRichard Henderson    tcg_out_insn(s, RIL, LARL, TCG_TMP0, 0);
285334ef7676SRichard Henderson    new_pool_label(s, val, R_390_PC32DBL, s->code_ptr - 2, 2);
2854d58f0173SMiroslav Rezanina    tcg_out_insn(s, VRX, VLREP, dst, TCG_TMP0, TCG_REG_NONE, 0, MO_64);
2855d58f0173SMiroslav Rezanina}
285634ef7676SRichard Henderson
2857a429ee29SRichard Hendersonstatic bool tcg_out_cmp_vec_noinv(TCGContext *s, unsigned vece, TCGReg a0,
2858a429ee29SRichard Henderson                                  TCGReg a1, TCGReg a2, TCGCond cond)
2859a429ee29SRichard Henderson{
2860a429ee29SRichard Henderson    bool need_swap = false, need_inv = false;
2861a429ee29SRichard Henderson
2862a429ee29SRichard Henderson    switch (cond) {
2863a429ee29SRichard Henderson    case TCG_COND_EQ:
2864a429ee29SRichard Henderson    case TCG_COND_GT:
2865a429ee29SRichard Henderson    case TCG_COND_GTU:
2866a429ee29SRichard Henderson        break;
2867a429ee29SRichard Henderson    case TCG_COND_NE:
2868a429ee29SRichard Henderson    case TCG_COND_LE:
2869a429ee29SRichard Henderson    case TCG_COND_LEU:
2870a429ee29SRichard Henderson        need_inv = true;
2871ae77bbe5SRichard Henderson        break;
2872ae77bbe5SRichard Henderson    case TCG_COND_LT:
2873ae77bbe5SRichard Henderson    case TCG_COND_LTU:
2874ae77bbe5SRichard Henderson        need_swap = true;
2875ae77bbe5SRichard Henderson        break;
2876ae77bbe5SRichard Henderson    case TCG_COND_GE:
2877ae77bbe5SRichard Henderson    case TCG_COND_GEU:
2878ae77bbe5SRichard Henderson        need_swap = need_inv = true;
2879ae77bbe5SRichard Henderson        break;
2880ae77bbe5SRichard Henderson    default:
2881a429ee29SRichard Henderson        g_assert_not_reached();
2882a429ee29SRichard Henderson    }
2883a429ee29SRichard Henderson
2884a429ee29SRichard Henderson    if (need_inv) {
2885a429ee29SRichard Henderson        cond = tcg_invert_cond(cond);
2886a429ee29SRichard Henderson    }
2887a429ee29SRichard Henderson    if (need_swap) {
2888a429ee29SRichard Henderson        TCGReg swap = a1;
2889a429ee29SRichard Henderson        a1 = a2;
2890ae77bbe5SRichard Henderson        a2 = swap;
2891ae77bbe5SRichard Henderson        cond = tcg_swap_cond(cond);
2892ae77bbe5SRichard Henderson    }
2893479b61cbSRichard Henderson
2894479b61cbSRichard Henderson    switch (cond) {
2895479b61cbSRichard Henderson    case TCG_COND_EQ:
2896a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VCEQ, a0, a1, a2, vece);
2897a429ee29SRichard Henderson        break;
2898a429ee29SRichard Henderson    case TCG_COND_GT:
2899ae77bbe5SRichard Henderson        tcg_out_insn(s, VRRc, VCH, a0, a1, a2, vece);
2900ae77bbe5SRichard Henderson        break;
2901ae77bbe5SRichard Henderson    case TCG_COND_GTU:
2902a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VCHL, a0, a1, a2, vece);
2903a429ee29SRichard Henderson        break;
2904a429ee29SRichard Henderson    default:
290521eab5bfSRichard Henderson        g_assert_not_reached();
290621eab5bfSRichard Henderson    }
290721eab5bfSRichard Henderson    return need_inv;
290821eab5bfSRichard Henderson}
290921eab5bfSRichard Henderson
291021eab5bfSRichard Hendersonstatic void tcg_out_cmp_vec(TCGContext *s, unsigned vece, TCGReg a0,
291121eab5bfSRichard Henderson                            TCGReg a1, TCGReg a2, TCGCond cond)
291221eab5bfSRichard Henderson{
291321eab5bfSRichard Henderson    if (tcg_out_cmp_vec_noinv(s, vece, a0, a1, a2, cond)) {
2914a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VNO, a0, a0, a0, 0);
291522cb37b4SRichard Henderson    }
291622cb37b4SRichard Henderson}
291722cb37b4SRichard Henderson
291822cb37b4SRichard Hendersonstatic void tcg_out_cmpsel_vec(TCGContext *s, unsigned vece, TCGReg a0,
291922cb37b4SRichard Henderson                               TCGReg c1, TCGReg c2, TCGArg v3,
292022cb37b4SRichard Henderson                               int const_v3, TCGReg v4, TCGCond cond)
292122cb37b4SRichard Henderson{
292222cb37b4SRichard Henderson    bool inv = tcg_out_cmp_vec_noinv(s, vece, TCG_VEC_TMP0, c1, c2, cond);
292322cb37b4SRichard Henderson
292422cb37b4SRichard Henderson    if (!const_v3) {
292522cb37b4SRichard Henderson        if (inv) {
292622cb37b4SRichard Henderson            tcg_out_insn(s, VRRe, VSEL, a0, v4, v3, TCG_VEC_TMP0);
292722cb37b4SRichard Henderson        } else {
292822cb37b4SRichard Henderson            tcg_out_insn(s, VRRe, VSEL, a0, v3, v4, TCG_VEC_TMP0);
292922cb37b4SRichard Henderson        }
293022cb37b4SRichard Henderson    } else if (v3) {
293122cb37b4SRichard Henderson        if (inv) {
293222cb37b4SRichard Henderson            tcg_out_insn(s, VRRc, VOC, a0, v4, TCG_VEC_TMP0, 0);
293322cb37b4SRichard Henderson        } else {
293422cb37b4SRichard Henderson            tcg_out_insn(s, VRRc, VO, a0, v4, TCG_VEC_TMP0, 0);
293522cb37b4SRichard Henderson        }
293622cb37b4SRichard Henderson    } else {
293722cb37b4SRichard Henderson        if (inv) {
293822cb37b4SRichard Henderson            tcg_out_insn(s, VRRc, VN, a0, v4, TCG_VEC_TMP0, 0);
293922cb37b4SRichard Henderson        } else {
294022cb37b4SRichard Henderson            tcg_out_insn(s, VRRc, VNC, a0, v4, TCG_VEC_TMP0, 0);
294122cb37b4SRichard Henderson        }
294222cb37b4SRichard Henderson    }
294322cb37b4SRichard Henderson}
294422cb37b4SRichard Henderson
294522cb37b4SRichard Hendersonstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
294622cb37b4SRichard Henderson                           unsigned vecl, unsigned vece,
294722cb37b4SRichard Henderson                           const TCGArg args[TCG_MAX_OP_ARGS],
294822cb37b4SRichard Henderson                           const int const_args[TCG_MAX_OP_ARGS])
294922cb37b4SRichard Henderson{
295022cb37b4SRichard Henderson    TCGType type = vecl + TCG_TYPE_V64;
295122cb37b4SRichard Henderson    TCGArg a0 = args[0], a1 = args[1], a2 = args[2];
2952220db7a6SRichard Henderson
2953220db7a6SRichard Henderson    switch (opc) {
2954220db7a6SRichard Henderson    case INDEX_op_ld_vec:
2955220db7a6SRichard Henderson        tcg_out_ld(s, type, a0, a1, a2);
2956220db7a6SRichard Henderson        break;
2957220db7a6SRichard Henderson    case INDEX_op_st_vec:
2958220db7a6SRichard Henderson        tcg_out_st(s, type, a0, a1, a2);
2959220db7a6SRichard Henderson        break;
2960220db7a6SRichard Henderson    case INDEX_op_dupm_vec:
2961220db7a6SRichard Henderson        tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
2962220db7a6SRichard Henderson        break;
2963220db7a6SRichard Henderson
2964220db7a6SRichard Henderson    case INDEX_op_abs_vec:
29659bca986dSRichard Henderson        tcg_out_insn(s, VRRa, VLP, a0, a1, vece);
29666e5f9fb7SRichard Henderson        break;
29679bca986dSRichard Henderson    case INDEX_op_neg_vec:
29689bca986dSRichard Henderson        tcg_out_insn(s, VRRa, VLC, a0, a1, vece);
2969a429ee29SRichard Henderson        break;
2970a429ee29SRichard Henderson    case INDEX_op_not_vec:
2971a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VNO, a0, a1, a1, 0);
2972a429ee29SRichard Henderson        break;
2973a429ee29SRichard Henderson
2974a429ee29SRichard Henderson    case INDEX_op_add_vec:
2975a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VA, a0, a1, a2, vece);
2976a429ee29SRichard Henderson        break;
2977a429ee29SRichard Henderson    case INDEX_op_sub_vec:
2978a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VS, a0, a1, a2, vece);
2979a429ee29SRichard Henderson        break;
2980a429ee29SRichard Henderson    case INDEX_op_and_vec:
298134ef7676SRichard Henderson        tcg_out_insn(s, VRRc, VN, a0, a1, a2, 0);
298234ef7676SRichard Henderson        break;
2983a429ee29SRichard Henderson    case INDEX_op_andc_vec:
2984a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VNC, a0, a1, a2, 0);
29854223c9c1SRichard Henderson        break;
29864223c9c1SRichard Henderson    case INDEX_op_mul_vec:
29874223c9c1SRichard Henderson        tcg_out_insn(s, VRRc, VML, a0, a1, a2, vece);
29884223c9c1SRichard Henderson        break;
29894223c9c1SRichard Henderson    case INDEX_op_or_vec:
29904223c9c1SRichard Henderson        tcg_out_insn(s, VRRc, VO, a0, a1, a2, 0);
29914223c9c1SRichard Henderson        break;
29924223c9c1SRichard Henderson    case INDEX_op_orc_vec:
29934223c9c1SRichard Henderson        tcg_out_insn(s, VRRc, VOC, a0, a1, a2, 0);
29944223c9c1SRichard Henderson        break;
2995a429ee29SRichard Henderson    case INDEX_op_xor_vec:
2996a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VX, a0, a1, a2, 0);
2997a429ee29SRichard Henderson        break;
2998a429ee29SRichard Henderson    case INDEX_op_nand_vec:
2999a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VNN, a0, a1, a2, 0);
3000a429ee29SRichard Henderson        break;
300134ef7676SRichard Henderson    case INDEX_op_nor_vec:
300234ef7676SRichard Henderson        tcg_out_insn(s, VRRc, VNO, a0, a1, a2, 0);
300334ef7676SRichard Henderson        break;
3004a429ee29SRichard Henderson    case INDEX_op_eqv_vec:
3005ae77bbe5SRichard Henderson        tcg_out_insn(s, VRRc, VNX, a0, a1, a2, 0);
3006a429ee29SRichard Henderson        break;
3007a429ee29SRichard Henderson
3008ae77bbe5SRichard Henderson    case INDEX_op_shli_vec:
30099bca986dSRichard Henderson        tcg_out_insn(s, VRSa, VESL, a0, a2, TCG_REG_NONE, a1, vece);
301021eab5bfSRichard Henderson        break;
301121eab5bfSRichard Henderson    case INDEX_op_shri_vec:
3012ae77bbe5SRichard Henderson        tcg_out_insn(s, VRSa, VESRL, a0, a2, TCG_REG_NONE, a1, vece);
301321eab5bfSRichard Henderson        break;
3014ae77bbe5SRichard Henderson    case INDEX_op_sari_vec:
3015a429ee29SRichard Henderson        tcg_out_insn(s, VRSa, VESRA, a0, a2, TCG_REG_NONE, a1, vece);
3016ae77bbe5SRichard Henderson        break;
301722cb37b4SRichard Henderson    case INDEX_op_rotli_vec:
301822cb37b4SRichard Henderson        tcg_out_insn(s, VRSa, VERLL, a0, a2, TCG_REG_NONE, a1, vece);
301922cb37b4SRichard Henderson        break;
302022cb37b4SRichard Henderson    case INDEX_op_shls_vec:
302122cb37b4SRichard Henderson        tcg_out_insn(s, VRSa, VESL, a0, 0, a2, a1, vece);
302222cb37b4SRichard Henderson        break;
302322cb37b4SRichard Henderson    case INDEX_op_shrs_vec:
302422cb37b4SRichard Henderson        tcg_out_insn(s, VRSa, VESRL, a0, 0, a2, a1, vece);
302522cb37b4SRichard Henderson        break;
302622cb37b4SRichard Henderson    case INDEX_op_sars_vec:
302722cb37b4SRichard Henderson        tcg_out_insn(s, VRSa, VESRA, a0, 0, a2, a1, vece);
302822cb37b4SRichard Henderson        break;
3029220db7a6SRichard Henderson    case INDEX_op_rotls_vec:
3030220db7a6SRichard Henderson        tcg_out_insn(s, VRSa, VERLL, a0, 0, a2, a1, vece);
3031a429ee29SRichard Henderson        break;
3032220db7a6SRichard Henderson    case INDEX_op_shlv_vec:
3033220db7a6SRichard Henderson        tcg_out_insn(s, VRRc, VESLV, a0, a1, a2, vece);
3034a429ee29SRichard Henderson        break;
3035a429ee29SRichard Henderson    case INDEX_op_shrv_vec:
3036a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VESRLV, a0, a1, a2, vece);
3037ea3f2af8SRichard Henderson        break;
303822cb37b4SRichard Henderson    case INDEX_op_sarv_vec:
3039a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VESRAV, a0, a1, a2, vece);
3040479b61cbSRichard Henderson        break;
3041479b61cbSRichard Henderson    case INDEX_op_rotlv_vec:
30424223c9c1SRichard Henderson        tcg_out_insn(s, VRRc, VERLLV, a0, a1, a2, vece);
30434223c9c1SRichard Henderson        break;
30444223c9c1SRichard Henderson
3045a429ee29SRichard Henderson    case INDEX_op_smin_vec:
304634ef7676SRichard Henderson        tcg_out_insn(s, VRRc, VMN, a0, a1, a2, vece);
304734ef7676SRichard Henderson        break;
3048a429ee29SRichard Henderson    case INDEX_op_smax_vec:
3049a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VMX, a0, a1, a2, vece);
3050a429ee29SRichard Henderson        break;
3051a429ee29SRichard Henderson    case INDEX_op_umin_vec:
3052a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VMNL, a0, a1, a2, vece);
3053a429ee29SRichard Henderson        break;
3054a429ee29SRichard Henderson    case INDEX_op_umax_vec:
3055a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VMXL, a0, a1, a2, vece);
3056a429ee29SRichard Henderson        break;
3057a429ee29SRichard Henderson
3058a429ee29SRichard Henderson    case INDEX_op_bitsel_vec:
3059a429ee29SRichard Henderson        tcg_out_insn(s, VRRe, VSEL, a0, a2, args[3], a1);
3060a429ee29SRichard Henderson        break;
3061a429ee29SRichard Henderson
3062a429ee29SRichard Henderson    case INDEX_op_cmp_vec:
3063a429ee29SRichard Henderson        tcg_out_cmp_vec(s, vece, a0, a1, a2, args[3]);
3064a429ee29SRichard Henderson        break;
3065a429ee29SRichard Henderson    case INDEX_op_cmpsel_vec:
3066a429ee29SRichard Henderson        tcg_out_cmpsel_vec(s, vece, a0, a1, a2, args[3], const_args[3],
3067a429ee29SRichard Henderson                           args[4], args[5]);
3068a429ee29SRichard Henderson        break;
3069a429ee29SRichard Henderson
3070a429ee29SRichard Henderson    case INDEX_op_s390_vuph_vec:
3071a429ee29SRichard Henderson        tcg_out_insn(s, VRRa, VUPH, a0, a1, vece);
3072a429ee29SRichard Henderson        break;
3073a429ee29SRichard Henderson    case INDEX_op_s390_vupl_vec:
3074a429ee29SRichard Henderson        tcg_out_insn(s, VRRa, VUPL, a0, a1, vece);
3075a429ee29SRichard Henderson        break;
3076a429ee29SRichard Henderson    case INDEX_op_s390_vpks_vec:
3077a429ee29SRichard Henderson        tcg_out_insn(s, VRRc, VPKS, a0, a1, a2, vece);
3078a429ee29SRichard Henderson        break;
3079a429ee29SRichard Henderson
3080a429ee29SRichard Henderson    case INDEX_op_mov_vec:   /* Always emitted via tcg_out_mov.  */
3081a429ee29SRichard Henderson    case INDEX_op_dup_vec:   /* Always emitted via tcg_out_dup_vec.  */
3082a429ee29SRichard Henderson    default:
3083a429ee29SRichard Henderson        g_assert_not_reached();
3084a429ee29SRichard Henderson    }
3085a429ee29SRichard Henderson}
3086a429ee29SRichard Henderson
3087a429ee29SRichard Hendersonint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
3088a429ee29SRichard Henderson{
3089a429ee29SRichard Henderson    switch (opc) {
3090a429ee29SRichard Henderson    case INDEX_op_abs_vec:
3091a429ee29SRichard Henderson    case INDEX_op_add_vec:
3092a429ee29SRichard Henderson    case INDEX_op_and_vec:
3093a429ee29SRichard Henderson    case INDEX_op_andc_vec:
3094a429ee29SRichard Henderson    case INDEX_op_bitsel_vec:
3095a429ee29SRichard Henderson    case INDEX_op_eqv_vec:
3096a429ee29SRichard Henderson    case INDEX_op_nand_vec:
3097a429ee29SRichard Henderson    case INDEX_op_neg_vec:
3098a429ee29SRichard Henderson    case INDEX_op_nor_vec:
309934ef7676SRichard Henderson    case INDEX_op_not_vec:
3100ea3f2af8SRichard Henderson    case INDEX_op_or_vec:
3101ea3f2af8SRichard Henderson    case INDEX_op_orc_vec:
3102ea3f2af8SRichard Henderson    case INDEX_op_rotli_vec:
3103ea3f2af8SRichard Henderson    case INDEX_op_rotls_vec:
3104ea3f2af8SRichard Henderson    case INDEX_op_rotlv_vec:
3105ea3f2af8SRichard Henderson    case INDEX_op_sari_vec:
3106ea3f2af8SRichard Henderson    case INDEX_op_sars_vec:
3107ea3f2af8SRichard Henderson    case INDEX_op_sarv_vec:
3108ea3f2af8SRichard Henderson    case INDEX_op_shli_vec:
3109ea3f2af8SRichard Henderson    case INDEX_op_shls_vec:
3110ea3f2af8SRichard Henderson    case INDEX_op_shlv_vec:
3111ea3f2af8SRichard Henderson    case INDEX_op_shri_vec:
3112ea3f2af8SRichard Henderson    case INDEX_op_shrs_vec:
3113ea3f2af8SRichard Henderson    case INDEX_op_shrv_vec:
3114ea3f2af8SRichard Henderson    case INDEX_op_smax_vec:
31154223c9c1SRichard Henderson    case INDEX_op_smin_vec:
31164223c9c1SRichard Henderson    case INDEX_op_sub_vec:
31174223c9c1SRichard Henderson    case INDEX_op_umax_vec:
31184223c9c1SRichard Henderson    case INDEX_op_umin_vec:
31194223c9c1SRichard Henderson    case INDEX_op_xor_vec:
31204223c9c1SRichard Henderson    case INDEX_op_cmp_vec:
31214223c9c1SRichard Henderson    case INDEX_op_cmpsel_vec:
31224223c9c1SRichard Henderson        return 1;
31234223c9c1SRichard Henderson    case INDEX_op_rotrv_vec:
31244223c9c1SRichard Henderson        return -1;
31254223c9c1SRichard Henderson    case INDEX_op_mul_vec:
31264223c9c1SRichard Henderson        return vece < MO_64;
31274223c9c1SRichard Henderson    case INDEX_op_ssadd_vec:
31284223c9c1SRichard Henderson    case INDEX_op_sssub_vec:
31294223c9c1SRichard Henderson        return vece < MO_64 ? -1 : 0;
31304223c9c1SRichard Henderson    default:
31314223c9c1SRichard Henderson        return 0;
31324223c9c1SRichard Henderson    }
31334223c9c1SRichard Henderson}
31344223c9c1SRichard Henderson
31354223c9c1SRichard Hendersonstatic void expand_vec_sat(TCGType type, unsigned vece, TCGv_vec v0,
31364223c9c1SRichard Henderson                           TCGv_vec v1, TCGv_vec v2, TCGOpcode add_sub_opc)
31374223c9c1SRichard Henderson{
31384223c9c1SRichard Henderson    TCGv_vec h1 = tcg_temp_new_vec(type);
31394223c9c1SRichard Henderson    TCGv_vec h2 = tcg_temp_new_vec(type);
31404223c9c1SRichard Henderson    TCGv_vec l1 = tcg_temp_new_vec(type);
31414223c9c1SRichard Henderson    TCGv_vec l2 = tcg_temp_new_vec(type);
31424223c9c1SRichard Henderson
31434223c9c1SRichard Henderson    tcg_debug_assert (vece < MO_64);
31444223c9c1SRichard Henderson
31454223c9c1SRichard Henderson    /* Unpack with sign-extension. */
31464223c9c1SRichard Henderson    vec_gen_2(INDEX_op_s390_vuph_vec, type, vece,
31474223c9c1SRichard Henderson              tcgv_vec_arg(h1), tcgv_vec_arg(v1));
31484223c9c1SRichard Henderson    vec_gen_2(INDEX_op_s390_vuph_vec, type, vece,
31494223c9c1SRichard Henderson              tcgv_vec_arg(h2), tcgv_vec_arg(v2));
31504223c9c1SRichard Henderson
31514223c9c1SRichard Henderson    vec_gen_2(INDEX_op_s390_vupl_vec, type, vece,
315234ef7676SRichard Henderson              tcgv_vec_arg(l1), tcgv_vec_arg(v1));
315334ef7676SRichard Henderson    vec_gen_2(INDEX_op_s390_vupl_vec, type, vece,
315434ef7676SRichard Henderson              tcgv_vec_arg(l2), tcgv_vec_arg(v2));
3155a429ee29SRichard Henderson
3156ea3f2af8SRichard Henderson    /* Arithmetic on a wider element size. */
3157a429ee29SRichard Henderson    vec_gen_3(add_sub_opc, type, vece + 1, tcgv_vec_arg(h1),
3158a429ee29SRichard Henderson              tcgv_vec_arg(h1), tcgv_vec_arg(h2));
3159a429ee29SRichard Henderson    vec_gen_3(add_sub_opc, type, vece + 1, tcgv_vec_arg(l1),
3160a429ee29SRichard Henderson              tcgv_vec_arg(l1), tcgv_vec_arg(l2));
3161a429ee29SRichard Henderson
3162a429ee29SRichard Henderson    /* Pack with saturation. */
3163a429ee29SRichard Henderson    vec_gen_3(INDEX_op_s390_vpks_vec, type, vece + 1,
3164a429ee29SRichard Henderson              tcgv_vec_arg(v0), tcgv_vec_arg(h1), tcgv_vec_arg(l1));
3165a429ee29SRichard Henderson
3166a429ee29SRichard Henderson    tcg_temp_free_vec(h1);
3167a429ee29SRichard Henderson    tcg_temp_free_vec(h2);
3168ea3f2af8SRichard Henderson    tcg_temp_free_vec(l1);
3169ea3f2af8SRichard Henderson    tcg_temp_free_vec(l2);
3170ea3f2af8SRichard Henderson}
3171ea3f2af8SRichard Henderson
3172ea3f2af8SRichard Hendersonvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
3173ea3f2af8SRichard Henderson                       TCGArg a0, ...)
317422cb37b4SRichard Henderson{
317522cb37b4SRichard Henderson    va_list va;
317622cb37b4SRichard Henderson    TCGv_vec v0, v1, v2, t0;
317722cb37b4SRichard Henderson
317822cb37b4SRichard Henderson    va_start(va, a0);
317922cb37b4SRichard Henderson    v0 = temp_tcgv_vec(arg_temp(a0));
318022cb37b4SRichard Henderson    v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg)));
31814223c9c1SRichard Henderson    v2 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg)));
31824223c9c1SRichard Henderson
31834223c9c1SRichard Henderson    switch (opc) {
31844223c9c1SRichard Henderson    case INDEX_op_rotrv_vec:
31854223c9c1SRichard Henderson        t0 = tcg_temp_new_vec(type);
31864223c9c1SRichard Henderson        tcg_gen_neg_vec(vece, t0, v2);
31874223c9c1SRichard Henderson        tcg_gen_rotlv_vec(vece, v0, v1, t0);
3188a429ee29SRichard Henderson        tcg_temp_free_vec(t0);
318934ef7676SRichard Henderson        break;
319034ef7676SRichard Henderson
3191a429ee29SRichard Henderson    case INDEX_op_ssadd_vec:
3192a429ee29SRichard Henderson        expand_vec_sat(type, vece, v0, v1, v2, INDEX_op_add_vec);
319334ef7676SRichard Henderson        break;
31943704993fSRichard Henderson    case INDEX_op_sssub_vec:
31953704993fSRichard Henderson        expand_vec_sat(type, vece, v0, v1, v2, INDEX_op_sub_vec);
31963704993fSRichard Henderson        break;
31973704993fSRichard Henderson
31983704993fSRichard Henderson    default:
31993704993fSRichard Henderson        g_assert_not_reached();
32003704993fSRichard Henderson    }
32013704993fSRichard Henderson    va_end(va);
32023704993fSRichard Henderson}
32033704993fSRichard Henderson
32043704993fSRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
32053704993fSRichard Henderson{
32063704993fSRichard Henderson    switch (op) {
32073704993fSRichard Henderson    case INDEX_op_goto_ptr:
32083704993fSRichard Henderson        return C_O0_I1(r);
32093704993fSRichard Henderson
32103704993fSRichard Henderson    case INDEX_op_ld8u_i32:
32113704993fSRichard Henderson    case INDEX_op_ld8u_i64:
32123704993fSRichard Henderson    case INDEX_op_ld8s_i32:
32133704993fSRichard Henderson    case INDEX_op_ld8s_i64:
32143704993fSRichard Henderson    case INDEX_op_ld16u_i32:
32153704993fSRichard Henderson    case INDEX_op_ld16u_i64:
32163704993fSRichard Henderson    case INDEX_op_ld16s_i32:
32173704993fSRichard Henderson    case INDEX_op_ld16s_i64:
32183704993fSRichard Henderson    case INDEX_op_ld_i32:
32193704993fSRichard Henderson    case INDEX_op_ld32u_i64:
32203704993fSRichard Henderson    case INDEX_op_ld32s_i64:
32213704993fSRichard Henderson    case INDEX_op_ld_i64:
32223704993fSRichard Henderson        return C_O1_I1(r, r);
32233704993fSRichard Henderson
32243704993fSRichard Henderson    case INDEX_op_st8_i32:
32253704993fSRichard Henderson    case INDEX_op_st8_i64:
32263704993fSRichard Henderson    case INDEX_op_st16_i32:
32273704993fSRichard Henderson    case INDEX_op_st16_i64:
32283704993fSRichard Henderson    case INDEX_op_st_i32:
32293704993fSRichard Henderson    case INDEX_op_st32_i64:
32303704993fSRichard Henderson    case INDEX_op_st_i64:
32313704993fSRichard Henderson        return C_O0_I2(r, r);
3232*994f8717SPaolo Bonzini
32333704993fSRichard Henderson    case INDEX_op_add_i32:
3234128c7d51SRichard Henderson    case INDEX_op_add_i64:
323532c256edSRichard Henderson    case INDEX_op_shl_i64:
3236128c7d51SRichard Henderson    case INDEX_op_shr_i64:
3237d95b51d3SRichard Henderson    case INDEX_op_sar_i64:
32383704993fSRichard Henderson    case INDEX_op_rotl_i32:
3239bfff8518SRichard Henderson    case INDEX_op_rotl_i64:
3240bfff8518SRichard Henderson    case INDEX_op_rotr_i32:
3241bfff8518SRichard Henderson    case INDEX_op_rotr_i64:
32423704993fSRichard Henderson        return C_O1_I2(r, r, ri);
32433704993fSRichard Henderson    case INDEX_op_setcond_i32:
32443704993fSRichard Henderson    case INDEX_op_negsetcond_i32:
32453704993fSRichard Henderson    case INDEX_op_setcond_i64:
32463704993fSRichard Henderson    case INDEX_op_negsetcond_i64:
3247238da1c9SRichard Henderson        return C_O1_I2(r, r, rC);
32484134083fSRichard Henderson
32494134083fSRichard Henderson    case INDEX_op_clz_i64:
3250b2509accSRichard Henderson        return C_O1_I2(r, r, rI);
3251b2509accSRichard Henderson
3252b2509accSRichard Henderson    case INDEX_op_sub_i32:
32533704993fSRichard Henderson    case INDEX_op_sub_i64:
32546c9b5c0fSRichard Henderson    case INDEX_op_and_i32:
32556c9b5c0fSRichard Henderson    case INDEX_op_or_i32:
32566c9b5c0fSRichard Henderson    case INDEX_op_xor_i32:
32576c9b5c0fSRichard Henderson        return C_O1_I2(r, r, ri);
32586c9b5c0fSRichard Henderson    case INDEX_op_and_i64:
32596c9b5c0fSRichard Henderson        return C_O1_I2(r, r, rNKR);
32606c9b5c0fSRichard Henderson    case INDEX_op_or_i64:
32616c9b5c0fSRichard Henderson    case INDEX_op_xor_i64:
32626c9b5c0fSRichard Henderson        return C_O1_I2(r, r, rK);
32636c9b5c0fSRichard Henderson
32646c9b5c0fSRichard Henderson    case INDEX_op_andc_i32:
32656c9b5c0fSRichard Henderson    case INDEX_op_orc_i32:
32666c9b5c0fSRichard Henderson    case INDEX_op_eqv_i32:
32676c9b5c0fSRichard Henderson        return C_O1_I2(r, r, ri);
32686c9b5c0fSRichard Henderson    case INDEX_op_andc_i64:
32696c9b5c0fSRichard Henderson        return C_O1_I2(r, r, rKR);
32703704993fSRichard Henderson    case INDEX_op_orc_i64:
327192c89a07SRichard Henderson    case INDEX_op_eqv_i64:
327292c89a07SRichard Henderson        return C_O1_I2(r, r, rNK);
327392c89a07SRichard Henderson
32743704993fSRichard Henderson    case INDEX_op_nand_i32:
327592c89a07SRichard Henderson    case INDEX_op_nand_i64:
327692c89a07SRichard Henderson    case INDEX_op_nor_i32:
327792c89a07SRichard Henderson    case INDEX_op_nor_i64:
32783704993fSRichard Henderson        return C_O1_I2(r, r, r);
32793704993fSRichard Henderson
32803704993fSRichard Henderson    case INDEX_op_mul_i32:
32813704993fSRichard Henderson        return (HAVE_FACILITY(MISC_INSN_EXT2)
3282238da1c9SRichard Henderson                ? C_O1_I2(r, r, ri)
32833704993fSRichard Henderson                : C_O1_I2(r, 0, ri));
32843704993fSRichard Henderson    case INDEX_op_mul_i64:
32853704993fSRichard Henderson        return (HAVE_FACILITY(MISC_INSN_EXT2)
328632c256edSRichard Henderson                ? C_O1_I2(r, r, rJ)
3287d95b51d3SRichard Henderson                : C_O1_I2(r, 0, rJ));
32883704993fSRichard Henderson
32893704993fSRichard Henderson    case INDEX_op_shl_i32:
32903704993fSRichard Henderson    case INDEX_op_shr_i32:
32913704993fSRichard Henderson    case INDEX_op_sar_i32:
32923704993fSRichard Henderson        return C_O1_I2(r, r, ri);
32933704993fSRichard Henderson
32943704993fSRichard Henderson    case INDEX_op_brcond_i32:
32953704993fSRichard Henderson        return C_O0_I2(r, ri);
32966c9b5c0fSRichard Henderson    case INDEX_op_brcond_i64:
32976c9b5c0fSRichard Henderson        return C_O0_I2(r, rC);
32983704993fSRichard Henderson
32993704993fSRichard Henderson    case INDEX_op_bswap16_i32:
33003704993fSRichard Henderson    case INDEX_op_bswap16_i64:
33013704993fSRichard Henderson    case INDEX_op_bswap32_i32:
33023704993fSRichard Henderson    case INDEX_op_bswap32_i64:
33033704993fSRichard Henderson    case INDEX_op_bswap64_i64:
33043704993fSRichard Henderson    case INDEX_op_neg_i32:
33053704993fSRichard Henderson    case INDEX_op_neg_i64:
33063704993fSRichard Henderson    case INDEX_op_not_i32:
33073704993fSRichard Henderson    case INDEX_op_not_i64:
33083704993fSRichard Henderson    case INDEX_op_ext8s_i32:
33093704993fSRichard Henderson    case INDEX_op_ext8s_i64:
33103704993fSRichard Henderson    case INDEX_op_ext8u_i32:
33113704993fSRichard Henderson    case INDEX_op_ext8u_i64:
331229a5ea73SRichard Henderson    case INDEX_op_ext16s_i32:
331329a5ea73SRichard Henderson    case INDEX_op_ext16s_i64:
33143704993fSRichard Henderson    case INDEX_op_ext16u_i32:
33153704993fSRichard Henderson    case INDEX_op_ext16u_i64:
3316fecccfccSRichard Henderson    case INDEX_op_ext32s_i64:
3317fecccfccSRichard Henderson    case INDEX_op_ext32u_i64:
3318fecccfccSRichard Henderson    case INDEX_op_ext_i32_i64:
3319fecccfccSRichard Henderson    case INDEX_op_extu_i32_i64:
332094901422SRichard Henderson    case INDEX_op_extract_i32:
3321fecccfccSRichard Henderson    case INDEX_op_extract_i64:
3322fecccfccSRichard Henderson    case INDEX_op_ctpop_i32:
3323fecccfccSRichard Henderson    case INDEX_op_ctpop_i64:
3324fecccfccSRichard Henderson        return C_O1_I1(r, r);
332594901422SRichard Henderson
33264caad79fSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
33274caad79fSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
33284caad79fSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
33294caad79fSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
33304caad79fSRichard Henderson        return C_O1_I1(r, r);
33314caad79fSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
33323704993fSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
33333704993fSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
33343704993fSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
33353704993fSRichard Henderson        return C_O0_I2(r, r);
33363704993fSRichard Henderson    case INDEX_op_qemu_ld_a32_i128:
33373704993fSRichard Henderson    case INDEX_op_qemu_ld_a64_i128:
333823d1394aSRichard Henderson        return C_O2_I1(o, m, r);
333932c256edSRichard Henderson    case INDEX_op_qemu_st_a32_i128:
3340d95b51d3SRichard Henderson    case INDEX_op_qemu_st_a64_i128:
33413704993fSRichard Henderson        return C_O0_I3(o, m, r);
33423704993fSRichard Henderson
33433704993fSRichard Henderson    case INDEX_op_deposit_i32:
33443704993fSRichard Henderson    case INDEX_op_deposit_i64:
33453704993fSRichard Henderson        return C_O1_I2(r, rZ, r);
33464143f78dSRichard Henderson
33473704993fSRichard Henderson    case INDEX_op_movcond_i32:
33483704993fSRichard Henderson        return C_O1_I4(r, r, ri, rI, r);
33494143f78dSRichard Henderson    case INDEX_op_movcond_i64:
3350668ce343SRichard Henderson        return C_O1_I4(r, r, rC, rI, r);
3351668ce343SRichard Henderson
33523704993fSRichard Henderson    case INDEX_op_div2_i32:
33533704993fSRichard Henderson    case INDEX_op_div2_i64:
33543704993fSRichard Henderson    case INDEX_op_divu2_i32:
335522d2e535SIlya Leoshkevich    case INDEX_op_divu2_i64:
33563704993fSRichard Henderson        return C_O2_I3(o, m, 0, 1, r);
33573704993fSRichard Henderson
33583704993fSRichard Henderson    case INDEX_op_mulu2_i64:
3359cbaddf30SRichard Henderson        return C_O2_I2(o, m, 0, r);
33603704993fSRichard Henderson    case INDEX_op_muls2_i64:
336134ef7676SRichard Henderson        return C_O2_I2(o, m, r, r);
336234ef7676SRichard Henderson
336334ef7676SRichard Henderson    case INDEX_op_add2_i32:
336434ef7676SRichard Henderson    case INDEX_op_sub2_i32:
336534ef7676SRichard Henderson        return C_N1_O1_I4(r, r, 0, 1, ri, r);
336634ef7676SRichard Henderson
336734ef7676SRichard Henderson    case INDEX_op_add2_i64:
3368ae77bbe5SRichard Henderson    case INDEX_op_sub2_i64:
3369ae77bbe5SRichard Henderson        return C_N1_O1_I4(r, r, 0, 1, rJU, r);
3370ae77bbe5SRichard Henderson
337122cb37b4SRichard Henderson    case INDEX_op_st_vec:
337222cb37b4SRichard Henderson        return C_O0_I2(v, r);
337322cb37b4SRichard Henderson    case INDEX_op_ld_vec:
337422cb37b4SRichard Henderson    case INDEX_op_dupm_vec:
33754223c9c1SRichard Henderson        return C_O1_I1(v, r);
33764223c9c1SRichard Henderson    case INDEX_op_dup_vec:
3377ae77bbe5SRichard Henderson        return C_O1_I1(v, vr);
337834ef7676SRichard Henderson    case INDEX_op_abs_vec:
337934ef7676SRichard Henderson    case INDEX_op_neg_vec:
338034ef7676SRichard Henderson    case INDEX_op_not_vec:
3381ae77bbe5SRichard Henderson    case INDEX_op_rotli_vec:
338234ef7676SRichard Henderson    case INDEX_op_sari_vec:
3383ae77bbe5SRichard Henderson    case INDEX_op_shli_vec:
338434ef7676SRichard Henderson    case INDEX_op_shri_vec:
338521eab5bfSRichard Henderson    case INDEX_op_s390_vuph_vec:
338621eab5bfSRichard Henderson    case INDEX_op_s390_vupl_vec:
338721eab5bfSRichard Henderson        return C_O1_I1(v, v);
338834ef7676SRichard Henderson    case INDEX_op_add_vec:
3389479b61cbSRichard Henderson    case INDEX_op_sub_vec:
339022cb37b4SRichard Henderson    case INDEX_op_and_vec:
339122cb37b4SRichard Henderson    case INDEX_op_andc_vec:
339222cb37b4SRichard Henderson    case INDEX_op_or_vec:
339322cb37b4SRichard Henderson    case INDEX_op_orc_vec:
339422cb37b4SRichard Henderson    case INDEX_op_xor_vec:
3395220db7a6SRichard Henderson    case INDEX_op_nand_vec:
3396220db7a6SRichard Henderson    case INDEX_op_nor_vec:
3397220db7a6SRichard Henderson    case INDEX_op_eqv_vec:
3398220db7a6SRichard Henderson    case INDEX_op_cmp_vec:
33994223c9c1SRichard Henderson    case INDEX_op_mul_vec:
340034ef7676SRichard Henderson    case INDEX_op_rotlv_vec:
340122cb37b4SRichard Henderson    case INDEX_op_rotrv_vec:
340222cb37b4SRichard Henderson    case INDEX_op_shlv_vec:
340322cb37b4SRichard Henderson    case INDEX_op_shrv_vec:
340422cb37b4SRichard Henderson    case INDEX_op_sarv_vec:
340522cb37b4SRichard Henderson    case INDEX_op_smax_vec:
34069bca986dSRichard Henderson    case INDEX_op_smin_vec:
34079bca986dSRichard Henderson    case INDEX_op_umax_vec:
340834ef7676SRichard Henderson    case INDEX_op_umin_vec:
34093704993fSRichard Henderson    case INDEX_op_s390_vpks_vec:
34103704993fSRichard Henderson        return C_O1_I2(v, v, v);
34113704993fSRichard Henderson    case INDEX_op_rotls_vec:
34123704993fSRichard Henderson    case INDEX_op_shls_vec:
34133704993fSRichard Henderson    case INDEX_op_shrs_vec:
341434ef7676SRichard Henderson    case INDEX_op_sars_vec:
341534ef7676SRichard Henderson        return C_O1_I2(v, v, r);
341634ef7676SRichard Henderson    case INDEX_op_bitsel_vec:
341734ef7676SRichard Henderson        return C_O1_I3(v, v, v, v);
341834ef7676SRichard Henderson    case INDEX_op_cmpsel_vec:
341934ef7676SRichard Henderson        return (TCG_TARGET_HAS_orc_vec
342034ef7676SRichard Henderson                ? C_O1_I4(v, v, v, vZM, v)
342134ef7676SRichard Henderson                : C_O1_I4(v, v, v, vZ, v));
34223704993fSRichard Henderson
34233704993fSRichard Henderson    default:
34243704993fSRichard Henderson        g_assert_not_reached();
3425761ea522SRichard Henderson    }
34263704993fSRichard Henderson}
34273704993fSRichard Henderson
34283704993fSRichard Henderson/*
34293704993fSRichard Henderson * Mainline glibc added HWCAP_S390_VX before it was kernel abi.
3430748b7f3eSRichard Henderson * Some distros have fixed this up locally, others have not.
3431748b7f3eSRichard Henderson */
34323704993fSRichard Henderson#ifndef HWCAP_S390_VXRS
34333704993fSRichard Henderson#define HWCAP_S390_VXRS 2048
34343704993fSRichard Henderson#endif
3435748b7f3eSRichard Henderson
34363704993fSRichard Hendersonstatic void query_s390_facilities(void)
343734ef7676SRichard Henderson{
343834ef7676SRichard Henderson    unsigned long hwcap = qemu_getauxval(AT_HWCAP);
343934ef7676SRichard Henderson    const char *which;
344034ef7676SRichard Henderson
344134ef7676SRichard Henderson    /* Is STORE FACILITY LIST EXTENDED available?  Honestly, I believe this
344234ef7676SRichard Henderson       is present on all 64-bit systems, but let's check for it anyway.  */
344334ef7676SRichard Henderson    if (hwcap & HWCAP_S390_STFLE) {
3444a429ee29SRichard Henderson        register int r0 __asm__("0") = ARRAY_SIZE(s390_facilities) - 1;
344534ef7676SRichard Henderson        register void *r1 __asm__("1") = s390_facilities;
344634ef7676SRichard Henderson
3447761ea522SRichard Henderson        /* stfle 0(%r1) */
3448761ea522SRichard Henderson        asm volatile(".word 0xb2b0,0x1000"
3449c68d5b7aSRichard Henderson                     : "=r"(r0) : "r"(r0), "r"(r1) : "memory", "cc");
3450761ea522SRichard Henderson    }
3451761ea522SRichard Henderson
3452761ea522SRichard Henderson    /*
3453761ea522SRichard Henderson     * Use of vector registers requires os support beyond the facility bit.
3454761ea522SRichard Henderson     * If the kernel does not advertise support, disable the facility bits.
3455761ea522SRichard Henderson     * There is nothing else we currently care about in the 3rd word, so
3456761ea522SRichard Henderson     * disable VECTOR with one store.
34573e25f7daSRichard Henderson     */
34583e25f7daSRichard Henderson    if (!(hwcap & HWCAP_S390_VXRS)) {
34593e25f7daSRichard Henderson        s390_facilities[2] = 0;
34603e25f7daSRichard Henderson    }
34619c3bfb79SRichard Henderson
34629c3bfb79SRichard Henderson    /*
34639c3bfb79SRichard Henderson     * Minimum supported cpu revision is z196.
34649c3bfb79SRichard Henderson     * Check for all required facilities.
3465c68d5b7aSRichard Henderson     * ZARCH_ACTIVE is done via preprocessor check for 64-bit.
3466c68d5b7aSRichard Henderson     */
3467c68d5b7aSRichard Henderson    if (!HAVE_FACILITY(LONG_DISP)) {
3468c68d5b7aSRichard Henderson        which = "long-displacement";
3469c68d5b7aSRichard Henderson        goto fail;
3470c68d5b7aSRichard Henderson    }
3471c68d5b7aSRichard Henderson    if (!HAVE_FACILITY(EXT_IMM)) {
3472c68d5b7aSRichard Henderson        which = "extended-immediate";
3473c68d5b7aSRichard Henderson        goto fail;
3474761ea522SRichard Henderson    }
3475761ea522SRichard Henderson    if (!HAVE_FACILITY(GEN_INST_EXT)) {
3476761ea522SRichard Henderson        which = "general-instructions-extension";
3477761ea522SRichard Henderson        goto fail;
3478761ea522SRichard Henderson    }
34793704993fSRichard Henderson    /*
34803704993fSRichard Henderson     * Facility 45 is a big bin that contains: distinct-operands,
34813704993fSRichard Henderson     * fast-BCR-serialization, high-word, population-count,
34823704993fSRichard Henderson     * interlocked-access-1, and load/store-on-condition-1
34833704993fSRichard Henderson     */
34843704993fSRichard Henderson    if (!HAVE_FACILITY(45)) {
34853704993fSRichard Henderson        which = "45";
34863704993fSRichard Henderson        goto fail;
348734ef7676SRichard Henderson    }
348834ef7676SRichard Henderson    return;
348934ef7676SRichard Henderson
349034ef7676SRichard Henderson fail:
34913704993fSRichard Henderson    error_report("%s: missing required facility %s", __func__, which);
34923704993fSRichard Henderson    exit(EXIT_FAILURE);
34933704993fSRichard Henderson}
34943704993fSRichard Henderson
34953704993fSRichard Hendersonstatic void tcg_target_init(TCGContext *s)
34963704993fSRichard Henderson{
34973704993fSRichard Henderson    query_s390_facilities();
34983704993fSRichard Henderson
34993704993fSRichard Henderson    tcg_target_available_regs[TCG_TYPE_I32] = 0xffff;
35003704993fSRichard Henderson    tcg_target_available_regs[TCG_TYPE_I64] = 0xffff;
35013704993fSRichard Henderson    if (HAVE_FACILITY(VECTOR)) {
35023704993fSRichard Henderson        tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;
35033704993fSRichard Henderson        tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull;
35043704993fSRichard Henderson    }
350534ef7676SRichard Henderson
350634ef7676SRichard Henderson    tcg_target_call_clobber_regs = 0;
350734ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0);
350834ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R1);
350934ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R2);
351034ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R3);
351134ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R4);
351234ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R5);
351334ef7676SRichard Henderson    /* The r6 register is technically call-saved, but it's also a parameter
351434ef7676SRichard Henderson       register, so it can get killed by setup for the qemu_st helper.  */
351534ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R6);
351634ef7676SRichard Henderson    /* The return register can be considered call-clobbered.  */
351734ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14);
351834ef7676SRichard Henderson
351934ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
352034ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
352134ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V2);
352234ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V3);
352334ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V4);
352434ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V5);
352534ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V6);
352634ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V7);
352734ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V16);
352834ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V17);
352934ef7676SRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V18);
35303704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V19);
35313704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V20);
35323704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V21);
35333704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V22);
35343704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V23);
35353704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V24);
35363704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V25);
35373704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V26);
35383704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V27);
35393704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V28);
35403704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V29);
35413704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V30);
35423704993fSRichard Henderson    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V31);
35433704993fSRichard Henderson
35443704993fSRichard Henderson    s->reserved_regs = 0;
35453704993fSRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_TMP0);
35463704993fSRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP0);
35473704993fSRichard Henderson    /* XXX many insns can't be used with R0, so we better avoid it for now */
35483704993fSRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
35493704993fSRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
35503704993fSRichard Henderson}
35513704993fSRichard Henderson
35523704993fSRichard Henderson#define FRAME_SIZE  ((int)(TCG_TARGET_CALL_STACK_OFFSET          \
35532e486b59SRichard Henderson                           + TCG_STATIC_CALL_ARGS_SIZE           \
3554ccbecb44SRichard Henderson                           + CPU_TEMP_BUF_NLONGS * sizeof(long)))
35553704993fSRichard Henderson
35563704993fSRichard Hendersonstatic void tcg_target_qemu_prologue(TCGContext *s)
35573704993fSRichard Henderson{
35583704993fSRichard Henderson    /* stmg %r6,%r15,48(%r15) (save registers) */
35593704993fSRichard Henderson    tcg_out_insn(s, RXY, STMG, TCG_REG_R6, TCG_REG_R15, TCG_REG_R15, 48);
35603704993fSRichard Henderson
35613704993fSRichard Henderson    /* aghi %r15,-frame_size */
35623704993fSRichard Henderson    tcg_out_insn(s, RI, AGHI, TCG_REG_R15, -FRAME_SIZE);
35633704993fSRichard Henderson
35643704993fSRichard Henderson    tcg_set_frame(s, TCG_REG_CALL_STACK,
35653704993fSRichard Henderson                  TCG_STATIC_CALL_ARGS_SIZE + TCG_TARGET_CALL_STACK_OFFSET,
35663704993fSRichard Henderson                  CPU_TEMP_BUF_NLONGS * sizeof(long));
35673704993fSRichard Henderson
35683704993fSRichard Henderson    if (!tcg_use_softmmu && guest_base >= 0x80000) {
35693704993fSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
35703704993fSRichard Henderson        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
35713704993fSRichard Henderson    }
35723704993fSRichard Henderson
35733704993fSRichard Henderson    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
35743704993fSRichard Henderson
35753704993fSRichard Henderson    /* br %r3 (go to TB) */
35763704993fSRichard Henderson    tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, tcg_target_call_iarg_regs[1]);
35773704993fSRichard Henderson
35783704993fSRichard Henderson    /*
35793704993fSRichard Henderson     * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
35803704993fSRichard Henderson     * and fall through to the rest of the epilogue.
35819358fbbfSRichard Henderson     */
35829358fbbfSRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
35839358fbbfSRichard Henderson    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, 0);
35849358fbbfSRichard Henderson
35859358fbbfSRichard Henderson    /* TB epilogue */
35863704993fSRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
35873704993fSRichard Henderson
35883704993fSRichard Henderson    /* lmg %r6,%r15,fs+48(%r15) (restore registers) */
35893704993fSRichard Henderson    tcg_out_insn(s, RXY, LMG, TCG_REG_R6, TCG_REG_R15, TCG_REG_R15,
35903704993fSRichard Henderson                 FRAME_SIZE + 48);
35913704993fSRichard Henderson
35923704993fSRichard Henderson    /* br %r14 (return) */
35933704993fSRichard Henderson    tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_R14);
35943704993fSRichard Henderson}
35953704993fSRichard Henderson
35963704993fSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
35973704993fSRichard Henderson{
35983704993fSRichard Henderson    /* nothing to do */
35993704993fSRichard Henderson}
36003704993fSRichard Henderson
36013704993fSRichard Hendersonstatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
36023704993fSRichard Henderson{
36033704993fSRichard Henderson    memset(p, 0x07, count * sizeof(tcg_insn_unit));
36043704993fSRichard Henderson}
36053704993fSRichard Henderson
36063704993fSRichard Hendersontypedef struct {
36073704993fSRichard Henderson    DebugFrameHeader h;
36083704993fSRichard Henderson    uint8_t fde_def_cfa[4];
36093704993fSRichard Henderson    uint8_t fde_reg_ofs[18];
36103704993fSRichard Henderson} DebugFrame;
36113704993fSRichard Henderson
36123704993fSRichard Henderson/* We're expecting a 2 byte uleb128 encoded value.  */
36133704993fSRichard HendersonQEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
36143704993fSRichard Henderson
36153704993fSRichard Henderson#define ELF_HOST_MACHINE  EM_S390
36163704993fSRichard Henderson
36173704993fSRichard Hendersonstatic const DebugFrame debug_frame = {
36183704993fSRichard Henderson    .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
36193704993fSRichard Henderson    .h.cie.id = -1,
36203704993fSRichard Henderson    .h.cie.version = 1,
36213704993fSRichard Henderson    .h.cie.code_align = 1,
36223704993fSRichard Henderson    .h.cie.data_align = 8,                /* sleb128 8 */
36233704993fSRichard Henderson    .h.cie.return_column = TCG_REG_R14,
36243704993fSRichard Henderson
36253704993fSRichard Henderson    /* Total FDE size does not include the "len" member.  */
36263704993fSRichard Henderson    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
36273704993fSRichard Henderson
36283704993fSRichard Henderson    .fde_def_cfa = {
36293704993fSRichard Henderson        12, TCG_REG_CALL_STACK,         /* DW_CFA_def_cfa %r15, ... */
36303704993fSRichard Henderson        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
36313704993fSRichard Henderson        (FRAME_SIZE >> 7)
36323704993fSRichard Henderson    },
36333704993fSRichard Henderson    .fde_reg_ofs = {
36343704993fSRichard Henderson        0x86, 6,                        /* DW_CFA_offset, %r6, 48 */
3635        0x87, 7,                        /* DW_CFA_offset, %r7, 56 */
3636        0x88, 8,                        /* DW_CFA_offset, %r8, 64 */
3637        0x89, 9,                        /* DW_CFA_offset, %r92, 72 */
3638        0x8a, 10,                       /* DW_CFA_offset, %r10, 80 */
3639        0x8b, 11,                       /* DW_CFA_offset, %r11, 88 */
3640        0x8c, 12,                       /* DW_CFA_offset, %r12, 96 */
3641        0x8d, 13,                       /* DW_CFA_offset, %r13, 104 */
3642        0x8e, 14,                       /* DW_CFA_offset, %r14, 112 */
3643    }
3644};
3645
3646void tcg_register_jit(const void *buf, size_t buf_size)
3647{
3648    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
3649}
3650