|
|
1.1 root 1: /*
2: * Tiny Code Generator for QEMU
3: *
4: * Copyright (c) 2009 Ulrich Hecht <[email protected]>
1.1.1.2 ! root 5: * Copyright (c) 2009 Alexander Graf <[email protected]>
! 6: * Copyright (c) 2010 Richard Henderson <[email protected]>
1.1 root 7: *
8: * Permission is hereby granted, free of charge, to any person obtaining a copy
9: * of this software and associated documentation files (the "Software"), to deal
10: * in the Software without restriction, including without limitation the rights
11: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12: * copies of the Software, and to permit persons to whom the Software is
13: * furnished to do so, subject to the following conditions:
14: *
15: * The above copyright notice and this permission notice shall be included in
16: * all copies or substantial portions of the Software.
17: *
18: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24: * THE SOFTWARE.
25: */
26:
1.1.1.2 ! root 27: /* ??? The translation blocks produced by TCG are generally small enough to
! 28: be entirely reachable with a 16-bit displacement. Leaving the option for
! 29: a 32-bit displacement here Just In Case. */
! 30: #define USE_LONG_BRANCHES 0
! 31:
! 32: #define TCG_CT_CONST_32 0x0100
! 33: #define TCG_CT_CONST_NEG 0x0200
! 34: #define TCG_CT_CONST_ADDI 0x0400
! 35: #define TCG_CT_CONST_MULI 0x0800
! 36: #define TCG_CT_CONST_ANDI 0x1000
! 37: #define TCG_CT_CONST_ORI 0x2000
! 38: #define TCG_CT_CONST_XORI 0x4000
! 39: #define TCG_CT_CONST_CMPI 0x8000
! 40:
! 41: /* Several places within the instruction set 0 means "no register"
! 42: rather than TCG_REG_R0. */
! 43: #define TCG_REG_NONE 0
! 44:
! 45: /* A scratch register that may be be used throughout the backend. */
! 46: #define TCG_TMP0 TCG_REG_R14
! 47:
! 48: #ifdef CONFIG_USE_GUEST_BASE
! 49: #define TCG_GUEST_BASE_REG TCG_REG_R13
! 50: #else
! 51: #define TCG_GUEST_BASE_REG TCG_REG_R0
! 52: #endif
! 53:
! 54: #ifndef GUEST_BASE
! 55: #define GUEST_BASE 0
! 56: #endif
! 57:
! 58:
! 59: /* All of the following instructions are prefixed with their instruction
! 60: format, and are defined as 8- or 16-bit quantities, even when the two
! 61: halves of the 16-bit quantity may appear 32 bits apart in the insn.
! 62: This makes it easy to copy the values from the tables in Appendix B. */
! 63: typedef enum S390Opcode {
! 64: RIL_AFI = 0xc209,
! 65: RIL_AGFI = 0xc208,
! 66: RIL_ALGFI = 0xc20a,
! 67: RIL_BRASL = 0xc005,
! 68: RIL_BRCL = 0xc004,
! 69: RIL_CFI = 0xc20d,
! 70: RIL_CGFI = 0xc20c,
! 71: RIL_CLFI = 0xc20f,
! 72: RIL_CLGFI = 0xc20e,
! 73: RIL_IIHF = 0xc008,
! 74: RIL_IILF = 0xc009,
! 75: RIL_LARL = 0xc000,
! 76: RIL_LGFI = 0xc001,
! 77: RIL_LGRL = 0xc408,
! 78: RIL_LLIHF = 0xc00e,
! 79: RIL_LLILF = 0xc00f,
! 80: RIL_LRL = 0xc40d,
! 81: RIL_MSFI = 0xc201,
! 82: RIL_MSGFI = 0xc200,
! 83: RIL_NIHF = 0xc00a,
! 84: RIL_NILF = 0xc00b,
! 85: RIL_OIHF = 0xc00c,
! 86: RIL_OILF = 0xc00d,
! 87: RIL_XIHF = 0xc006,
! 88: RIL_XILF = 0xc007,
! 89:
! 90: RI_AGHI = 0xa70b,
! 91: RI_AHI = 0xa70a,
! 92: RI_BRC = 0xa704,
! 93: RI_IIHH = 0xa500,
! 94: RI_IIHL = 0xa501,
! 95: RI_IILH = 0xa502,
! 96: RI_IILL = 0xa503,
! 97: RI_LGHI = 0xa709,
! 98: RI_LLIHH = 0xa50c,
! 99: RI_LLIHL = 0xa50d,
! 100: RI_LLILH = 0xa50e,
! 101: RI_LLILL = 0xa50f,
! 102: RI_MGHI = 0xa70d,
! 103: RI_MHI = 0xa70c,
! 104: RI_NIHH = 0xa504,
! 105: RI_NIHL = 0xa505,
! 106: RI_NILH = 0xa506,
! 107: RI_NILL = 0xa507,
! 108: RI_OIHH = 0xa508,
! 109: RI_OIHL = 0xa509,
! 110: RI_OILH = 0xa50a,
! 111: RI_OILL = 0xa50b,
! 112:
! 113: RIE_CGIJ = 0xec7c,
! 114: RIE_CGRJ = 0xec64,
! 115: RIE_CIJ = 0xec7e,
! 116: RIE_CLGRJ = 0xec65,
! 117: RIE_CLIJ = 0xec7f,
! 118: RIE_CLGIJ = 0xec7d,
! 119: RIE_CLRJ = 0xec77,
! 120: RIE_CRJ = 0xec76,
! 121:
! 122: RRE_AGR = 0xb908,
! 123: RRE_CGR = 0xb920,
! 124: RRE_CLGR = 0xb921,
! 125: RRE_DLGR = 0xb987,
! 126: RRE_DLR = 0xb997,
! 127: RRE_DSGFR = 0xb91d,
! 128: RRE_DSGR = 0xb90d,
! 129: RRE_LGBR = 0xb906,
! 130: RRE_LCGR = 0xb903,
! 131: RRE_LGFR = 0xb914,
! 132: RRE_LGHR = 0xb907,
! 133: RRE_LGR = 0xb904,
! 134: RRE_LLGCR = 0xb984,
! 135: RRE_LLGFR = 0xb916,
! 136: RRE_LLGHR = 0xb985,
! 137: RRE_LRVR = 0xb91f,
! 138: RRE_LRVGR = 0xb90f,
! 139: RRE_LTGR = 0xb902,
! 140: RRE_MSGR = 0xb90c,
! 141: RRE_MSR = 0xb252,
! 142: RRE_NGR = 0xb980,
! 143: RRE_OGR = 0xb981,
! 144: RRE_SGR = 0xb909,
! 145: RRE_XGR = 0xb982,
! 146:
! 147: RR_AR = 0x1a,
! 148: RR_BASR = 0x0d,
! 149: RR_BCR = 0x07,
! 150: RR_CLR = 0x15,
! 151: RR_CR = 0x19,
! 152: RR_DR = 0x1d,
! 153: RR_LCR = 0x13,
! 154: RR_LR = 0x18,
! 155: RR_LTR = 0x12,
! 156: RR_NR = 0x14,
! 157: RR_OR = 0x16,
! 158: RR_SR = 0x1b,
! 159: RR_XR = 0x17,
! 160:
! 161: RSY_RLL = 0xeb1d,
! 162: RSY_RLLG = 0xeb1c,
! 163: RSY_SLLG = 0xeb0d,
! 164: RSY_SRAG = 0xeb0a,
! 165: RSY_SRLG = 0xeb0c,
! 166:
! 167: RS_SLL = 0x89,
! 168: RS_SRA = 0x8a,
! 169: RS_SRL = 0x88,
! 170:
! 171: RXY_AG = 0xe308,
! 172: RXY_AY = 0xe35a,
! 173: RXY_CG = 0xe320,
! 174: RXY_CY = 0xe359,
! 175: RXY_LB = 0xe376,
! 176: RXY_LG = 0xe304,
! 177: RXY_LGB = 0xe377,
! 178: RXY_LGF = 0xe314,
! 179: RXY_LGH = 0xe315,
! 180: RXY_LHY = 0xe378,
! 181: RXY_LLGC = 0xe390,
! 182: RXY_LLGF = 0xe316,
! 183: RXY_LLGH = 0xe391,
! 184: RXY_LMG = 0xeb04,
! 185: RXY_LRV = 0xe31e,
! 186: RXY_LRVG = 0xe30f,
! 187: RXY_LRVH = 0xe31f,
! 188: RXY_LY = 0xe358,
! 189: RXY_STCY = 0xe372,
! 190: RXY_STG = 0xe324,
! 191: RXY_STHY = 0xe370,
! 192: RXY_STMG = 0xeb24,
! 193: RXY_STRV = 0xe33e,
! 194: RXY_STRVG = 0xe32f,
! 195: RXY_STRVH = 0xe33f,
! 196: RXY_STY = 0xe350,
! 197:
! 198: RX_A = 0x5a,
! 199: RX_C = 0x59,
! 200: RX_L = 0x58,
! 201: RX_LH = 0x48,
! 202: RX_ST = 0x50,
! 203: RX_STC = 0x42,
! 204: RX_STH = 0x40,
! 205: } S390Opcode;
! 206:
! 207: #define LD_SIGNED 0x04
! 208: #define LD_UINT8 0x00
! 209: #define LD_INT8 (LD_UINT8 | LD_SIGNED)
! 210: #define LD_UINT16 0x01
! 211: #define LD_INT16 (LD_UINT16 | LD_SIGNED)
! 212: #define LD_UINT32 0x02
! 213: #define LD_INT32 (LD_UINT32 | LD_SIGNED)
! 214: #define LD_UINT64 0x03
! 215: #define LD_INT64 (LD_UINT64 | LD_SIGNED)
! 216:
! 217: #ifndef NDEBUG
! 218: static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
! 219: "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
! 220: "%r8", "%r9", "%r10" "%r11" "%r12" "%r13" "%r14" "%r15"
! 221: };
! 222: #endif
! 223:
! 224: /* Since R6 is a potential argument register, choose it last of the
! 225: call-saved registers. Likewise prefer the call-clobbered registers
! 226: in reverse order to maximize the chance of avoiding the arguments. */
1.1 root 227: static const int tcg_target_reg_alloc_order[] = {
1.1.1.2 ! root 228: TCG_REG_R13,
! 229: TCG_REG_R12,
! 230: TCG_REG_R11,
! 231: TCG_REG_R10,
! 232: TCG_REG_R9,
! 233: TCG_REG_R8,
! 234: TCG_REG_R7,
! 235: TCG_REG_R6,
! 236: TCG_REG_R14,
! 237: TCG_REG_R0,
! 238: TCG_REG_R1,
! 239: TCG_REG_R5,
! 240: TCG_REG_R4,
! 241: TCG_REG_R3,
! 242: TCG_REG_R2,
1.1 root 243: };
244:
245: static const int tcg_target_call_iarg_regs[] = {
1.1.1.2 ! root 246: TCG_REG_R2,
! 247: TCG_REG_R3,
! 248: TCG_REG_R4,
! 249: TCG_REG_R5,
! 250: TCG_REG_R6,
1.1 root 251: };
252:
253: static const int tcg_target_call_oarg_regs[] = {
1.1.1.2 ! root 254: TCG_REG_R2,
! 255: TCG_REG_R3,
! 256: };
! 257:
! 258: #define S390_CC_EQ 8
! 259: #define S390_CC_LT 4
! 260: #define S390_CC_GT 2
! 261: #define S390_CC_OV 1
! 262: #define S390_CC_NE (S390_CC_LT | S390_CC_GT)
! 263: #define S390_CC_LE (S390_CC_LT | S390_CC_EQ)
! 264: #define S390_CC_GE (S390_CC_GT | S390_CC_EQ)
! 265: #define S390_CC_NEVER 0
! 266: #define S390_CC_ALWAYS 15
! 267:
! 268: /* Condition codes that result from a COMPARE and COMPARE LOGICAL. */
! 269: static const uint8_t tcg_cond_to_s390_cond[10] = {
! 270: [TCG_COND_EQ] = S390_CC_EQ,
! 271: [TCG_COND_NE] = S390_CC_NE,
! 272: [TCG_COND_LT] = S390_CC_LT,
! 273: [TCG_COND_LE] = S390_CC_LE,
! 274: [TCG_COND_GT] = S390_CC_GT,
! 275: [TCG_COND_GE] = S390_CC_GE,
! 276: [TCG_COND_LTU] = S390_CC_LT,
! 277: [TCG_COND_LEU] = S390_CC_LE,
! 278: [TCG_COND_GTU] = S390_CC_GT,
! 279: [TCG_COND_GEU] = S390_CC_GE,
! 280: };
! 281:
! 282: /* Condition codes that result from a LOAD AND TEST. Here, we have no
! 283: unsigned instruction variation, however since the test is vs zero we
! 284: can re-map the outcomes appropriately. */
! 285: static const uint8_t tcg_cond_to_ltr_cond[10] = {
! 286: [TCG_COND_EQ] = S390_CC_EQ,
! 287: [TCG_COND_NE] = S390_CC_NE,
! 288: [TCG_COND_LT] = S390_CC_LT,
! 289: [TCG_COND_LE] = S390_CC_LE,
! 290: [TCG_COND_GT] = S390_CC_GT,
! 291: [TCG_COND_GE] = S390_CC_GE,
! 292: [TCG_COND_LTU] = S390_CC_NEVER,
! 293: [TCG_COND_LEU] = S390_CC_EQ,
! 294: [TCG_COND_GTU] = S390_CC_NE,
! 295: [TCG_COND_GEU] = S390_CC_ALWAYS,
! 296: };
! 297:
! 298: #ifdef CONFIG_SOFTMMU
! 299:
! 300: #include "../../softmmu_defs.h"
! 301:
! 302: static void *qemu_ld_helpers[4] = {
! 303: __ldb_mmu,
! 304: __ldw_mmu,
! 305: __ldl_mmu,
! 306: __ldq_mmu,
! 307: };
! 308:
! 309: static void *qemu_st_helpers[4] = {
! 310: __stb_mmu,
! 311: __stw_mmu,
! 312: __stl_mmu,
! 313: __stq_mmu,
1.1 root 314: };
1.1.1.2 ! root 315: #endif
! 316:
! 317: static uint8_t *tb_ret_addr;
! 318:
! 319: /* A list of relevant facilities used by this translator. Some of these
! 320: are required for proper operation, and these are checked at startup. */
! 321:
! 322: #define FACILITY_ZARCH_ACTIVE (1ULL << (63 - 2))
! 323: #define FACILITY_LONG_DISP (1ULL << (63 - 18))
! 324: #define FACILITY_EXT_IMM (1ULL << (63 - 21))
! 325: #define FACILITY_GEN_INST_EXT (1ULL << (63 - 34))
! 326:
! 327: static uint64_t facilities;
1.1 root 328:
329: static void patch_reloc(uint8_t *code_ptr, int type,
1.1.1.2 ! root 330: tcg_target_long value, tcg_target_long addend)
1.1 root 331: {
1.1.1.2 ! root 332: tcg_target_long code_ptr_tl = (tcg_target_long)code_ptr;
! 333: tcg_target_long pcrel2;
! 334:
! 335: /* ??? Not the usual definition of "addend". */
! 336: pcrel2 = (value - (code_ptr_tl + addend)) >> 1;
! 337:
! 338: switch (type) {
! 339: case R_390_PC16DBL:
! 340: assert(pcrel2 == (int16_t)pcrel2);
! 341: *(int16_t *)code_ptr = pcrel2;
! 342: break;
! 343: case R_390_PC32DBL:
! 344: assert(pcrel2 == (int32_t)pcrel2);
! 345: *(int32_t *)code_ptr = pcrel2;
! 346: break;
! 347: default:
! 348: tcg_abort();
! 349: break;
! 350: }
1.1 root 351: }
352:
1.1.1.2 ! root 353: static int tcg_target_get_call_iarg_regs_count(int flags)
1.1 root 354: {
1.1.1.2 ! root 355: return sizeof(tcg_target_call_iarg_regs) / sizeof(int);
1.1 root 356: }
357:
358: /* parse target specific constraints */
359: static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
360: {
1.1.1.2 ! root 361: const char *ct_str = *pct_str;
! 362:
! 363: switch (ct_str[0]) {
! 364: case 'r': /* all registers */
! 365: ct->ct |= TCG_CT_REG;
! 366: tcg_regset_set32(ct->u.regs, 0, 0xffff);
! 367: break;
! 368: case 'R': /* not R0 */
! 369: ct->ct |= TCG_CT_REG;
! 370: tcg_regset_set32(ct->u.regs, 0, 0xffff);
! 371: tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
! 372: break;
! 373: case 'L': /* qemu_ld/st constraint */
! 374: ct->ct |= TCG_CT_REG;
! 375: tcg_regset_set32(ct->u.regs, 0, 0xffff);
! 376: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R2);
! 377: tcg_regset_reset_reg (ct->u.regs, TCG_REG_R3);
! 378: break;
! 379: case 'a': /* force R2 for division */
! 380: ct->ct |= TCG_CT_REG;
! 381: tcg_regset_clear(ct->u.regs);
! 382: tcg_regset_set_reg(ct->u.regs, TCG_REG_R2);
! 383: break;
! 384: case 'b': /* force R3 for division */
! 385: ct->ct |= TCG_CT_REG;
! 386: tcg_regset_clear(ct->u.regs);
! 387: tcg_regset_set_reg(ct->u.regs, TCG_REG_R3);
! 388: break;
! 389: case 'N': /* force immediate negate */
! 390: ct->ct |= TCG_CT_CONST_NEG;
! 391: break;
! 392: case 'W': /* force 32-bit ("word") immediate */
! 393: ct->ct |= TCG_CT_CONST_32;
! 394: break;
! 395: case 'I':
! 396: ct->ct |= TCG_CT_CONST_ADDI;
! 397: break;
! 398: case 'K':
! 399: ct->ct |= TCG_CT_CONST_MULI;
! 400: break;
! 401: case 'A':
! 402: ct->ct |= TCG_CT_CONST_ANDI;
! 403: break;
! 404: case 'O':
! 405: ct->ct |= TCG_CT_CONST_ORI;
! 406: break;
! 407: case 'X':
! 408: ct->ct |= TCG_CT_CONST_XORI;
! 409: break;
! 410: case 'C':
! 411: ct->ct |= TCG_CT_CONST_CMPI;
! 412: break;
! 413: default:
! 414: return -1;
! 415: }
! 416: ct_str++;
! 417: *pct_str = ct_str;
! 418:
1.1 root 419: return 0;
420: }
421:
1.1.1.2 ! root 422: /* Immediates to be used with logical AND. This is an optimization only,
! 423: since a full 64-bit immediate AND can always be performed with 4 sequential
! 424: NI[LH][LH] instructions. What we're looking for is immediates that we
! 425: can load efficiently, and the immediate load plus the reg-reg AND is
! 426: smaller than the sequential NI's. */
! 427:
! 428: static int tcg_match_andi(int ct, tcg_target_ulong val)
! 429: {
! 430: int i;
! 431:
! 432: if (facilities & FACILITY_EXT_IMM) {
! 433: if (ct & TCG_CT_CONST_32) {
! 434: /* All 32-bit ANDs can be performed with 1 48-bit insn. */
! 435: return 1;
! 436: }
! 437:
! 438: /* Zero-extensions. */
! 439: if (val == 0xff || val == 0xffff || val == 0xffffffff) {
! 440: return 1;
! 441: }
! 442: } else {
! 443: if (ct & TCG_CT_CONST_32) {
! 444: val = (uint32_t)val;
! 445: } else if (val == 0xffffffff) {
! 446: return 1;
! 447: }
! 448: }
! 449:
! 450: /* Try all 32-bit insns that can perform it in one go. */
! 451: for (i = 0; i < 4; i++) {
! 452: tcg_target_ulong mask = ~(0xffffull << i*16);
! 453: if ((val & mask) == mask) {
! 454: return 1;
! 455: }
! 456: }
! 457:
! 458: /* Look for 16-bit values performing the mask. These are better
! 459: to load with LLI[LH][LH]. */
! 460: for (i = 0; i < 4; i++) {
! 461: tcg_target_ulong mask = 0xffffull << i*16;
! 462: if ((val & mask) == val) {
! 463: return 0;
! 464: }
! 465: }
! 466:
! 467: /* Look for 32-bit values performing the 64-bit mask. These
! 468: are better to load with LLI[LH]F, or if extended immediates
! 469: not available, with a pair of LLI insns. */
! 470: if ((ct & TCG_CT_CONST_32) == 0) {
! 471: if (val <= 0xffffffff || (val & 0xffffffff) == 0) {
! 472: return 0;
! 473: }
! 474: }
! 475:
! 476: return 1;
! 477: }
! 478:
! 479: /* Immediates to be used with logical OR. This is an optimization only,
! 480: since a full 64-bit immediate OR can always be performed with 4 sequential
! 481: OI[LH][LH] instructions. What we're looking for is immediates that we
! 482: can load efficiently, and the immediate load plus the reg-reg OR is
! 483: smaller than the sequential OI's. */
! 484:
! 485: static int tcg_match_ori(int ct, tcg_target_long val)
! 486: {
! 487: if (facilities & FACILITY_EXT_IMM) {
! 488: if (ct & TCG_CT_CONST_32) {
! 489: /* All 32-bit ORs can be performed with 1 48-bit insn. */
! 490: return 1;
! 491: }
! 492: }
! 493:
! 494: /* Look for negative values. These are best to load with LGHI. */
! 495: if (val < 0) {
! 496: if (val == (int16_t)val) {
! 497: return 0;
! 498: }
! 499: if (facilities & FACILITY_EXT_IMM) {
! 500: if (val == (int32_t)val) {
! 501: return 0;
! 502: }
! 503: }
! 504: }
! 505:
! 506: return 1;
! 507: }
! 508:
! 509: /* Immediates to be used with logical XOR. This is almost, but not quite,
! 510: only an optimization. XOR with immediate is only supported with the
! 511: extended-immediate facility. That said, there are a few patterns for
! 512: which it is better to load the value into a register first. */
! 513:
! 514: static int tcg_match_xori(int ct, tcg_target_long val)
! 515: {
! 516: if ((facilities & FACILITY_EXT_IMM) == 0) {
! 517: return 0;
! 518: }
! 519:
! 520: if (ct & TCG_CT_CONST_32) {
! 521: /* All 32-bit XORs can be performed with 1 48-bit insn. */
! 522: return 1;
! 523: }
! 524:
! 525: /* Look for negative values. These are best to load with LGHI. */
! 526: if (val < 0 && val == (int32_t)val) {
! 527: return 0;
! 528: }
! 529:
! 530: return 1;
! 531: }
! 532:
! 533: /* Imediates to be used with comparisons. */
! 534:
! 535: static int tcg_match_cmpi(int ct, tcg_target_long val)
! 536: {
! 537: if (facilities & FACILITY_EXT_IMM) {
! 538: /* The COMPARE IMMEDIATE instruction is available. */
! 539: if (ct & TCG_CT_CONST_32) {
! 540: /* We have a 32-bit immediate and can compare against anything. */
! 541: return 1;
! 542: } else {
! 543: /* ??? We have no insight here into whether the comparison is
! 544: signed or unsigned. The COMPARE IMMEDIATE insn uses a 32-bit
! 545: signed immediate, and the COMPARE LOGICAL IMMEDIATE insn uses
! 546: a 32-bit unsigned immediate. If we were to use the (semi)
! 547: obvious "val == (int32_t)val" we would be enabling unsigned
! 548: comparisons vs very large numbers. The only solution is to
! 549: take the intersection of the ranges. */
! 550: /* ??? Another possible solution is to simply lie and allow all
! 551: constants here and force the out-of-range values into a temp
! 552: register in tgen_cmp when we have knowledge of the actual
! 553: comparison code in use. */
! 554: return val >= 0 && val <= 0x7fffffff;
! 555: }
! 556: } else {
! 557: /* Only the LOAD AND TEST instruction is available. */
! 558: return val == 0;
! 559: }
! 560: }
! 561:
1.1 root 562: /* Test if a constant matches the constraint. */
1.1.1.2 ! root 563: static int tcg_target_const_match(tcg_target_long val,
! 564: const TCGArgConstraint *arg_ct)
1.1 root 565: {
1.1.1.2 ! root 566: int ct = arg_ct->ct;
! 567:
! 568: if (ct & TCG_CT_CONST) {
! 569: return 1;
! 570: }
! 571:
! 572: /* Handle the modifiers. */
! 573: if (ct & TCG_CT_CONST_NEG) {
! 574: val = -val;
! 575: }
! 576: if (ct & TCG_CT_CONST_32) {
! 577: val = (int32_t)val;
! 578: }
! 579:
! 580: /* The following are mutually exclusive. */
! 581: if (ct & TCG_CT_CONST_ADDI) {
! 582: /* Immediates that may be used with add. If we have the
! 583: extended-immediates facility then we have ADD IMMEDIATE
! 584: with signed and unsigned 32-bit, otherwise we have only
! 585: ADD HALFWORD IMMEDIATE with a signed 16-bit. */
! 586: if (facilities & FACILITY_EXT_IMM) {
! 587: return val == (int32_t)val || val == (uint32_t)val;
! 588: } else {
! 589: return val == (int16_t)val;
! 590: }
! 591: } else if (ct & TCG_CT_CONST_MULI) {
! 592: /* Immediates that may be used with multiply. If we have the
! 593: general-instruction-extensions, then we have MULTIPLY SINGLE
! 594: IMMEDIATE with a signed 32-bit, otherwise we have only
! 595: MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit. */
! 596: if (facilities & FACILITY_GEN_INST_EXT) {
! 597: return val == (int32_t)val;
! 598: } else {
! 599: return val == (int16_t)val;
! 600: }
! 601: } else if (ct & TCG_CT_CONST_ANDI) {
! 602: return tcg_match_andi(ct, val);
! 603: } else if (ct & TCG_CT_CONST_ORI) {
! 604: return tcg_match_ori(ct, val);
! 605: } else if (ct & TCG_CT_CONST_XORI) {
! 606: return tcg_match_xori(ct, val);
! 607: } else if (ct & TCG_CT_CONST_CMPI) {
! 608: return tcg_match_cmpi(ct, val);
! 609: }
! 610:
1.1 root 611: return 0;
612: }
613:
1.1.1.2 ! root 614: /* Emit instructions according to the given instruction format. */
! 615:
! 616: static void tcg_out_insn_RR(TCGContext *s, S390Opcode op, TCGReg r1, TCGReg r2)
! 617: {
! 618: tcg_out16(s, (op << 8) | (r1 << 4) | r2);
! 619: }
! 620:
! 621: static void tcg_out_insn_RRE(TCGContext *s, S390Opcode op,
! 622: TCGReg r1, TCGReg r2)
! 623: {
! 624: tcg_out32(s, (op << 16) | (r1 << 4) | r2);
! 625: }
! 626:
! 627: static void tcg_out_insn_RI(TCGContext *s, S390Opcode op, TCGReg r1, int i2)
! 628: {
! 629: tcg_out32(s, (op << 16) | (r1 << 20) | (i2 & 0xffff));
! 630: }
! 631:
! 632: static void tcg_out_insn_RIL(TCGContext *s, S390Opcode op, TCGReg r1, int i2)
! 633: {
! 634: tcg_out16(s, op | (r1 << 4));
! 635: tcg_out32(s, i2);
! 636: }
! 637:
! 638: static void tcg_out_insn_RS(TCGContext *s, S390Opcode op, TCGReg r1,
! 639: TCGReg b2, TCGReg r3, int disp)
! 640: {
! 641: tcg_out32(s, (op << 24) | (r1 << 20) | (r3 << 16) | (b2 << 12)
! 642: | (disp & 0xfff));
! 643: }
! 644:
! 645: static void tcg_out_insn_RSY(TCGContext *s, S390Opcode op, TCGReg r1,
! 646: TCGReg b2, TCGReg r3, int disp)
! 647: {
! 648: tcg_out16(s, (op & 0xff00) | (r1 << 4) | r3);
! 649: tcg_out32(s, (op & 0xff) | (b2 << 28)
! 650: | ((disp & 0xfff) << 16) | ((disp & 0xff000) >> 4));
! 651: }
! 652:
! 653: #define tcg_out_insn_RX tcg_out_insn_RS
! 654: #define tcg_out_insn_RXY tcg_out_insn_RSY
! 655:
! 656: /* Emit an opcode with "type-checking" of the format. */
! 657: #define tcg_out_insn(S, FMT, OP, ...) \
! 658: glue(tcg_out_insn_,FMT)(S, glue(glue(FMT,_),OP), ## __VA_ARGS__)
! 659:
! 660:
! 661: /* emit 64-bit shifts */
! 662: static void tcg_out_sh64(TCGContext* s, S390Opcode op, TCGReg dest,
! 663: TCGReg src, TCGReg sh_reg, int sh_imm)
! 664: {
! 665: tcg_out_insn_RSY(s, op, dest, sh_reg, src, sh_imm);
! 666: }
! 667:
! 668: /* emit 32-bit shifts */
! 669: static void tcg_out_sh32(TCGContext* s, S390Opcode op, TCGReg dest,
! 670: TCGReg sh_reg, int sh_imm)
! 671: {
! 672: tcg_out_insn_RS(s, op, dest, sh_reg, 0, sh_imm);
! 673: }
! 674:
! 675: static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg dst, TCGReg src)
! 676: {
! 677: if (src != dst) {
! 678: if (type == TCG_TYPE_I32) {
! 679: tcg_out_insn(s, RR, LR, dst, src);
! 680: } else {
! 681: tcg_out_insn(s, RRE, LGR, dst, src);
! 682: }
! 683: }
! 684: }
! 685:
1.1 root 686: /* load a register with an immediate value */
1.1.1.2 ! root 687: static void tcg_out_movi(TCGContext *s, TCGType type,
! 688: TCGReg ret, tcg_target_long sval)
1.1 root 689: {
1.1.1.2 ! root 690: static const S390Opcode lli_insns[4] = {
! 691: RI_LLILL, RI_LLILH, RI_LLIHL, RI_LLIHH
! 692: };
! 693:
! 694: tcg_target_ulong uval = sval;
! 695: int i;
! 696:
! 697: if (type == TCG_TYPE_I32) {
! 698: uval = (uint32_t)sval;
! 699: sval = (int32_t)sval;
! 700: }
! 701:
! 702: /* Try all 32-bit insns that can load it in one go. */
! 703: if (sval >= -0x8000 && sval < 0x8000) {
! 704: tcg_out_insn(s, RI, LGHI, ret, sval);
! 705: return;
! 706: }
! 707:
! 708: for (i = 0; i < 4; i++) {
! 709: tcg_target_long mask = 0xffffull << i*16;
! 710: if ((uval & mask) == uval) {
! 711: tcg_out_insn_RI(s, lli_insns[i], ret, uval >> i*16);
! 712: return;
! 713: }
! 714: }
! 715:
! 716: /* Try all 48-bit insns that can load it in one go. */
! 717: if (facilities & FACILITY_EXT_IMM) {
! 718: if (sval == (int32_t)sval) {
! 719: tcg_out_insn(s, RIL, LGFI, ret, sval);
! 720: return;
! 721: }
! 722: if (uval <= 0xffffffff) {
! 723: tcg_out_insn(s, RIL, LLILF, ret, uval);
! 724: return;
! 725: }
! 726: if ((uval & 0xffffffff) == 0) {
! 727: tcg_out_insn(s, RIL, LLIHF, ret, uval >> 31 >> 1);
! 728: return;
! 729: }
! 730: }
! 731:
! 732: /* Try for PC-relative address load. */
! 733: if ((sval & 1) == 0) {
! 734: intptr_t off = (sval - (intptr_t)s->code_ptr) >> 1;
! 735: if (off == (int32_t)off) {
! 736: tcg_out_insn(s, RIL, LARL, ret, off);
! 737: return;
! 738: }
! 739: }
! 740:
! 741: /* If extended immediates are not present, then we may have to issue
! 742: several instructions to load the low 32 bits. */
! 743: if (!(facilities & FACILITY_EXT_IMM)) {
! 744: /* A 32-bit unsigned value can be loaded in 2 insns. And given
! 745: that the lli_insns loop above did not succeed, we know that
! 746: both insns are required. */
! 747: if (uval <= 0xffffffff) {
! 748: tcg_out_insn(s, RI, LLILL, ret, uval);
! 749: tcg_out_insn(s, RI, IILH, ret, uval >> 16);
! 750: return;
! 751: }
! 752:
! 753: /* If all high bits are set, the value can be loaded in 2 or 3 insns.
! 754: We first want to make sure that all the high bits get set. With
! 755: luck the low 16-bits can be considered negative to perform that for
! 756: free, otherwise we load an explicit -1. */
! 757: if (sval >> 31 >> 1 == -1) {
! 758: if (uval & 0x8000) {
! 759: tcg_out_insn(s, RI, LGHI, ret, uval);
! 760: } else {
! 761: tcg_out_insn(s, RI, LGHI, ret, -1);
! 762: tcg_out_insn(s, RI, IILL, ret, uval);
! 763: }
! 764: tcg_out_insn(s, RI, IILH, ret, uval >> 16);
! 765: return;
! 766: }
! 767: }
! 768:
! 769: /* If we get here, both the high and low parts have non-zero bits. */
! 770:
! 771: /* Recurse to load the lower 32-bits. */
! 772: tcg_out_movi(s, TCG_TYPE_I32, ret, sval);
! 773:
! 774: /* Insert data into the high 32-bits. */
! 775: uval = uval >> 31 >> 1;
! 776: if (facilities & FACILITY_EXT_IMM) {
! 777: if (uval < 0x10000) {
! 778: tcg_out_insn(s, RI, IIHL, ret, uval);
! 779: } else if ((uval & 0xffff) == 0) {
! 780: tcg_out_insn(s, RI, IIHH, ret, uval >> 16);
! 781: } else {
! 782: tcg_out_insn(s, RIL, IIHF, ret, uval);
! 783: }
! 784: } else {
! 785: if (uval & 0xffff) {
! 786: tcg_out_insn(s, RI, IIHL, ret, uval);
! 787: }
! 788: if (uval & 0xffff0000) {
! 789: tcg_out_insn(s, RI, IIHH, ret, uval >> 16);
! 790: }
! 791: }
! 792: }
! 793:
! 794:
! 795: /* Emit a load/store type instruction. Inputs are:
! 796: DATA: The register to be loaded or stored.
! 797: BASE+OFS: The effective address.
! 798: OPC_RX: If the operation has an RX format opcode (e.g. STC), otherwise 0.
! 799: OPC_RXY: The RXY format opcode for the operation (e.g. STCY). */
! 800:
! 801: static void tcg_out_mem(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy,
! 802: TCGReg data, TCGReg base, TCGReg index,
! 803: tcg_target_long ofs)
! 804: {
! 805: if (ofs < -0x80000 || ofs >= 0x80000) {
! 806: /* Combine the low 16 bits of the offset with the actual load insn;
! 807: the high 48 bits must come from an immediate load. */
! 808: tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs & ~0xffff);
! 809: ofs &= 0xffff;
! 810:
! 811: /* If we were already given an index register, add it in. */
! 812: if (index != TCG_REG_NONE) {
! 813: tcg_out_insn(s, RRE, AGR, TCG_TMP0, index);
! 814: }
! 815: index = TCG_TMP0;
! 816: }
! 817:
! 818: if (opc_rx && ofs >= 0 && ofs < 0x1000) {
! 819: tcg_out_insn_RX(s, opc_rx, data, base, index, ofs);
! 820: } else {
! 821: tcg_out_insn_RXY(s, opc_rxy, data, base, index, ofs);
! 822: }
1.1 root 823: }
824:
1.1.1.2 ! root 825:
1.1 root 826: /* load data without address translation or endianness conversion */
1.1.1.2 ! root 827: static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data,
! 828: TCGReg base, tcg_target_long ofs)
1.1 root 829: {
1.1.1.2 ! root 830: if (type == TCG_TYPE_I32) {
! 831: tcg_out_mem(s, RX_L, RXY_LY, data, base, TCG_REG_NONE, ofs);
! 832: } else {
! 833: tcg_out_mem(s, 0, RXY_LG, data, base, TCG_REG_NONE, ofs);
! 834: }
1.1 root 835: }
836:
1.1.1.2 ! root 837: static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
! 838: TCGReg base, tcg_target_long ofs)
1.1 root 839: {
1.1.1.2 ! root 840: if (type == TCG_TYPE_I32) {
! 841: tcg_out_mem(s, RX_ST, RXY_STY, data, base, TCG_REG_NONE, ofs);
! 842: } else {
! 843: tcg_out_mem(s, 0, RXY_STG, data, base, TCG_REG_NONE, ofs);
! 844: }
! 845: }
! 846:
! 847: /* load data from an absolute host address */
! 848: static void tcg_out_ld_abs(TCGContext *s, TCGType type, TCGReg dest, void *abs)
! 849: {
! 850: tcg_target_long addr = (tcg_target_long)abs;
! 851:
! 852: if (facilities & FACILITY_GEN_INST_EXT) {
! 853: tcg_target_long disp = (addr - (tcg_target_long)s->code_ptr) >> 1;
! 854: if (disp == (int32_t)disp) {
! 855: if (type == TCG_TYPE_I32) {
! 856: tcg_out_insn(s, RIL, LRL, dest, disp);
! 857: } else {
! 858: tcg_out_insn(s, RIL, LGRL, dest, disp);
! 859: }
! 860: return;
! 861: }
! 862: }
! 863:
! 864: tcg_out_movi(s, TCG_TYPE_PTR, dest, addr & ~0xffff);
! 865: tcg_out_ld(s, type, dest, dest, addr & 0xffff);
! 866: }
! 867:
! 868: static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
! 869: {
! 870: if (facilities & FACILITY_EXT_IMM) {
! 871: tcg_out_insn(s, RRE, LGBR, dest, src);
! 872: return;
! 873: }
! 874:
! 875: if (type == TCG_TYPE_I32) {
! 876: if (dest == src) {
! 877: tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 24);
! 878: } else {
! 879: tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 24);
! 880: }
! 881: tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 24);
! 882: } else {
! 883: tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 56);
! 884: tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 56);
! 885: }
! 886: }
! 887:
! 888: static void tgen_ext8u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
! 889: {
! 890: if (facilities & FACILITY_EXT_IMM) {
! 891: tcg_out_insn(s, RRE, LLGCR, dest, src);
! 892: return;
! 893: }
! 894:
! 895: if (dest == src) {
! 896: tcg_out_movi(s, type, TCG_TMP0, 0xff);
! 897: src = TCG_TMP0;
! 898: } else {
! 899: tcg_out_movi(s, type, dest, 0xff);
! 900: }
! 901: if (type == TCG_TYPE_I32) {
! 902: tcg_out_insn(s, RR, NR, dest, src);
! 903: } else {
! 904: tcg_out_insn(s, RRE, NGR, dest, src);
! 905: }
! 906: }
! 907:
! 908: static void tgen_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
! 909: {
! 910: if (facilities & FACILITY_EXT_IMM) {
! 911: tcg_out_insn(s, RRE, LGHR, dest, src);
! 912: return;
! 913: }
! 914:
! 915: if (type == TCG_TYPE_I32) {
! 916: if (dest == src) {
! 917: tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 16);
! 918: } else {
! 919: tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 16);
! 920: }
! 921: tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 16);
! 922: } else {
! 923: tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 48);
! 924: tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 48);
! 925: }
! 926: }
! 927:
! 928: static void tgen_ext16u(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
! 929: {
! 930: if (facilities & FACILITY_EXT_IMM) {
! 931: tcg_out_insn(s, RRE, LLGHR, dest, src);
! 932: return;
! 933: }
! 934:
! 935: if (dest == src) {
! 936: tcg_out_movi(s, type, TCG_TMP0, 0xffff);
! 937: src = TCG_TMP0;
! 938: } else {
! 939: tcg_out_movi(s, type, dest, 0xffff);
! 940: }
! 941: if (type == TCG_TYPE_I32) {
! 942: tcg_out_insn(s, RR, NR, dest, src);
! 943: } else {
! 944: tcg_out_insn(s, RRE, NGR, dest, src);
! 945: }
! 946: }
! 947:
! 948: static inline void tgen_ext32s(TCGContext *s, TCGReg dest, TCGReg src)
! 949: {
! 950: tcg_out_insn(s, RRE, LGFR, dest, src);
! 951: }
! 952:
! 953: static inline void tgen_ext32u(TCGContext *s, TCGReg dest, TCGReg src)
! 954: {
! 955: tcg_out_insn(s, RRE, LLGFR, dest, src);
! 956: }
! 957:
! 958: static inline void tgen32_addi(TCGContext *s, TCGReg dest, int32_t val)
! 959: {
! 960: if (val == (int16_t)val) {
! 961: tcg_out_insn(s, RI, AHI, dest, val);
! 962: } else {
! 963: tcg_out_insn(s, RIL, AFI, dest, val);
! 964: }
! 965: }
! 966:
! 967: static inline void tgen64_addi(TCGContext *s, TCGReg dest, int64_t val)
! 968: {
! 969: if (val == (int16_t)val) {
! 970: tcg_out_insn(s, RI, AGHI, dest, val);
! 971: } else if (val == (int32_t)val) {
! 972: tcg_out_insn(s, RIL, AGFI, dest, val);
! 973: } else if (val == (uint32_t)val) {
! 974: tcg_out_insn(s, RIL, ALGFI, dest, val);
! 975: } else {
! 976: tcg_abort();
! 977: }
! 978:
! 979: }
! 980:
! 981: static void tgen64_andi(TCGContext *s, TCGReg dest, tcg_target_ulong val)
! 982: {
! 983: static const S390Opcode ni_insns[4] = {
! 984: RI_NILL, RI_NILH, RI_NIHL, RI_NIHH
! 985: };
! 986: static const S390Opcode nif_insns[2] = {
! 987: RIL_NILF, RIL_NIHF
! 988: };
! 989:
! 990: int i;
! 991:
! 992: /* Look for no-op. */
! 993: if (val == -1) {
! 994: return;
! 995: }
! 996:
! 997: /* Look for the zero-extensions. */
! 998: if (val == 0xffffffff) {
! 999: tgen_ext32u(s, dest, dest);
! 1000: return;
! 1001: }
! 1002:
! 1003: if (facilities & FACILITY_EXT_IMM) {
! 1004: if (val == 0xff) {
! 1005: tgen_ext8u(s, TCG_TYPE_I64, dest, dest);
! 1006: return;
! 1007: }
! 1008: if (val == 0xffff) {
! 1009: tgen_ext16u(s, TCG_TYPE_I64, dest, dest);
! 1010: return;
! 1011: }
! 1012:
! 1013: /* Try all 32-bit insns that can perform it in one go. */
! 1014: for (i = 0; i < 4; i++) {
! 1015: tcg_target_ulong mask = ~(0xffffull << i*16);
! 1016: if ((val & mask) == mask) {
! 1017: tcg_out_insn_RI(s, ni_insns[i], dest, val >> i*16);
! 1018: return;
! 1019: }
! 1020: }
! 1021:
! 1022: /* Try all 48-bit insns that can perform it in one go. */
! 1023: if (facilities & FACILITY_EXT_IMM) {
! 1024: for (i = 0; i < 2; i++) {
! 1025: tcg_target_ulong mask = ~(0xffffffffull << i*32);
! 1026: if ((val & mask) == mask) {
! 1027: tcg_out_insn_RIL(s, nif_insns[i], dest, val >> i*32);
! 1028: return;
! 1029: }
! 1030: }
! 1031: }
! 1032:
! 1033: /* Perform the AND via sequential modifications to the high and low
! 1034: parts. Do this via recursion to handle 16-bit vs 32-bit masks in
! 1035: each half. */
! 1036: tgen64_andi(s, dest, val | 0xffffffff00000000ull);
! 1037: tgen64_andi(s, dest, val | 0x00000000ffffffffull);
! 1038: } else {
! 1039: /* With no extended-immediate facility, just emit the sequence. */
! 1040: for (i = 0; i < 4; i++) {
! 1041: tcg_target_ulong mask = 0xffffull << i*16;
! 1042: if ((val & mask) != mask) {
! 1043: tcg_out_insn_RI(s, ni_insns[i], dest, val >> i*16);
! 1044: }
! 1045: }
! 1046: }
! 1047: }
! 1048:
! 1049: static void tgen64_ori(TCGContext *s, TCGReg dest, tcg_target_ulong val)
! 1050: {
! 1051: static const S390Opcode oi_insns[4] = {
! 1052: RI_OILL, RI_OILH, RI_OIHL, RI_OIHH
! 1053: };
! 1054: static const S390Opcode nif_insns[2] = {
! 1055: RIL_OILF, RIL_OIHF
! 1056: };
! 1057:
! 1058: int i;
! 1059:
! 1060: /* Look for no-op. */
! 1061: if (val == 0) {
! 1062: return;
! 1063: }
! 1064:
! 1065: if (facilities & FACILITY_EXT_IMM) {
! 1066: /* Try all 32-bit insns that can perform it in one go. */
! 1067: for (i = 0; i < 4; i++) {
! 1068: tcg_target_ulong mask = (0xffffull << i*16);
! 1069: if ((val & mask) != 0 && (val & ~mask) == 0) {
! 1070: tcg_out_insn_RI(s, oi_insns[i], dest, val >> i*16);
! 1071: return;
! 1072: }
! 1073: }
! 1074:
! 1075: /* Try all 48-bit insns that can perform it in one go. */
! 1076: for (i = 0; i < 2; i++) {
! 1077: tcg_target_ulong mask = (0xffffffffull << i*32);
! 1078: if ((val & mask) != 0 && (val & ~mask) == 0) {
! 1079: tcg_out_insn_RIL(s, nif_insns[i], dest, val >> i*32);
! 1080: return;
! 1081: }
! 1082: }
! 1083:
! 1084: /* Perform the OR via sequential modifications to the high and
! 1085: low parts. Do this via recursion to handle 16-bit vs 32-bit
! 1086: masks in each half. */
! 1087: tgen64_ori(s, dest, val & 0x00000000ffffffffull);
! 1088: tgen64_ori(s, dest, val & 0xffffffff00000000ull);
! 1089: } else {
! 1090: /* With no extended-immediate facility, we don't need to be so
! 1091: clever. Just iterate over the insns and mask in the constant. */
! 1092: for (i = 0; i < 4; i++) {
! 1093: tcg_target_ulong mask = (0xffffull << i*16);
! 1094: if ((val & mask) != 0) {
! 1095: tcg_out_insn_RI(s, oi_insns[i], dest, val >> i*16);
! 1096: }
! 1097: }
! 1098: }
! 1099: }
! 1100:
! 1101: static void tgen64_xori(TCGContext *s, TCGReg dest, tcg_target_ulong val)
! 1102: {
! 1103: /* Perform the xor by parts. */
! 1104: if (val & 0xffffffff) {
! 1105: tcg_out_insn(s, RIL, XILF, dest, val);
! 1106: }
! 1107: if (val > 0xffffffff) {
! 1108: tcg_out_insn(s, RIL, XIHF, dest, val >> 31 >> 1);
! 1109: }
1.1 root 1110: }
1111:
1.1.1.2 ! root 1112: static int tgen_cmp(TCGContext *s, TCGType type, TCGCond c, TCGReg r1,
! 1113: TCGArg c2, int c2const)
! 1114: {
! 1115: bool is_unsigned = (c > TCG_COND_GT);
! 1116: if (c2const) {
! 1117: if (c2 == 0) {
! 1118: if (type == TCG_TYPE_I32) {
! 1119: tcg_out_insn(s, RR, LTR, r1, r1);
! 1120: } else {
! 1121: tcg_out_insn(s, RRE, LTGR, r1, r1);
! 1122: }
! 1123: return tcg_cond_to_ltr_cond[c];
! 1124: } else {
! 1125: if (is_unsigned) {
! 1126: if (type == TCG_TYPE_I32) {
! 1127: tcg_out_insn(s, RIL, CLFI, r1, c2);
! 1128: } else {
! 1129: tcg_out_insn(s, RIL, CLGFI, r1, c2);
! 1130: }
! 1131: } else {
! 1132: if (type == TCG_TYPE_I32) {
! 1133: tcg_out_insn(s, RIL, CFI, r1, c2);
! 1134: } else {
! 1135: tcg_out_insn(s, RIL, CGFI, r1, c2);
! 1136: }
! 1137: }
! 1138: }
! 1139: } else {
! 1140: if (is_unsigned) {
! 1141: if (type == TCG_TYPE_I32) {
! 1142: tcg_out_insn(s, RR, CLR, r1, c2);
! 1143: } else {
! 1144: tcg_out_insn(s, RRE, CLGR, r1, c2);
! 1145: }
! 1146: } else {
! 1147: if (type == TCG_TYPE_I32) {
! 1148: tcg_out_insn(s, RR, CR, r1, c2);
! 1149: } else {
! 1150: tcg_out_insn(s, RRE, CGR, r1, c2);
! 1151: }
! 1152: }
! 1153: }
! 1154: return tcg_cond_to_s390_cond[c];
! 1155: }
! 1156:
! 1157: static void tgen_setcond(TCGContext *s, TCGType type, TCGCond c,
! 1158: TCGReg dest, TCGReg r1, TCGArg c2, int c2const)
! 1159: {
! 1160: int cc = tgen_cmp(s, type, c, r1, c2, c2const);
! 1161:
! 1162: /* Emit: r1 = 1; if (cc) goto over; r1 = 0; over: */
! 1163: tcg_out_movi(s, type, dest, 1);
! 1164: tcg_out_insn(s, RI, BRC, cc, (4 + 4) >> 1);
! 1165: tcg_out_movi(s, type, dest, 0);
! 1166: }
! 1167:
! 1168: static void tgen_gotoi(TCGContext *s, int cc, tcg_target_long dest)
! 1169: {
! 1170: tcg_target_long off = (dest - (tcg_target_long)s->code_ptr) >> 1;
! 1171: if (off > -0x8000 && off < 0x7fff) {
! 1172: tcg_out_insn(s, RI, BRC, cc, off);
! 1173: } else if (off == (int32_t)off) {
! 1174: tcg_out_insn(s, RIL, BRCL, cc, off);
! 1175: } else {
! 1176: tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, dest);
! 1177: tcg_out_insn(s, RR, BCR, cc, TCG_TMP0);
! 1178: }
! 1179: }
! 1180:
! 1181: static void tgen_branch(TCGContext *s, int cc, int labelno)
! 1182: {
! 1183: TCGLabel* l = &s->labels[labelno];
! 1184: if (l->has_value) {
! 1185: tgen_gotoi(s, cc, l->u.value);
! 1186: } else if (USE_LONG_BRANCHES) {
! 1187: tcg_out16(s, RIL_BRCL | (cc << 4));
! 1188: tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, labelno, -2);
! 1189: s->code_ptr += 4;
! 1190: } else {
! 1191: tcg_out16(s, RI_BRC | (cc << 4));
! 1192: tcg_out_reloc(s, s->code_ptr, R_390_PC16DBL, labelno, -2);
! 1193: s->code_ptr += 2;
! 1194: }
! 1195: }
! 1196:
! 1197: static void tgen_compare_branch(TCGContext *s, S390Opcode opc, int cc,
! 1198: TCGReg r1, TCGReg r2, int labelno)
! 1199: {
! 1200: TCGLabel* l = &s->labels[labelno];
! 1201: tcg_target_long off;
! 1202:
! 1203: if (l->has_value) {
! 1204: off = (l->u.value - (tcg_target_long)s->code_ptr) >> 1;
! 1205: } else {
! 1206: /* We need to keep the offset unchanged for retranslation. */
! 1207: off = ((int16_t *)s->code_ptr)[1];
! 1208: tcg_out_reloc(s, s->code_ptr + 2, R_390_PC16DBL, labelno, -2);
! 1209: }
! 1210:
! 1211: tcg_out16(s, (opc & 0xff00) | (r1 << 4) | r2);
! 1212: tcg_out16(s, off);
! 1213: tcg_out16(s, cc << 12 | (opc & 0xff));
! 1214: }
! 1215:
! 1216: static void tgen_compare_imm_branch(TCGContext *s, S390Opcode opc, int cc,
! 1217: TCGReg r1, int i2, int labelno)
! 1218: {
! 1219: TCGLabel* l = &s->labels[labelno];
! 1220: tcg_target_long off;
! 1221:
! 1222: if (l->has_value) {
! 1223: off = (l->u.value - (tcg_target_long)s->code_ptr) >> 1;
! 1224: } else {
! 1225: /* We need to keep the offset unchanged for retranslation. */
! 1226: off = ((int16_t *)s->code_ptr)[1];
! 1227: tcg_out_reloc(s, s->code_ptr + 2, R_390_PC16DBL, labelno, -2);
! 1228: }
! 1229:
! 1230: tcg_out16(s, (opc & 0xff00) | (r1 << 4) | cc);
! 1231: tcg_out16(s, off);
! 1232: tcg_out16(s, (i2 << 8) | (opc & 0xff));
! 1233: }
! 1234:
! 1235: static void tgen_brcond(TCGContext *s, TCGType type, TCGCond c,
! 1236: TCGReg r1, TCGArg c2, int c2const, int labelno)
! 1237: {
! 1238: int cc;
! 1239:
! 1240: if (facilities & FACILITY_GEN_INST_EXT) {
! 1241: bool is_unsigned = (c > TCG_COND_GT);
! 1242: bool in_range;
! 1243: S390Opcode opc;
! 1244:
! 1245: cc = tcg_cond_to_s390_cond[c];
! 1246:
! 1247: if (!c2const) {
! 1248: opc = (type == TCG_TYPE_I32
! 1249: ? (is_unsigned ? RIE_CLRJ : RIE_CRJ)
! 1250: : (is_unsigned ? RIE_CLGRJ : RIE_CGRJ));
! 1251: tgen_compare_branch(s, opc, cc, r1, c2, labelno);
! 1252: return;
! 1253: }
! 1254:
! 1255: /* COMPARE IMMEDIATE AND BRANCH RELATIVE has an 8-bit immediate field.
! 1256: If the immediate we've been given does not fit that range, we'll
! 1257: fall back to separate compare and branch instructions using the
! 1258: larger comparison range afforded by COMPARE IMMEDIATE. */
! 1259: if (type == TCG_TYPE_I32) {
! 1260: if (is_unsigned) {
! 1261: opc = RIE_CLIJ;
! 1262: in_range = (uint32_t)c2 == (uint8_t)c2;
! 1263: } else {
! 1264: opc = RIE_CIJ;
! 1265: in_range = (int32_t)c2 == (int8_t)c2;
! 1266: }
! 1267: } else {
! 1268: if (is_unsigned) {
! 1269: opc = RIE_CLGIJ;
! 1270: in_range = (uint64_t)c2 == (uint8_t)c2;
! 1271: } else {
! 1272: opc = RIE_CGIJ;
! 1273: in_range = (int64_t)c2 == (int8_t)c2;
! 1274: }
! 1275: }
! 1276: if (in_range) {
! 1277: tgen_compare_imm_branch(s, opc, cc, r1, c2, labelno);
! 1278: return;
! 1279: }
! 1280: }
! 1281:
! 1282: cc = tgen_cmp(s, type, c, r1, c2, c2const);
! 1283: tgen_branch(s, cc, labelno);
! 1284: }
! 1285:
! 1286: static void tgen_calli(TCGContext *s, tcg_target_long dest)
! 1287: {
! 1288: tcg_target_long off = (dest - (tcg_target_long)s->code_ptr) >> 1;
! 1289: if (off == (int32_t)off) {
! 1290: tcg_out_insn(s, RIL, BRASL, TCG_REG_R14, off);
! 1291: } else {
! 1292: tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, dest);
! 1293: tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_TMP0);
! 1294: }
! 1295: }
! 1296:
! 1297: static void tcg_out_qemu_ld_direct(TCGContext *s, int opc, TCGReg data,
! 1298: TCGReg base, TCGReg index, int disp)
! 1299: {
! 1300: #ifdef TARGET_WORDS_BIGENDIAN
! 1301: const int bswap = 0;
! 1302: #else
! 1303: const int bswap = 1;
! 1304: #endif
! 1305: switch (opc) {
! 1306: case LD_UINT8:
! 1307: tcg_out_insn(s, RXY, LLGC, data, base, index, disp);
! 1308: break;
! 1309: case LD_INT8:
! 1310: tcg_out_insn(s, RXY, LGB, data, base, index, disp);
! 1311: break;
! 1312: case LD_UINT16:
! 1313: if (bswap) {
! 1314: /* swapped unsigned halfword load with upper bits zeroed */
! 1315: tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
! 1316: tgen_ext16u(s, TCG_TYPE_I64, data, data);
! 1317: } else {
! 1318: tcg_out_insn(s, RXY, LLGH, data, base, index, disp);
! 1319: }
! 1320: break;
! 1321: case LD_INT16:
! 1322: if (bswap) {
! 1323: /* swapped sign-extended halfword load */
! 1324: tcg_out_insn(s, RXY, LRVH, data, base, index, disp);
! 1325: tgen_ext16s(s, TCG_TYPE_I64, data, data);
! 1326: } else {
! 1327: tcg_out_insn(s, RXY, LGH, data, base, index, disp);
! 1328: }
! 1329: break;
! 1330: case LD_UINT32:
! 1331: if (bswap) {
! 1332: /* swapped unsigned int load with upper bits zeroed */
! 1333: tcg_out_insn(s, RXY, LRV, data, base, index, disp);
! 1334: tgen_ext32u(s, data, data);
! 1335: } else {
! 1336: tcg_out_insn(s, RXY, LLGF, data, base, index, disp);
! 1337: }
! 1338: break;
! 1339: case LD_INT32:
! 1340: if (bswap) {
! 1341: /* swapped sign-extended int load */
! 1342: tcg_out_insn(s, RXY, LRV, data, base, index, disp);
! 1343: tgen_ext32s(s, data, data);
! 1344: } else {
! 1345: tcg_out_insn(s, RXY, LGF, data, base, index, disp);
! 1346: }
! 1347: break;
! 1348: case LD_UINT64:
! 1349: if (bswap) {
! 1350: tcg_out_insn(s, RXY, LRVG, data, base, index, disp);
! 1351: } else {
! 1352: tcg_out_insn(s, RXY, LG, data, base, index, disp);
! 1353: }
! 1354: break;
! 1355: default:
! 1356: tcg_abort();
! 1357: }
! 1358: }
! 1359:
! 1360: static void tcg_out_qemu_st_direct(TCGContext *s, int opc, TCGReg data,
! 1361: TCGReg base, TCGReg index, int disp)
! 1362: {
! 1363: #ifdef TARGET_WORDS_BIGENDIAN
! 1364: const int bswap = 0;
! 1365: #else
! 1366: const int bswap = 1;
! 1367: #endif
! 1368: switch (opc) {
! 1369: case LD_UINT8:
! 1370: if (disp >= 0 && disp < 0x1000) {
! 1371: tcg_out_insn(s, RX, STC, data, base, index, disp);
! 1372: } else {
! 1373: tcg_out_insn(s, RXY, STCY, data, base, index, disp);
! 1374: }
! 1375: break;
! 1376: case LD_UINT16:
! 1377: if (bswap) {
! 1378: tcg_out_insn(s, RXY, STRVH, data, base, index, disp);
! 1379: } else if (disp >= 0 && disp < 0x1000) {
! 1380: tcg_out_insn(s, RX, STH, data, base, index, disp);
! 1381: } else {
! 1382: tcg_out_insn(s, RXY, STHY, data, base, index, disp);
! 1383: }
! 1384: break;
! 1385: case LD_UINT32:
! 1386: if (bswap) {
! 1387: tcg_out_insn(s, RXY, STRV, data, base, index, disp);
! 1388: } else if (disp >= 0 && disp < 0x1000) {
! 1389: tcg_out_insn(s, RX, ST, data, base, index, disp);
! 1390: } else {
! 1391: tcg_out_insn(s, RXY, STY, data, base, index, disp);
! 1392: }
! 1393: break;
! 1394: case LD_UINT64:
! 1395: if (bswap) {
! 1396: tcg_out_insn(s, RXY, STRVG, data, base, index, disp);
! 1397: } else {
! 1398: tcg_out_insn(s, RXY, STG, data, base, index, disp);
! 1399: }
! 1400: break;
! 1401: default:
! 1402: tcg_abort();
! 1403: }
! 1404: }
! 1405:
! 1406: #if defined(CONFIG_SOFTMMU)
! 1407: static void tgen64_andi_tmp(TCGContext *s, TCGReg dest, tcg_target_ulong val)
! 1408: {
! 1409: if (tcg_match_andi(0, val)) {
! 1410: tcg_out_movi(s, TCG_TYPE_I64, TCG_TMP0, val);
! 1411: tcg_out_insn(s, RRE, NGR, dest, TCG_TMP0);
! 1412: } else {
! 1413: tgen64_andi(s, dest, val);
! 1414: }
! 1415: }
! 1416:
! 1417: static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
! 1418: TCGReg addr_reg, int mem_index, int opc,
! 1419: uint16_t **label2_ptr_p, int is_store)
! 1420: {
! 1421: const TCGReg arg0 = TCG_REG_R2;
! 1422: const TCGReg arg1 = TCG_REG_R3;
! 1423: int s_bits = opc & 3;
! 1424: uint16_t *label1_ptr;
! 1425: tcg_target_long ofs;
! 1426:
! 1427: if (TARGET_LONG_BITS == 32) {
! 1428: tgen_ext32u(s, arg0, addr_reg);
! 1429: } else {
! 1430: tcg_out_mov(s, TCG_TYPE_I64, arg0, addr_reg);
! 1431: }
! 1432:
! 1433: tcg_out_sh64(s, RSY_SRLG, arg1, addr_reg, TCG_REG_NONE,
! 1434: TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
! 1435:
! 1436: tgen64_andi_tmp(s, arg0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
! 1437: tgen64_andi_tmp(s, arg1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
! 1438:
! 1439: if (is_store) {
! 1440: ofs = offsetof(CPUState, tlb_table[mem_index][0].addr_write);
! 1441: } else {
! 1442: ofs = offsetof(CPUState, tlb_table[mem_index][0].addr_read);
! 1443: }
! 1444: assert(ofs < 0x80000);
! 1445:
! 1446: if (TARGET_LONG_BITS == 32) {
! 1447: tcg_out_mem(s, RX_C, RXY_CY, arg0, arg1, TCG_AREG0, ofs);
! 1448: } else {
! 1449: tcg_out_mem(s, 0, RXY_CG, arg0, arg1, TCG_AREG0, ofs);
! 1450: }
! 1451:
! 1452: if (TARGET_LONG_BITS == 32) {
! 1453: tgen_ext32u(s, arg0, addr_reg);
! 1454: } else {
! 1455: tcg_out_mov(s, TCG_TYPE_I64, arg0, addr_reg);
! 1456: }
! 1457:
! 1458: label1_ptr = (uint16_t*)s->code_ptr;
! 1459:
! 1460: /* je label1 (offset will be patched in later) */
! 1461: tcg_out_insn(s, RI, BRC, S390_CC_EQ, 0);
! 1462:
! 1463: /* call load/store helper */
! 1464: if (is_store) {
! 1465: /* Make sure to zero-extend the value to the full register
! 1466: for the calling convention. */
! 1467: switch (opc) {
! 1468: case LD_UINT8:
! 1469: tgen_ext8u(s, TCG_TYPE_I64, arg1, data_reg);
! 1470: break;
! 1471: case LD_UINT16:
! 1472: tgen_ext16u(s, TCG_TYPE_I64, arg1, data_reg);
! 1473: break;
! 1474: case LD_UINT32:
! 1475: tgen_ext32u(s, arg1, data_reg);
! 1476: break;
! 1477: case LD_UINT64:
! 1478: tcg_out_mov(s, TCG_TYPE_I64, arg1, data_reg);
! 1479: break;
! 1480: default:
! 1481: tcg_abort();
! 1482: }
! 1483: tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R4, mem_index);
! 1484: tgen_calli(s, (tcg_target_ulong)qemu_st_helpers[s_bits]);
! 1485: } else {
! 1486: tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
! 1487: tgen_calli(s, (tcg_target_ulong)qemu_ld_helpers[s_bits]);
! 1488:
! 1489: /* sign extension */
! 1490: switch (opc) {
! 1491: case LD_INT8:
! 1492: tgen_ext8s(s, TCG_TYPE_I64, data_reg, arg0);
! 1493: break;
! 1494: case LD_INT16:
! 1495: tgen_ext16s(s, TCG_TYPE_I64, data_reg, arg0);
! 1496: break;
! 1497: case LD_INT32:
! 1498: tgen_ext32s(s, data_reg, arg0);
! 1499: break;
! 1500: default:
! 1501: /* unsigned -> just copy */
! 1502: tcg_out_mov(s, TCG_TYPE_I64, data_reg, arg0);
! 1503: break;
! 1504: }
! 1505: }
! 1506:
! 1507: /* jump to label2 (end) */
! 1508: *label2_ptr_p = (uint16_t*)s->code_ptr;
! 1509:
! 1510: tcg_out_insn(s, RI, BRC, S390_CC_ALWAYS, 0);
! 1511:
! 1512: /* this is label1, patch branch */
! 1513: *(label1_ptr + 1) = ((unsigned long)s->code_ptr -
! 1514: (unsigned long)label1_ptr) >> 1;
! 1515:
! 1516: ofs = offsetof(CPUState, tlb_table[mem_index][0].addend);
! 1517: assert(ofs < 0x80000);
! 1518:
! 1519: tcg_out_mem(s, 0, RXY_AG, arg0, arg1, TCG_AREG0, ofs);
! 1520: }
! 1521:
! 1522: static void tcg_finish_qemu_ldst(TCGContext* s, uint16_t *label2_ptr)
! 1523: {
! 1524: /* patch branch */
! 1525: *(label2_ptr + 1) = ((unsigned long)s->code_ptr -
! 1526: (unsigned long)label2_ptr) >> 1;
! 1527: }
! 1528: #else
! 1529: static void tcg_prepare_user_ldst(TCGContext *s, TCGReg *addr_reg,
! 1530: TCGReg *index_reg, tcg_target_long *disp)
! 1531: {
! 1532: if (TARGET_LONG_BITS == 32) {
! 1533: tgen_ext32u(s, TCG_TMP0, *addr_reg);
! 1534: *addr_reg = TCG_TMP0;
! 1535: }
! 1536: if (GUEST_BASE < 0x80000) {
! 1537: *index_reg = TCG_REG_NONE;
! 1538: *disp = GUEST_BASE;
! 1539: } else {
! 1540: *index_reg = TCG_GUEST_BASE_REG;
! 1541: *disp = 0;
! 1542: }
! 1543: }
! 1544: #endif /* CONFIG_SOFTMMU */
! 1545:
! 1546: /* load data with address translation (if applicable)
! 1547: and endianness conversion */
! 1548: static void tcg_out_qemu_ld(TCGContext* s, const TCGArg* args, int opc)
! 1549: {
! 1550: TCGReg addr_reg, data_reg;
! 1551: #if defined(CONFIG_SOFTMMU)
! 1552: int mem_index;
! 1553: uint16_t *label2_ptr;
! 1554: #else
! 1555: TCGReg index_reg;
! 1556: tcg_target_long disp;
! 1557: #endif
! 1558:
! 1559: data_reg = *args++;
! 1560: addr_reg = *args++;
! 1561:
! 1562: #if defined(CONFIG_SOFTMMU)
! 1563: mem_index = *args;
! 1564:
! 1565: tcg_prepare_qemu_ldst(s, data_reg, addr_reg, mem_index,
! 1566: opc, &label2_ptr, 0);
! 1567:
! 1568: tcg_out_qemu_ld_direct(s, opc, data_reg, TCG_REG_R2, TCG_REG_NONE, 0);
! 1569:
! 1570: tcg_finish_qemu_ldst(s, label2_ptr);
! 1571: #else
! 1572: tcg_prepare_user_ldst(s, &addr_reg, &index_reg, &disp);
! 1573: tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg, index_reg, disp);
! 1574: #endif
! 1575: }
! 1576:
! 1577: static void tcg_out_qemu_st(TCGContext* s, const TCGArg* args, int opc)
! 1578: {
! 1579: TCGReg addr_reg, data_reg;
! 1580: #if defined(CONFIG_SOFTMMU)
! 1581: int mem_index;
! 1582: uint16_t *label2_ptr;
! 1583: #else
! 1584: TCGReg index_reg;
! 1585: tcg_target_long disp;
! 1586: #endif
! 1587:
! 1588: data_reg = *args++;
! 1589: addr_reg = *args++;
! 1590:
! 1591: #if defined(CONFIG_SOFTMMU)
! 1592: mem_index = *args;
! 1593:
! 1594: tcg_prepare_qemu_ldst(s, data_reg, addr_reg, mem_index,
! 1595: opc, &label2_ptr, 1);
! 1596:
! 1597: tcg_out_qemu_st_direct(s, opc, data_reg, TCG_REG_R2, TCG_REG_NONE, 0);
! 1598:
! 1599: tcg_finish_qemu_ldst(s, label2_ptr);
! 1600: #else
! 1601: tcg_prepare_user_ldst(s, &addr_reg, &index_reg, &disp);
! 1602: tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg, index_reg, disp);
! 1603: #endif
! 1604: }
! 1605:
! 1606: #if TCG_TARGET_REG_BITS == 64
! 1607: # define OP_32_64(x) \
! 1608: case glue(glue(INDEX_op_,x),_i32): \
! 1609: case glue(glue(INDEX_op_,x),_i64)
! 1610: #else
! 1611: # define OP_32_64(x) \
! 1612: case glue(glue(INDEX_op_,x),_i32)
! 1613: #endif
! 1614:
! 1615: static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
1.1 root 1616: const TCGArg *args, const int *const_args)
1617: {
1.1.1.2 ! root 1618: S390Opcode op;
! 1619:
! 1620: switch (opc) {
! 1621: case INDEX_op_exit_tb:
! 1622: /* return value */
! 1623: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, args[0]);
! 1624: tgen_gotoi(s, S390_CC_ALWAYS, (unsigned long)tb_ret_addr);
! 1625: break;
! 1626:
! 1627: case INDEX_op_goto_tb:
! 1628: if (s->tb_jmp_offset) {
! 1629: tcg_abort();
! 1630: } else {
! 1631: /* load address stored at s->tb_next + args[0] */
! 1632: tcg_out_ld_abs(s, TCG_TYPE_PTR, TCG_TMP0, s->tb_next + args[0]);
! 1633: /* and go there */
! 1634: tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_TMP0);
! 1635: }
! 1636: s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
! 1637: break;
! 1638:
! 1639: case INDEX_op_call:
! 1640: if (const_args[0]) {
! 1641: tgen_calli(s, args[0]);
! 1642: } else {
! 1643: tcg_out_insn(s, RR, BASR, TCG_REG_R14, args[0]);
! 1644: }
! 1645: break;
! 1646:
! 1647: case INDEX_op_mov_i32:
! 1648: tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
! 1649: break;
! 1650: case INDEX_op_movi_i32:
! 1651: tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
! 1652: break;
! 1653:
! 1654: OP_32_64(ld8u):
! 1655: /* ??? LLC (RXY format) is only present with the extended-immediate
! 1656: facility, whereas LLGC is always present. */
! 1657: tcg_out_mem(s, 0, RXY_LLGC, args[0], args[1], TCG_REG_NONE, args[2]);
! 1658: break;
! 1659:
! 1660: OP_32_64(ld8s):
! 1661: /* ??? LB is no smaller than LGB, so no point to using it. */
! 1662: tcg_out_mem(s, 0, RXY_LGB, args[0], args[1], TCG_REG_NONE, args[2]);
! 1663: break;
! 1664:
! 1665: OP_32_64(ld16u):
! 1666: /* ??? LLH (RXY format) is only present with the extended-immediate
! 1667: facility, whereas LLGH is always present. */
! 1668: tcg_out_mem(s, 0, RXY_LLGH, args[0], args[1], TCG_REG_NONE, args[2]);
! 1669: break;
! 1670:
! 1671: case INDEX_op_ld16s_i32:
! 1672: tcg_out_mem(s, RX_LH, RXY_LHY, args[0], args[1], TCG_REG_NONE, args[2]);
! 1673: break;
! 1674:
! 1675: case INDEX_op_ld_i32:
! 1676: tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
! 1677: break;
! 1678:
! 1679: OP_32_64(st8):
! 1680: tcg_out_mem(s, RX_STC, RXY_STCY, args[0], args[1],
! 1681: TCG_REG_NONE, args[2]);
! 1682: break;
! 1683:
! 1684: OP_32_64(st16):
! 1685: tcg_out_mem(s, RX_STH, RXY_STHY, args[0], args[1],
! 1686: TCG_REG_NONE, args[2]);
! 1687: break;
! 1688:
! 1689: case INDEX_op_st_i32:
! 1690: tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
! 1691: break;
! 1692:
! 1693: case INDEX_op_add_i32:
! 1694: if (const_args[2]) {
! 1695: tgen32_addi(s, args[0], args[2]);
! 1696: } else {
! 1697: tcg_out_insn(s, RR, AR, args[0], args[2]);
! 1698: }
! 1699: break;
! 1700: case INDEX_op_sub_i32:
! 1701: if (const_args[2]) {
! 1702: tgen32_addi(s, args[0], -args[2]);
! 1703: } else {
! 1704: tcg_out_insn(s, RR, SR, args[0], args[2]);
! 1705: }
! 1706: break;
! 1707:
! 1708: case INDEX_op_and_i32:
! 1709: if (const_args[2]) {
! 1710: tgen64_andi(s, args[0], args[2] | 0xffffffff00000000ull);
! 1711: } else {
! 1712: tcg_out_insn(s, RR, NR, args[0], args[2]);
! 1713: }
! 1714: break;
! 1715: case INDEX_op_or_i32:
! 1716: if (const_args[2]) {
! 1717: tgen64_ori(s, args[0], args[2] & 0xffffffff);
! 1718: } else {
! 1719: tcg_out_insn(s, RR, OR, args[0], args[2]);
! 1720: }
! 1721: break;
! 1722: case INDEX_op_xor_i32:
! 1723: if (const_args[2]) {
! 1724: tgen64_xori(s, args[0], args[2] & 0xffffffff);
! 1725: } else {
! 1726: tcg_out_insn(s, RR, XR, args[0], args[2]);
! 1727: }
! 1728: break;
! 1729:
! 1730: case INDEX_op_neg_i32:
! 1731: tcg_out_insn(s, RR, LCR, args[0], args[1]);
! 1732: break;
! 1733:
! 1734: case INDEX_op_mul_i32:
! 1735: if (const_args[2]) {
! 1736: if ((int32_t)args[2] == (int16_t)args[2]) {
! 1737: tcg_out_insn(s, RI, MHI, args[0], args[2]);
! 1738: } else {
! 1739: tcg_out_insn(s, RIL, MSFI, args[0], args[2]);
! 1740: }
! 1741: } else {
! 1742: tcg_out_insn(s, RRE, MSR, args[0], args[2]);
! 1743: }
! 1744: break;
! 1745:
! 1746: case INDEX_op_div2_i32:
! 1747: tcg_out_insn(s, RR, DR, TCG_REG_R2, args[4]);
! 1748: break;
! 1749: case INDEX_op_divu2_i32:
! 1750: tcg_out_insn(s, RRE, DLR, TCG_REG_R2, args[4]);
! 1751: break;
! 1752:
! 1753: case INDEX_op_shl_i32:
! 1754: op = RS_SLL;
! 1755: do_shift32:
! 1756: if (const_args[2]) {
! 1757: tcg_out_sh32(s, op, args[0], TCG_REG_NONE, args[2]);
! 1758: } else {
! 1759: tcg_out_sh32(s, op, args[0], args[2], 0);
! 1760: }
! 1761: break;
! 1762: case INDEX_op_shr_i32:
! 1763: op = RS_SRL;
! 1764: goto do_shift32;
! 1765: case INDEX_op_sar_i32:
! 1766: op = RS_SRA;
! 1767: goto do_shift32;
! 1768:
! 1769: case INDEX_op_rotl_i32:
! 1770: /* ??? Using tcg_out_sh64 here for the format; it is a 32-bit rol. */
! 1771: if (const_args[2]) {
! 1772: tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_REG_NONE, args[2]);
! 1773: } else {
! 1774: tcg_out_sh64(s, RSY_RLL, args[0], args[1], args[2], 0);
! 1775: }
! 1776: break;
! 1777: case INDEX_op_rotr_i32:
! 1778: if (const_args[2]) {
! 1779: tcg_out_sh64(s, RSY_RLL, args[0], args[1],
! 1780: TCG_REG_NONE, (32 - args[2]) & 31);
! 1781: } else {
! 1782: tcg_out_insn(s, RR, LCR, TCG_TMP0, args[2]);
! 1783: tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_TMP0, 0);
! 1784: }
! 1785: break;
! 1786:
! 1787: case INDEX_op_ext8s_i32:
! 1788: tgen_ext8s(s, TCG_TYPE_I32, args[0], args[1]);
! 1789: break;
! 1790: case INDEX_op_ext16s_i32:
! 1791: tgen_ext16s(s, TCG_TYPE_I32, args[0], args[1]);
! 1792: break;
! 1793: case INDEX_op_ext8u_i32:
! 1794: tgen_ext8u(s, TCG_TYPE_I32, args[0], args[1]);
! 1795: break;
! 1796: case INDEX_op_ext16u_i32:
! 1797: tgen_ext16u(s, TCG_TYPE_I32, args[0], args[1]);
! 1798: break;
! 1799:
! 1800: OP_32_64(bswap16):
! 1801: /* The TCG bswap definition requires bits 0-47 already be zero.
! 1802: Thus we don't need the G-type insns to implement bswap16_i64. */
! 1803: tcg_out_insn(s, RRE, LRVR, args[0], args[1]);
! 1804: tcg_out_sh32(s, RS_SRL, args[0], TCG_REG_NONE, 16);
! 1805: break;
! 1806: OP_32_64(bswap32):
! 1807: tcg_out_insn(s, RRE, LRVR, args[0], args[1]);
! 1808: break;
! 1809:
! 1810: case INDEX_op_br:
! 1811: tgen_branch(s, S390_CC_ALWAYS, args[0]);
! 1812: break;
! 1813:
! 1814: case INDEX_op_brcond_i32:
! 1815: tgen_brcond(s, TCG_TYPE_I32, args[2], args[0],
! 1816: args[1], const_args[1], args[3]);
! 1817: break;
! 1818: case INDEX_op_setcond_i32:
! 1819: tgen_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1],
! 1820: args[2], const_args[2]);
! 1821: break;
! 1822:
! 1823: case INDEX_op_qemu_ld8u:
! 1824: tcg_out_qemu_ld(s, args, LD_UINT8);
! 1825: break;
! 1826: case INDEX_op_qemu_ld8s:
! 1827: tcg_out_qemu_ld(s, args, LD_INT8);
! 1828: break;
! 1829: case INDEX_op_qemu_ld16u:
! 1830: tcg_out_qemu_ld(s, args, LD_UINT16);
! 1831: break;
! 1832: case INDEX_op_qemu_ld16s:
! 1833: tcg_out_qemu_ld(s, args, LD_INT16);
! 1834: break;
! 1835: case INDEX_op_qemu_ld32:
! 1836: /* ??? Technically we can use a non-extending instruction. */
! 1837: tcg_out_qemu_ld(s, args, LD_UINT32);
! 1838: break;
! 1839: case INDEX_op_qemu_ld64:
! 1840: tcg_out_qemu_ld(s, args, LD_UINT64);
! 1841: break;
! 1842:
! 1843: case INDEX_op_qemu_st8:
! 1844: tcg_out_qemu_st(s, args, LD_UINT8);
! 1845: break;
! 1846: case INDEX_op_qemu_st16:
! 1847: tcg_out_qemu_st(s, args, LD_UINT16);
! 1848: break;
! 1849: case INDEX_op_qemu_st32:
! 1850: tcg_out_qemu_st(s, args, LD_UINT32);
! 1851: break;
! 1852: case INDEX_op_qemu_st64:
! 1853: tcg_out_qemu_st(s, args, LD_UINT64);
! 1854: break;
! 1855:
! 1856: #if TCG_TARGET_REG_BITS == 64
! 1857: case INDEX_op_mov_i64:
! 1858: tcg_out_mov(s, TCG_TYPE_I64, args[0], args[1]);
! 1859: break;
! 1860: case INDEX_op_movi_i64:
! 1861: tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
! 1862: break;
! 1863:
! 1864: case INDEX_op_ld16s_i64:
! 1865: tcg_out_mem(s, 0, RXY_LGH, args[0], args[1], TCG_REG_NONE, args[2]);
! 1866: break;
! 1867: case INDEX_op_ld32u_i64:
! 1868: tcg_out_mem(s, 0, RXY_LLGF, args[0], args[1], TCG_REG_NONE, args[2]);
! 1869: break;
! 1870: case INDEX_op_ld32s_i64:
! 1871: tcg_out_mem(s, 0, RXY_LGF, args[0], args[1], TCG_REG_NONE, args[2]);
! 1872: break;
! 1873: case INDEX_op_ld_i64:
! 1874: tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
! 1875: break;
! 1876:
! 1877: case INDEX_op_st32_i64:
! 1878: tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
! 1879: break;
! 1880: case INDEX_op_st_i64:
! 1881: tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
! 1882: break;
! 1883:
! 1884: case INDEX_op_add_i64:
! 1885: if (const_args[2]) {
! 1886: tgen64_addi(s, args[0], args[2]);
! 1887: } else {
! 1888: tcg_out_insn(s, RRE, AGR, args[0], args[2]);
! 1889: }
! 1890: break;
! 1891: case INDEX_op_sub_i64:
! 1892: if (const_args[2]) {
! 1893: tgen64_addi(s, args[0], -args[2]);
! 1894: } else {
! 1895: tcg_out_insn(s, RRE, SGR, args[0], args[2]);
! 1896: }
! 1897: break;
! 1898:
! 1899: case INDEX_op_and_i64:
! 1900: if (const_args[2]) {
! 1901: tgen64_andi(s, args[0], args[2]);
! 1902: } else {
! 1903: tcg_out_insn(s, RRE, NGR, args[0], args[2]);
! 1904: }
! 1905: break;
! 1906: case INDEX_op_or_i64:
! 1907: if (const_args[2]) {
! 1908: tgen64_ori(s, args[0], args[2]);
! 1909: } else {
! 1910: tcg_out_insn(s, RRE, OGR, args[0], args[2]);
! 1911: }
! 1912: break;
! 1913: case INDEX_op_xor_i64:
! 1914: if (const_args[2]) {
! 1915: tgen64_xori(s, args[0], args[2]);
! 1916: } else {
! 1917: tcg_out_insn(s, RRE, XGR, args[0], args[2]);
! 1918: }
! 1919: break;
! 1920:
! 1921: case INDEX_op_neg_i64:
! 1922: tcg_out_insn(s, RRE, LCGR, args[0], args[1]);
! 1923: break;
! 1924: case INDEX_op_bswap64_i64:
! 1925: tcg_out_insn(s, RRE, LRVGR, args[0], args[1]);
! 1926: break;
! 1927:
! 1928: case INDEX_op_mul_i64:
! 1929: if (const_args[2]) {
! 1930: if (args[2] == (int16_t)args[2]) {
! 1931: tcg_out_insn(s, RI, MGHI, args[0], args[2]);
! 1932: } else {
! 1933: tcg_out_insn(s, RIL, MSGFI, args[0], args[2]);
! 1934: }
! 1935: } else {
! 1936: tcg_out_insn(s, RRE, MSGR, args[0], args[2]);
! 1937: }
! 1938: break;
! 1939:
! 1940: case INDEX_op_div2_i64:
! 1941: /* ??? We get an unnecessary sign-extension of the dividend
! 1942: into R3 with this definition, but as we do in fact always
! 1943: produce both quotient and remainder using INDEX_op_div_i64
! 1944: instead requires jumping through even more hoops. */
! 1945: tcg_out_insn(s, RRE, DSGR, TCG_REG_R2, args[4]);
! 1946: break;
! 1947: case INDEX_op_divu2_i64:
! 1948: tcg_out_insn(s, RRE, DLGR, TCG_REG_R2, args[4]);
! 1949: break;
! 1950:
! 1951: case INDEX_op_shl_i64:
! 1952: op = RSY_SLLG;
! 1953: do_shift64:
! 1954: if (const_args[2]) {
! 1955: tcg_out_sh64(s, op, args[0], args[1], TCG_REG_NONE, args[2]);
! 1956: } else {
! 1957: tcg_out_sh64(s, op, args[0], args[1], args[2], 0);
! 1958: }
! 1959: break;
! 1960: case INDEX_op_shr_i64:
! 1961: op = RSY_SRLG;
! 1962: goto do_shift64;
! 1963: case INDEX_op_sar_i64:
! 1964: op = RSY_SRAG;
! 1965: goto do_shift64;
! 1966:
! 1967: case INDEX_op_rotl_i64:
! 1968: if (const_args[2]) {
! 1969: tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
! 1970: TCG_REG_NONE, args[2]);
! 1971: } else {
! 1972: tcg_out_sh64(s, RSY_RLLG, args[0], args[1], args[2], 0);
! 1973: }
! 1974: break;
! 1975: case INDEX_op_rotr_i64:
! 1976: if (const_args[2]) {
! 1977: tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
! 1978: TCG_REG_NONE, (64 - args[2]) & 63);
! 1979: } else {
! 1980: /* We can use the smaller 32-bit negate because only the
! 1981: low 6 bits are examined for the rotate. */
! 1982: tcg_out_insn(s, RR, LCR, TCG_TMP0, args[2]);
! 1983: tcg_out_sh64(s, RSY_RLLG, args[0], args[1], TCG_TMP0, 0);
! 1984: }
! 1985: break;
! 1986:
! 1987: case INDEX_op_ext8s_i64:
! 1988: tgen_ext8s(s, TCG_TYPE_I64, args[0], args[1]);
! 1989: break;
! 1990: case INDEX_op_ext16s_i64:
! 1991: tgen_ext16s(s, TCG_TYPE_I64, args[0], args[1]);
! 1992: break;
! 1993: case INDEX_op_ext32s_i64:
! 1994: tgen_ext32s(s, args[0], args[1]);
! 1995: break;
! 1996: case INDEX_op_ext8u_i64:
! 1997: tgen_ext8u(s, TCG_TYPE_I64, args[0], args[1]);
! 1998: break;
! 1999: case INDEX_op_ext16u_i64:
! 2000: tgen_ext16u(s, TCG_TYPE_I64, args[0], args[1]);
! 2001: break;
! 2002: case INDEX_op_ext32u_i64:
! 2003: tgen_ext32u(s, args[0], args[1]);
! 2004: break;
! 2005:
! 2006: case INDEX_op_brcond_i64:
! 2007: tgen_brcond(s, TCG_TYPE_I64, args[2], args[0],
! 2008: args[1], const_args[1], args[3]);
! 2009: break;
! 2010: case INDEX_op_setcond_i64:
! 2011: tgen_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1],
! 2012: args[2], const_args[2]);
! 2013: break;
! 2014:
! 2015: case INDEX_op_qemu_ld32u:
! 2016: tcg_out_qemu_ld(s, args, LD_UINT32);
! 2017: break;
! 2018: case INDEX_op_qemu_ld32s:
! 2019: tcg_out_qemu_ld(s, args, LD_INT32);
! 2020: break;
! 2021: #endif /* TCG_TARGET_REG_BITS == 64 */
! 2022:
! 2023: case INDEX_op_jmp:
! 2024: /* This one is obsolete and never emitted. */
! 2025: tcg_abort();
! 2026: break;
! 2027:
! 2028: default:
! 2029: fprintf(stderr,"unimplemented opc 0x%x\n",opc);
! 2030: tcg_abort();
! 2031: }
1.1 root 2032: }
2033:
1.1.1.2 ! root 2034: static const TCGTargetOpDef s390_op_defs[] = {
! 2035: { INDEX_op_exit_tb, { } },
! 2036: { INDEX_op_goto_tb, { } },
! 2037: { INDEX_op_call, { "ri" } },
! 2038: { INDEX_op_jmp, { "ri" } },
! 2039: { INDEX_op_br, { } },
! 2040:
! 2041: { INDEX_op_mov_i32, { "r", "r" } },
! 2042: { INDEX_op_movi_i32, { "r" } },
! 2043:
! 2044: { INDEX_op_ld8u_i32, { "r", "r" } },
! 2045: { INDEX_op_ld8s_i32, { "r", "r" } },
! 2046: { INDEX_op_ld16u_i32, { "r", "r" } },
! 2047: { INDEX_op_ld16s_i32, { "r", "r" } },
! 2048: { INDEX_op_ld_i32, { "r", "r" } },
! 2049: { INDEX_op_st8_i32, { "r", "r" } },
! 2050: { INDEX_op_st16_i32, { "r", "r" } },
! 2051: { INDEX_op_st_i32, { "r", "r" } },
! 2052:
! 2053: { INDEX_op_add_i32, { "r", "0", "rWI" } },
! 2054: { INDEX_op_sub_i32, { "r", "0", "rWNI" } },
! 2055: { INDEX_op_mul_i32, { "r", "0", "rK" } },
! 2056:
! 2057: { INDEX_op_div2_i32, { "b", "a", "0", "1", "r" } },
! 2058: { INDEX_op_divu2_i32, { "b", "a", "0", "1", "r" } },
! 2059:
! 2060: { INDEX_op_and_i32, { "r", "0", "rWA" } },
! 2061: { INDEX_op_or_i32, { "r", "0", "rWO" } },
! 2062: { INDEX_op_xor_i32, { "r", "0", "rWX" } },
! 2063:
! 2064: { INDEX_op_neg_i32, { "r", "r" } },
! 2065:
! 2066: { INDEX_op_shl_i32, { "r", "0", "Ri" } },
! 2067: { INDEX_op_shr_i32, { "r", "0", "Ri" } },
! 2068: { INDEX_op_sar_i32, { "r", "0", "Ri" } },
! 2069:
! 2070: { INDEX_op_rotl_i32, { "r", "r", "Ri" } },
! 2071: { INDEX_op_rotr_i32, { "r", "r", "Ri" } },
! 2072:
! 2073: { INDEX_op_ext8s_i32, { "r", "r" } },
! 2074: { INDEX_op_ext8u_i32, { "r", "r" } },
! 2075: { INDEX_op_ext16s_i32, { "r", "r" } },
! 2076: { INDEX_op_ext16u_i32, { "r", "r" } },
! 2077:
! 2078: { INDEX_op_bswap16_i32, { "r", "r" } },
! 2079: { INDEX_op_bswap32_i32, { "r", "r" } },
! 2080:
! 2081: { INDEX_op_brcond_i32, { "r", "rWC" } },
! 2082: { INDEX_op_setcond_i32, { "r", "r", "rWC" } },
! 2083:
! 2084: { INDEX_op_qemu_ld8u, { "r", "L" } },
! 2085: { INDEX_op_qemu_ld8s, { "r", "L" } },
! 2086: { INDEX_op_qemu_ld16u, { "r", "L" } },
! 2087: { INDEX_op_qemu_ld16s, { "r", "L" } },
! 2088: { INDEX_op_qemu_ld32, { "r", "L" } },
! 2089: { INDEX_op_qemu_ld64, { "r", "L" } },
! 2090:
! 2091: { INDEX_op_qemu_st8, { "L", "L" } },
! 2092: { INDEX_op_qemu_st16, { "L", "L" } },
! 2093: { INDEX_op_qemu_st32, { "L", "L" } },
! 2094: { INDEX_op_qemu_st64, { "L", "L" } },
! 2095:
! 2096: #if defined(__s390x__)
! 2097: { INDEX_op_mov_i64, { "r", "r" } },
! 2098: { INDEX_op_movi_i64, { "r" } },
! 2099:
! 2100: { INDEX_op_ld8u_i64, { "r", "r" } },
! 2101: { INDEX_op_ld8s_i64, { "r", "r" } },
! 2102: { INDEX_op_ld16u_i64, { "r", "r" } },
! 2103: { INDEX_op_ld16s_i64, { "r", "r" } },
! 2104: { INDEX_op_ld32u_i64, { "r", "r" } },
! 2105: { INDEX_op_ld32s_i64, { "r", "r" } },
! 2106: { INDEX_op_ld_i64, { "r", "r" } },
! 2107:
! 2108: { INDEX_op_st8_i64, { "r", "r" } },
! 2109: { INDEX_op_st16_i64, { "r", "r" } },
! 2110: { INDEX_op_st32_i64, { "r", "r" } },
! 2111: { INDEX_op_st_i64, { "r", "r" } },
! 2112:
! 2113: { INDEX_op_add_i64, { "r", "0", "rI" } },
! 2114: { INDEX_op_sub_i64, { "r", "0", "rNI" } },
! 2115: { INDEX_op_mul_i64, { "r", "0", "rK" } },
! 2116:
! 2117: { INDEX_op_div2_i64, { "b", "a", "0", "1", "r" } },
! 2118: { INDEX_op_divu2_i64, { "b", "a", "0", "1", "r" } },
! 2119:
! 2120: { INDEX_op_and_i64, { "r", "0", "rA" } },
! 2121: { INDEX_op_or_i64, { "r", "0", "rO" } },
! 2122: { INDEX_op_xor_i64, { "r", "0", "rX" } },
! 2123:
! 2124: { INDEX_op_neg_i64, { "r", "r" } },
! 2125:
! 2126: { INDEX_op_shl_i64, { "r", "r", "Ri" } },
! 2127: { INDEX_op_shr_i64, { "r", "r", "Ri" } },
! 2128: { INDEX_op_sar_i64, { "r", "r", "Ri" } },
! 2129:
! 2130: { INDEX_op_rotl_i64, { "r", "r", "Ri" } },
! 2131: { INDEX_op_rotr_i64, { "r", "r", "Ri" } },
! 2132:
! 2133: { INDEX_op_ext8s_i64, { "r", "r" } },
! 2134: { INDEX_op_ext8u_i64, { "r", "r" } },
! 2135: { INDEX_op_ext16s_i64, { "r", "r" } },
! 2136: { INDEX_op_ext16u_i64, { "r", "r" } },
! 2137: { INDEX_op_ext32s_i64, { "r", "r" } },
! 2138: { INDEX_op_ext32u_i64, { "r", "r" } },
! 2139:
! 2140: { INDEX_op_bswap16_i64, { "r", "r" } },
! 2141: { INDEX_op_bswap32_i64, { "r", "r" } },
! 2142: { INDEX_op_bswap64_i64, { "r", "r" } },
! 2143:
! 2144: { INDEX_op_brcond_i64, { "r", "rC" } },
! 2145: { INDEX_op_setcond_i64, { "r", "r", "rC" } },
! 2146:
! 2147: { INDEX_op_qemu_ld32u, { "r", "L" } },
! 2148: { INDEX_op_qemu_ld32s, { "r", "L" } },
! 2149: #endif
! 2150:
! 2151: { -1 },
! 2152: };
! 2153:
! 2154: /* ??? Linux kernels provide an AUXV entry AT_HWCAP that provides most of
! 2155: this information. However, getting at that entry is not easy this far
! 2156: away from main. Our options are: start searching from environ, but
! 2157: that fails as soon as someone does a setenv in between. Read the data
! 2158: from /proc/self/auxv. Or do the probing ourselves. The only thing
! 2159: extra that AT_HWCAP gives us is HWCAP_S390_HIGH_GPRS, which indicates
! 2160: that the kernel saves all 64-bits of the registers around traps while
! 2161: in 31-bit mode. But this is true of all "recent" kernels (ought to dig
! 2162: back and see from when this might not be true). */
! 2163:
! 2164: #include <signal.h>
! 2165:
! 2166: static volatile sig_atomic_t got_sigill;
! 2167:
! 2168: static void sigill_handler(int sig)
1.1 root 2169: {
1.1.1.2 ! root 2170: got_sigill = 1;
1.1 root 2171: }
2172:
1.1.1.2 ! root 2173: static void query_facilities(void)
1.1 root 2174: {
1.1.1.2 ! root 2175: struct sigaction sa_old, sa_new;
! 2176: register int r0 __asm__("0");
! 2177: register void *r1 __asm__("1");
! 2178: int fail;
! 2179:
! 2180: memset(&sa_new, 0, sizeof(sa_new));
! 2181: sa_new.sa_handler = sigill_handler;
! 2182: sigaction(SIGILL, &sa_new, &sa_old);
! 2183:
! 2184: /* First, try STORE FACILITY LIST EXTENDED. If this is present, then
! 2185: we need not do any more probing. Unfortunately, this itself is an
! 2186: extension and the original STORE FACILITY LIST instruction is
! 2187: kernel-only, storing its results at absolute address 200. */
! 2188: /* stfle 0(%r1) */
! 2189: r1 = &facilities;
! 2190: asm volatile(".word 0xb2b0,0x1000"
! 2191: : "=r"(r0) : "0"(0), "r"(r1) : "memory", "cc");
! 2192:
! 2193: if (got_sigill) {
! 2194: /* STORE FACILITY EXTENDED is not available. Probe for one of each
! 2195: kind of instruction that we're interested in. */
! 2196: /* ??? Possibly some of these are in practice never present unless
! 2197: the store-facility-extended facility is also present. But since
! 2198: that isn't documented it's just better to probe for each. */
! 2199:
! 2200: /* Test for z/Architecture. Required even in 31-bit mode. */
! 2201: got_sigill = 0;
! 2202: /* agr %r0,%r0 */
! 2203: asm volatile(".word 0xb908,0x0000" : "=r"(r0) : : "cc");
! 2204: if (!got_sigill) {
! 2205: facilities |= FACILITY_ZARCH_ACTIVE;
! 2206: }
! 2207:
! 2208: /* Test for long displacement. */
! 2209: got_sigill = 0;
! 2210: /* ly %r0,0(%r1) */
! 2211: r1 = &facilities;
! 2212: asm volatile(".word 0xe300,0x1000,0x0058"
! 2213: : "=r"(r0) : "r"(r1) : "cc");
! 2214: if (!got_sigill) {
! 2215: facilities |= FACILITY_LONG_DISP;
! 2216: }
! 2217:
! 2218: /* Test for extended immediates. */
! 2219: got_sigill = 0;
! 2220: /* afi %r0,0 */
! 2221: asm volatile(".word 0xc209,0x0000,0x0000" : : : "cc");
! 2222: if (!got_sigill) {
! 2223: facilities |= FACILITY_EXT_IMM;
! 2224: }
! 2225:
! 2226: /* Test for general-instructions-extension. */
! 2227: got_sigill = 0;
! 2228: /* msfi %r0,1 */
! 2229: asm volatile(".word 0xc201,0x0000,0x0001");
! 2230: if (!got_sigill) {
! 2231: facilities |= FACILITY_GEN_INST_EXT;
! 2232: }
! 2233: }
! 2234:
! 2235: sigaction(SIGILL, &sa_old, NULL);
! 2236:
! 2237: /* The translator currently uses these extensions unconditionally.
! 2238: Pruning this back to the base ESA/390 architecture doesn't seem
! 2239: worthwhile, since even the KVM target requires z/Arch. */
! 2240: fail = 0;
! 2241: if ((facilities & FACILITY_ZARCH_ACTIVE) == 0) {
! 2242: fprintf(stderr, "TCG: z/Arch facility is required.\n");
! 2243: fprintf(stderr, "TCG: Boot with a 64-bit enabled kernel.\n");
! 2244: fail = 1;
! 2245: }
! 2246: if ((facilities & FACILITY_LONG_DISP) == 0) {
! 2247: fprintf(stderr, "TCG: long-displacement facility is required.\n");
! 2248: fail = 1;
! 2249: }
! 2250:
! 2251: /* So far there's just enough support for 31-bit mode to let the
! 2252: compile succeed. This is good enough to run QEMU with KVM. */
! 2253: if (sizeof(void *) != 8) {
! 2254: fprintf(stderr, "TCG: 31-bit mode is not supported.\n");
! 2255: fail = 1;
! 2256: }
! 2257:
! 2258: if (fail) {
! 2259: exit(-1);
! 2260: }
1.1 root 2261: }
2262:
1.1.1.2 ! root 2263: static void tcg_target_init(TCGContext *s)
1.1 root 2264: {
1.1.1.2 ! root 2265: #if !defined(CONFIG_USER_ONLY)
! 2266: /* fail safe */
! 2267: if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry)) {
! 2268: tcg_abort();
! 2269: }
! 2270: #endif
! 2271:
! 2272: query_facilities();
! 2273:
! 2274: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
! 2275: tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
! 2276:
! 2277: tcg_regset_clear(tcg_target_call_clobber_regs);
! 2278: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0);
! 2279: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R1);
! 2280: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R2);
! 2281: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R3);
! 2282: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R4);
! 2283: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R5);
! 2284: /* The return register can be considered call-clobbered. */
! 2285: tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14);
! 2286:
! 2287: tcg_regset_clear(s->reserved_regs);
! 2288: tcg_regset_set_reg(s->reserved_regs, TCG_TMP0);
! 2289: /* XXX many insns can't be used with R0, so we better avoid it for now */
! 2290: tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0);
! 2291: tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
! 2292:
! 2293: tcg_add_target_add_op_defs(s390_op_defs);
! 2294: }
! 2295:
! 2296: static void tcg_target_qemu_prologue(TCGContext *s)
! 2297: {
! 2298: /* stmg %r6,%r15,48(%r15) (save registers) */
! 2299: tcg_out_insn(s, RXY, STMG, TCG_REG_R6, TCG_REG_R15, TCG_REG_R15, 48);
! 2300:
! 2301: /* aghi %r15,-160 (stack frame) */
! 2302: tcg_out_insn(s, RI, AGHI, TCG_REG_R15, -160);
! 2303:
! 2304: if (GUEST_BASE >= 0x80000) {
! 2305: tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
! 2306: tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
! 2307: }
! 2308:
! 2309: /* br %r2 (go to TB) */
! 2310: tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_R2);
! 2311:
! 2312: tb_ret_addr = s->code_ptr;
! 2313:
! 2314: /* lmg %r6,%r15,208(%r15) (restore registers) */
! 2315: tcg_out_insn(s, RXY, LMG, TCG_REG_R6, TCG_REG_R15, TCG_REG_R15, 208);
! 2316:
! 2317: /* br %r14 (return) */
! 2318: tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, TCG_REG_R14);
1.1 root 2319: }
2320:
2321: static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
2322: {
2323: tcg_abort();
2324: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.