From patchwork Thu May 27 20:45:59 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 53810 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9A37FB7D24 for ; Fri, 28 May 2010 07:28:03 +1000 (EST) Received: from localhost ([127.0.0.1]:45473 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OHkQk-00073W-SF for incoming@patchwork.ozlabs.org; Thu, 27 May 2010 17:15:55 -0400 Received: from [140.186.70.92] (port=55887 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OHjz0-0001xF-Of for qemu-devel@nongnu.org; Thu, 27 May 2010 16:47:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OHjyx-0005HR-K9 for qemu-devel@nongnu.org; Thu, 27 May 2010 16:47:14 -0400 Received: from are.twiddle.net ([75.149.56.221]:51194) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OHjyw-0005H8-Vk for qemu-devel@nongnu.org; Thu, 27 May 2010 16:47:11 -0400 Received: from anchor.twiddle.home (anchor.twiddle.home [172.31.0.4]) by are.twiddle.net (Postfix) with ESMTPS id 619A6A32; Thu, 27 May 2010 13:47:10 -0700 (PDT) Received: from anchor.twiddle.home (anchor.twiddle.home [127.0.0.1]) by anchor.twiddle.home (8.14.4/8.14.4) with ESMTP id o4RKl9lT030905; Thu, 27 May 2010 13:47:09 -0700 Received: (from rth@localhost) by anchor.twiddle.home (8.14.4/8.14.4/Submit) id o4RKl9Hx030904; Thu, 27 May 2010 13:47:09 -0700 From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 27 May 2010 13:45:59 -0700 Message-Id: <1274993204-30766-18-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 1.7.0.1 In-Reply-To: <1274993204-30766-1-git-send-email-rth@twiddle.net> References: <1274993204-30766-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) Cc: agraf@suse.de, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH 17/62] tcg-s390: Reorganize instruction emission X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Tie the opcode names to the format, and arrange for moderate compile-time checking that the instruction format output routine matches the format used by the opcode. Signed-off-by: Richard Henderson --- tcg/s390/tcg-target.c | 625 +++++++++++++++++++++++-------------------------- tcg/s390/tcg-target.h | 5 +- 2 files changed, 297 insertions(+), 333 deletions(-) diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c index e0a0e73..0deb332 100644 --- a/tcg/s390/tcg-target.c +++ b/tcg/s390/tcg-target.c @@ -36,64 +36,86 @@ #define TCG_CT_CONST_S16 0x100 #define TCG_CT_CONST_U12 0x200 -#define E3_LG 0x04 -#define E3_LRVG 0x0f -#define E3_LGF 0x14 -#define E3_LGH 0x15 -#define E3_LLGF 0x16 -#define E3_LRV 0x1e -#define E3_LRVH 0x1f -#define E3_CG 0x20 -#define E3_STG 0x24 -#define E3_STRVG 0x2f -#define E3_STRV 0x3e -#define E3_STRVH 0x3f -#define E3_STHY 0x70 -#define E3_STCY 0x72 -#define E3_LGB 0x77 -#define E3_LLGC 0x90 -#define E3_LLGH 0x91 - -#define B9_LGR 0x04 -#define B9_AGR 0x08 -#define B9_SGR 0x09 -#define B9_MSGR 0x0c -#define B9_LGFR 0x14 -#define B9_LLGFR 0x16 -#define B9_CGR 0x20 -#define B9_CLGR 0x21 -#define B9_NGR 0x80 -#define B9_OGR 0x81 -#define B9_XGR 0x82 -#define B9_DLGR 0x87 -#define B9_DLR 0x97 - -#define RR_BASR 0x0d -#define RR_NR 0x14 -#define RR_CLR 0x15 -#define RR_OR 0x16 -#define RR_XR 0x17 -#define RR_LR 0x18 -#define RR_CR 0x19 -#define RR_AR 0x1a -#define RR_SR 0x1b - -#define A7_AHI 0xa -#define A7_AHGI 0xb - -#define SH64_REG_NONE 0x00 /* use immediate only (not R0!) */ -#define SH64_SRAG 0x0a -#define SH64_SRLG 0x0c -#define SH64_SLLG 0x0d - -#define SH32_REG_NONE 0x00 /* use immediate only (not R0!) */ -#define SH32_SRL 0x08 -#define SH32_SLL 0x09 -#define SH32_SRA 0x0a - -#define ST_STH 0x40 -#define ST_STC 0x42 -#define ST_ST 0x50 +/* All of the following instructions are prefixed with their instruction + format, and are defined as 8- or 16-bit quantities, even when the two + halves of the 16-bit quantity may appear 32 bits apart in the insn. + This makes it easy to copy the values from the tables in Appendix B. */ +typedef enum S390Opcode { + RIL_LARL = 0xc000, + RIL_BRASL = 0xc005, + + RI_AGHI = 0xa70b, + RI_AHI = 0xa70a, + RI_BRC = 0xa704, + RI_IILH = 0xa502, + RI_LGHI = 0xa709, + RI_LLILL = 0xa50f, + + RRE_AGR = 0xb908, + RRE_CGR = 0xb920, + RRE_CLGR = 0xb921, + RRE_DLGR = 0xb987, + RRE_DLR = 0xb997, + RRE_DSGFR = 0xb91d, + RRE_DSGR = 0xb90d, + RRE_LCGR = 0xb903, + RRE_LGFR = 0xb914, + RRE_LGR = 0xb904, + RRE_LLGFR = 0xb916, + RRE_MSGR = 0xb90c, + RRE_MSR = 0xb252, + RRE_NGR = 0xb980, + RRE_OGR = 0xb981, + RRE_SGR = 0xb909, + RRE_XGR = 0xb982, + + RR_AR = 0x1a, + RR_BASR = 0x0d, + RR_BCR = 0x07, + RR_CLR = 0x15, + RR_CR = 0x19, + RR_LCR = 0x13, + RR_LR = 0x18, + RR_NR = 0x14, + RR_OR = 0x16, + RR_SR = 0x1b, + RR_XR = 0x17, + + RSY_SLLG = 0xeb0d, + RSY_SRAG = 0xeb0a, + RSY_SRLG = 0xeb0c, + + RS_SLL = 0x89, + RS_SRA = 0x8a, + RS_SRL = 0x88, + + RXY_CG = 0xe320, + RXY_LG = 0xe304, + RXY_LGB = 0xe377, + RXY_LGF = 0xe314, + RXY_LGH = 0xe315, + RXY_LLGC = 0xe390, + RXY_LLGF = 0xe316, + RXY_LLGH = 0xe391, + RXY_LMG = 0xeb04, + RXY_LRV = 0xe31e, + RXY_LRVG = 0xe30f, + RXY_LRVH = 0xe31f, + RXY_STCY = 0xe372, + RXY_STG = 0xe324, + RXY_STHY = 0xe370, + RXY_STMG = 0xeb24, + RXY_STRV = 0xe33e, + RXY_STRVG = 0xe32f, + RXY_STRVH = 0xe33f, + + RX_ST = 0x50, + RX_STC = 0x42, + RX_STH = 0x40, +} S390Opcode; + +#define SH32_REG_NONE 0 +#define SH64_REG_NONE 0 #define LD_SIGNED 0x04 #define LD_UINT8 0x00 @@ -105,14 +127,6 @@ #define LD_UINT64 0x03 #define LD_INT64 (LD_UINT64 | LD_SIGNED) -#define S390_INS_BCR 0x0700 -#define S390_INS_BR (S390_INS_BCR | 0x00f0) -#define S390_INS_IILH 0xa5020000 -#define S390_INS_LLILL 0xa50f0000 -#define S390_INS_LGHI 0xa7090000 -#define S390_INS_MSR 0xb2520000 -#define S390_INS_LARL 0xc000 - #ifndef NDEBUG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", @@ -204,7 +218,7 @@ static void patch_reloc(uint8_t *code_ptr, int type, } static int tcg_target_get_call_iarg_regs_count(int flags) - { +{ return sizeof(tcg_target_call_iarg_regs) / sizeof(int); } @@ -240,7 +254,7 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str) /* Test if a constant matches the constraint. */ static inline int tcg_target_const_match(tcg_target_long val, - const TCGArgConstraint *arg_ct) + const TCGArgConstraint *arg_ct) { int ct = arg_ct->ct; @@ -253,60 +267,77 @@ static inline int tcg_target_const_match(tcg_target_long val, return 0; } -/* emit load/store (and then some) instructions (E3 prefix) */ -static void tcg_out_e3(TCGContext* s, int op, int r1, int r2, int disp) +/* Emit instructions according to the given instruction format. */ + +static void tcg_out_insn_RR(TCGContext *s, S390Opcode op, TCGReg r1, TCGReg r2) { - tcg_out16(s, 0xe300 | (r1 << 4)); - tcg_out32(s, op | (r2 << 28) | ((disp & 0xfff) << 16) | ((disp >> 12) << 8)); + tcg_out16(s, (op << 8) | (r1 << 4) | r2); } -/* emit 64-bit register/register insns (B9 prefix) */ -static void tcg_out_b9(TCGContext* s, int op, int r1, int r2) +static void tcg_out_insn_RRE(TCGContext *s, S390Opcode op, + TCGReg r1, TCGReg r2) { - tcg_out32(s, 0xb9000000 | (op << 16) | (r1 << 4) | r2); + tcg_out32(s, (op << 16) | (r1 << 4) | r2); } -/* emit (mostly) 32-bit register/register insns */ -static void tcg_out_rr(TCGContext* s, int op, int r1, int r2) +static void tcg_out_insn_RI(TCGContext *s, S390Opcode op, TCGReg r1, int i2) { - tcg_out16(s, (op << 8) | (r1 << 4) | r2); + tcg_out32(s, (op << 16) | (r1 << 20) | (i2 & 0xffff)); } -static void tcg_out_a7(TCGContext *s, int op, int r1, int16_t i2) +static void tcg_out_insn_RIL(TCGContext *s, S390Opcode op, TCGReg r1, int i2) { - tcg_out32(s, 0xa7000000UL | (r1 << 20) | (op << 16) | ((uint16_t)i2)); + tcg_out16(s, op | (r1 << 4)); + tcg_out32(s, i2); } -/* emit 64-bit shifts (EB prefix) */ -static void tcg_out_sh64(TCGContext* s, int op, int r0, int r1, int r2, int imm) +static void tcg_out_insn_RS(TCGContext *s, S390Opcode op, TCGReg r1, + TCGReg b2, TCGReg r3, int disp) { - tcg_out16(s, 0xeb00 | (r0 << 4) | r1); - tcg_out32(s, op | (r2 << 28) | ((imm & 0xfff) << 16) | ((imm >> 12) << 8)); + tcg_out32(s, (op << 24) | (r1 << 20) | (r3 << 16) | (b2 << 12) + | (disp & 0xfff)); } -/* emit 32-bit shifts */ -static void tcg_out_sh32(TCGContext* s, int op, int r0, int r1, int imm) +static void tcg_out_insn_RSY(TCGContext *s, S390Opcode op, TCGReg r1, + TCGReg b2, TCGReg r3, int disp) { - tcg_out32(s, 0x80000000 | (op << 24) | (r0 << 20) | (r1 << 12) | imm); + tcg_out16(s, (op & 0xff00) | (r1 << 4) | r3); + tcg_out32(s, (op & 0xff) | (b2 << 28) + | ((disp & 0xfff) << 16) | ((disp & 0xff000) >> 4)); } -/* branch to relative address (long) */ -static void tcg_out_brasl(TCGContext* s, int r, tcg_target_long raddr) +#define tcg_out_insn_RX tcg_out_insn_RS +#define tcg_out_insn_RXY tcg_out_insn_RSY + +/* Emit an opcode with "type-checking" of the format. */ +#define tcg_out_insn(S, FMT, OP, ...) \ + glue(tcg_out_insn_,FMT)(S, glue(glue(FMT,_),OP), ## __VA_ARGS__) + + +/* emit 64-bit shifts */ +static void tcg_out_sh64(TCGContext* s, S390Opcode op, TCGReg dest, + TCGReg src, TCGReg sh_reg, int sh_imm) +{ + tcg_out_insn_RSY(s, op, dest, sh_reg, src, sh_imm); +} + +/* emit 32-bit shifts */ +static void tcg_out_sh32(TCGContext* s, S390Opcode op, TCGReg dest, + TCGReg sh_reg, int sh_imm) { - tcg_out16(s, 0xc005 | (r << 4)); - tcg_out32(s, raddr >> 1); + tcg_out_insn_RS(s, op, dest, sh_reg, 0, sh_imm); } -/* store 8/16/32 bits */ -static void tcg_out_store(TCGContext* s, int op, int r0, int r1, int off) +/* branch to relative address (long) */ +static void tcg_out_brasl(TCGContext *s, TCGReg r, tcg_target_long raddr) { - tcg_out32(s, (op << 24) | (r0 << 20) | (r1 << 12) | off); + tcg_out_insn(s, RIL, BRASL, r, raddr >> 1); } static inline void tcg_out_mov(TCGContext *s, int ret, int arg) { /* ??? With a TCGType argument, we could emit the smaller LR insn. */ - tcg_out_b9(s, B9_LGR, ret, arg); + tcg_out_insn(s, RRE, LGR, ret, arg); } /* load a register with an immediate value */ @@ -314,48 +345,39 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, int ret, tcg_target_long arg) { if (arg >= -0x8000 && arg < 0x8000) { /* signed immediate load */ - /* lghi %rret, arg */ - tcg_out32(s, S390_INS_LGHI | (ret << 20) | (arg & 0xffff)); + tcg_out_insn(s, RI, LGHI, ret, arg); } else if (!(arg & 0xffffffffffff0000UL)) { - /* llill %rret, arg */ - tcg_out32(s, S390_INS_LLILL | (ret << 20) | arg); + tcg_out_insn(s, RI, LLILL, ret, arg); } else if (!(arg & 0xffffffff00000000UL) || type == TCG_TYPE_I32) { - /* llill %rret, arg */ - tcg_out32(s, S390_INS_LLILL | (ret << 20) | (arg & 0xffff)); - /* iilh %rret, arg */ - tcg_out32(s, S390_INS_IILH | (ret << 20) | ((arg & 0xffffffff) >> 16)); + tcg_out_insn(s, RI, LLILL, ret, arg); + tcg_out_insn(s, RI, IILH, ret, arg >> 16); } else { /* branch over constant and store its address in R13 */ tcg_out_brasl(s, TCG_REG_R13, 14); /* 64-bit constant */ - tcg_out32(s,arg >> 32); - tcg_out32(s,arg); + tcg_out32(s, arg >> 32); + tcg_out32(s, arg); /* load constant to ret */ - tcg_out_e3(s, E3_LG, ret, TCG_REG_R13, 0); + tcg_out_insn(s, RXY, LG, ret, TCG_REG_R13, 0, 0); } } /* load data without address translation or endianness conversion */ -static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg, - int arg1, tcg_target_long arg2) +static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data, + TCGReg base, tcg_target_long ofs) { - int op; - - dprintf("tcg_out_ld type %d arg %d arg1 %d arg2 %ld\n", - type, arg, arg1, arg2); + S390Opcode op; - op = (type == TCG_TYPE_I32) ? E3_LLGF : E3_LG; + op = (type == TCG_TYPE_I32) ? RXY_LLGF : RXY_LG; - if (arg2 < -0x80000 || arg2 > 0x7ffff) { + if (ofs < -0x80000 || ofs > 0x7ffff) { /* load the displacement */ - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, arg2); - /* add the address */ - tcg_out_b9(s, B9_AGR, TCG_REG_R13, arg1); + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, ofs); /* load the data */ - tcg_out_e3(s, op, arg, TCG_REG_R13, 0); + tcg_out_insn_RXY(s, op, data, base, TCG_REG_R13, 0); } else { /* load the data */ - tcg_out_e3(s, op, arg, arg1, arg2); + tcg_out_insn_RXY(s, op, data, base, 0, ofs); } } @@ -377,23 +399,23 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, int data_reg, int addr_reg, } #if TARGET_LONG_BITS == 32 - tcg_out_b9(s, B9_LLGFR, arg1, addr_reg); - tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); + tcg_out_insn(s, RRE, LLGFR, arg1, addr_reg); + tcg_out_insn(s, RRE, LLGFR, arg0, addr_reg); #else tcg_out_mov(s, arg1, addr_reg); tcg_out_mov(s, arg0, addr_reg); #endif - tcg_out_sh64(s, SH64_SRLG, arg1, addr_reg, SH64_REG_NONE, + tcg_out_sh64(s, RSY_SRLG, arg1, addr_reg, SH64_REG_NONE, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS); tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, TARGET_PAGE_MASK | ((1 << s_bits) - 1)); - tcg_out_b9(s, B9_NGR, arg0, TCG_REG_R13); + tcg_out_insn(s, RRE, NGR, arg0, TCG_REG_R13); tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS); - tcg_out_b9(s, B9_NGR, arg1, TCG_REG_R13); + tcg_out_insn(s, RRE, NGR, arg1, TCG_REG_R13); if (is_store) { tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, @@ -402,20 +424,20 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, int data_reg, int addr_reg, tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, offsetof(CPUState, tlb_table[mem_index][0].addr_read)); } - tcg_out_b9(s, B9_AGR, arg1, TCG_REG_R13); + tcg_out_insn(s, RRE, AGR, arg1, TCG_REG_R13); - tcg_out_b9(s, B9_AGR, arg1, TCG_AREG0); + tcg_out_insn(s, RRE, AGR, arg1, TCG_AREG0); - tcg_out_e3(s, E3_CG, arg0, arg1, 0); + tcg_out_insn(s, RXY, CG, arg0, arg1, 0, 0); label1_ptr = (uint16_t*)s->code_ptr; /* je label1 (offset will be patched in later) */ - tcg_out32(s, 0xa7840000); + tcg_out_insn(s, RI, BRC, 8, 0); /* call load/store helper */ #if TARGET_LONG_BITS == 32 - tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); + tcg_out_insn(s, RRE, LLGFR, arg0, addr_reg); #else tcg_out_mov(s, arg0, addr_reg); #endif @@ -425,25 +447,25 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, int data_reg, int addr_reg, tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index); tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_ulong)qemu_st_helpers[s_bits]); - tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); + tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_REG_R13); } else { tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index); tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (tcg_target_ulong)qemu_ld_helpers[s_bits]); - tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); + tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_REG_R13); /* sign extension */ switch (opc) { case LD_INT8: - tcg_out_sh64(s, SH64_SLLG, data_reg, arg0, SH64_REG_NONE, 56); - tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 56); + tcg_out_insn(s, RSY, SLLG, data_reg, arg0, SH64_REG_NONE, 56); + tcg_out_insn(s, RSY, SRAG, data_reg, data_reg, SH64_REG_NONE, 56); break; case LD_INT16: - tcg_out_sh64(s, SH64_SLLG, data_reg, arg0, SH64_REG_NONE, 48); - tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 48); + tcg_out_insn(s, RSY, SLLG, data_reg, arg0, SH64_REG_NONE, 48); + tcg_out_insn(s, RSY, SRAG, data_reg, data_reg, SH64_REG_NONE, 48); break; case LD_INT32: - tcg_out_b9(s, B9_LGFR, data_reg, arg0); + tcg_out_insn(s, RRE, LGFR, data_reg, arg0); break; default: /* unsigned -> just copy */ @@ -455,33 +477,34 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, int data_reg, int addr_reg, /* jump to label2 (end) */ *label2_ptr_p = (uint16_t*)s->code_ptr; - /* bras %r13, label2 */ - tcg_out32(s, 0xa7d50000); + tcg_out_insn(s, RI, BRC, 15, 0); /* this is label1, patch branch */ *(label1_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label1_ptr) >> 1; if (is_store) { - tcg_out_e3(s, E3_LG, arg1, arg1, offsetof(CPUTLBEntry, addend) - - offsetof(CPUTLBEntry, addr_write)); + tcg_out_insn(s, RXY, LG, arg1, arg1, 0, + offsetof(CPUTLBEntry, addend) + - offsetof(CPUTLBEntry, addr_write)); } else { - tcg_out_e3(s, E3_LG, arg1, arg1, offsetof(CPUTLBEntry, addend) - - offsetof(CPUTLBEntry, addr_read)); + tcg_out_insn(s, RXY, LG, arg1, arg1, 0, + offsetof(CPUTLBEntry, addend) + - offsetof(CPUTLBEntry, addr_read)); } #if TARGET_LONG_BITS == 32 /* zero upper 32 bits */ - tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); + tcg_out_insn(s, RRE, LLGFR, arg0, addr_reg); #else /* just copy */ tcg_out_mov(s, arg0, addr_reg); #endif - tcg_out_b9(s, B9_AGR, arg0, arg1); - } - + tcg_out_insn(s, RRE, AGR, arg0, arg1); +} + static void tcg_finish_qemu_ldst(TCGContext* s, uint16_t *label2_ptr) - { +{ /* patch branch */ *(label2_ptr + 1) = ((unsigned long)s->code_ptr - (unsigned long)label2_ptr) >> 1; @@ -497,7 +520,7 @@ static void tcg_prepare_qemu_ldst(TCGContext* s, int data_reg, int addr_reg, /* user mode, no address translation required */ if (TARGET_LONG_BITS == 32) { - tcg_out_b9(s, B9_LLGFR, arg0, addr_reg); + tcg_out_insn(s, RRE, LLGFR, arg0, addr_reg); } else { tcg_out_mov(s, arg0, addr_reg); } @@ -529,54 +552,54 @@ static void tcg_out_qemu_ld(TCGContext* s, const TCGArg* args, int opc) switch (opc) { case LD_UINT8: - tcg_out_e3(s, E3_LLGC, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LLGC, data_reg, arg0, 0, 0); break; case LD_INT8: - tcg_out_e3(s, E3_LGB, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LGB, data_reg, arg0, 0, 0); break; case LD_UINT16: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_e3(s, E3_LLGH, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LLGH, data_reg, arg0, 0, 0); #else /* swapped unsigned halfword load with upper bits zeroed */ - tcg_out_e3(s, E3_LRVH, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LRVH, data_reg, arg0, 0, 0); tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, 0xffffL); - tcg_out_b9(s, B9_NGR, data_reg, 13); + tcg_out_insn(s, RRE, NGR, data_reg, 13); #endif break; case LD_INT16: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_e3(s, E3_LGH, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LGH, data_reg, arg0, 0, 0); #else /* swapped sign-extended halfword load */ - tcg_out_e3(s, E3_LRVH, data_reg, arg0, 0); - tcg_out_sh64(s, SH64_SLLG, data_reg, data_reg, SH64_REG_NONE, 48); - tcg_out_sh64(s, SH64_SRAG, data_reg, data_reg, SH64_REG_NONE, 48); + tcg_out_insn(s, RXY, LRVH, data_reg, arg0, 0, 0); + tcg_out_insn(s, RSY, SLLG, data_reg, data_reg, SH64_REG_NONE, 48); + tcg_out_insn(s, RSY, SRAG, data_reg, data_reg, SH64_REG_NONE, 48); #endif break; case LD_UINT32: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_e3(s, E3_LLGF, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LLGF, data_reg, arg0, 0, 0); #else /* swapped unsigned int load with upper bits zeroed */ - tcg_out_e3(s, E3_LRV, data_reg, arg0, 0); - tcg_out_b9(s, B9_LLGFR, data_reg, data_reg); + tcg_out_insn(s, RXY, LRV, data_reg, arg0, 0, 0); + tcg_out_insn(s, RRE, LLGFR, data_reg, data_reg); #endif break; case LD_INT32: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_e3(s, E3_LGF, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LGF, data_reg, arg0, 0, 0); #else /* swapped sign-extended int load */ - tcg_out_e3(s, E3_LRV, data_reg, arg0, 0); - tcg_out_b9(s, B9_LGFR, data_reg, data_reg); + tcg_out_insn(s, RXY, LRV, data_reg, arg0, 0, 0); + tcg_out_insn(s, RRE, LGFR, data_reg, data_reg); #endif break; case LD_UINT64: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_e3(s, E3_LG, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LG, data_reg, arg0, 0, 0); #else - tcg_out_e3(s, E3_LRVG, data_reg, arg0, 0); + tcg_out_insn(s, RXY, LRVG, data_reg, arg0, 0, 0); #endif break; default: @@ -604,27 +627,27 @@ static void tcg_out_qemu_st(TCGContext* s, const TCGArg* args, int opc) switch (opc) { case LD_UINT8: - tcg_out_store(s, ST_STC, data_reg, arg0, 0); + tcg_out_insn(s, RX, STC, data_reg, arg0, 0, 0); break; case LD_UINT16: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_store(s, ST_STH, data_reg, arg0, 0); + tcg_out_insn(s, RX, STH, data_reg, arg0, 0, 0); #else - tcg_out_e3(s, E3_STRVH, data_reg, arg0, 0); + tcg_out_insn(s, RXY, STRVH, data_reg, arg0, 0, 0); #endif break; case LD_UINT32: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_store(s, ST_ST, data_reg, arg0, 0); + tcg_out_insn(s, RX, ST, data_reg, arg0, 0, 0); #else - tcg_out_e3(s, E3_STRV, data_reg, arg0, 0); + tcg_out_insn(s, RXY, STRV, data_reg, arg0, 0, 0); #endif break; case LD_UINT64: #ifdef TARGET_WORDS_BIGENDIAN - tcg_out_e3(s, E3_STG, data_reg, arg0, 0); + tcg_out_insn(s, RXY, STG, data_reg, arg0, 0, 0); #else - tcg_out_e3(s, E3_STRVG, data_reg, arg0, 0); + tcg_out_insn(s, RXY, STRVG, data_reg, arg0, 0, 0); #endif break; default: @@ -642,17 +665,17 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, int arg, if (type == TCG_TYPE_I32) { if (((long)arg2) < -0x800 || ((long)arg2) > 0x7ff) { tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, arg2); - tcg_out_b9(s, B9_AGR, 13, arg1); - tcg_out_store(s, ST_ST, arg, TCG_REG_R13, 0); + tcg_out_insn(s, RRE, AGR, 13, arg1); + tcg_out_insn(s, RX, ST, arg, TCG_REG_R13, 0, 0); } else { - tcg_out_store(s, ST_ST, arg, arg1, arg2); + tcg_out_insn(s, RX, ST, arg, arg1, 0, arg2); } } else { if (((long)arg2) < -0x80000 || ((long)arg2) > 0x7ffff) { tcg_abort(); } - tcg_out_e3(s, E3_STG, arg, arg1, arg2); + tcg_out_insn(s, RXY, STG, arg, arg1, 0, arg2); } } @@ -660,25 +683,18 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, const int *const_args) { TCGLabel* l; - int op; - int op2; - - dprintf("0x%x\n", INDEX_op_divu_i32); + S390Opcode op, op2; switch (opc) { case INDEX_op_exit_tb: - dprintf("op 0x%x exit_tb 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* return value */ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, args[0]); tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, (unsigned long)tb_ret_addr); /* br %r13 */ - tcg_out16(s, S390_INS_BR | TCG_REG_R13); + tcg_out_insn(s, RR, BCR, 15, TCG_REG_R13); break; case INDEX_op_goto_tb: - dprintf("op 0x%x goto_tb 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (s->tb_jmp_offset) { tcg_abort(); } else { @@ -686,9 +702,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, (tcg_target_long)s->code_ptr) >> 1; if (off > -0x80000000L && off < 0x7fffffffL) { /* load address relative to PC */ - /* larl %r13, off */ - tcg_out16(s, S390_INS_LARL | (TCG_REG_R13 << 4)); - tcg_out32(s, off); + tcg_out_insn(s, RIL, LARL, TCG_REG_R13, off); } else { /* too far for larl */ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, @@ -697,14 +711,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, /* load address stored at s->tb_next + args[0] */ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R13, TCG_REG_R13, 0); /* and go there */ - tcg_out_rr(s, RR_BASR, TCG_REG_R13, TCG_REG_R13); + tcg_out_insn(s, RR, BASR, TCG_REG_R13, TCG_REG_R13); } s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf; break; case INDEX_op_call: - dprintf("op 0x%x call 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (const_args[0]) { tcg_target_long off; @@ -718,27 +730,23 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, } else { /* too far for a relative call, load full address */ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[0]); - tcg_out_rr(s, RR_BASR, TCG_REG_R14, TCG_REG_R13); + tcg_out_insn(s, RR, BASR, TCG_REG_R14, TCG_REG_R13); } } else { /* call function in register args[0] */ - tcg_out_rr(s, RR_BASR, TCG_REG_R14, args[0]); + tcg_out_insn(s, RR, BASR, TCG_REG_R14, args[0]); } break; case INDEX_op_jmp: - dprintf("op 0x%x jmp 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* XXX */ tcg_abort(); break; case INDEX_op_ld8u_i32: case INDEX_op_ld8u_i64: - dprintf("op 0x%x ld8u_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { - tcg_out_e3(s, E3_LLGC, args[0], args[1], args[2]); + tcg_out_insn(s, RXY, LLGC, args[0], args[1], 0, args[2]); } else { /* XXX displacement too large, have to calculate address manually */ tcg_abort(); @@ -746,17 +754,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_ld8s_i32: - dprintf("op 0x%x ld8s_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* XXX */ tcg_abort(); break; case INDEX_op_ld16u_i32: - dprintf("op 0x%x ld16u_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if ((long)args[2] > -0x80000 && (long)args[2] < 0x7ffff) { - tcg_out_e3(s, E3_LLGH, args[0], args[1], args[2]); + tcg_out_insn(s, RXY, LLGH, args[0], args[1], 0, args[2]); } else { /* XXX displacement too large, have to calculate address manually */ tcg_abort(); @@ -764,8 +768,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_ld16s_i32: - dprintf("op 0x%x ld16s_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* XXX */ tcg_abort(); break; @@ -780,12 +782,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, /* load the displacement */ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, args[2]); /* add the address */ - tcg_out_b9(s, B9_AGR, TCG_REG_R13, args[1]); + tcg_out_insn(s, RRE, AGR, TCG_REG_R13, args[1]); /* load the data (sign-extended) */ - tcg_out_e3(s, E3_LGF, args[0], TCG_REG_R13, 0); + tcg_out_insn(s, RXY, LGF, args[0], TCG_REG_R13, 0, 0); } else { /* load the data (sign-extended) */ - tcg_out_e3(s, E3_LGF, args[0], args[1], args[2]); + tcg_out_insn(s, RXY, LGF, args[0], args[1], 0, args[2]); } break; @@ -795,13 +797,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_st8_i32: case INDEX_op_st8_i64: - dprintf("op 0x%x st8_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) { - tcg_out_store(s, ST_STC, args[0], args[1], args[2]); + tcg_out_insn(s, RX, STC, args[0], args[1], 0, args[2]); } else if (((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { /* FIXME: requires long displacement facility */ - tcg_out_e3(s, E3_STCY, args[0], args[1], args[2]); + tcg_out_insn(s, RXY, STCY, args[0], args[1], 0, args[2]); tcg_abort(); } else { tcg_abort(); @@ -810,13 +810,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_st16_i32: case INDEX_op_st16_i64: - dprintf("op 0x%x st16_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (((long)args[2]) >= -0x800 && ((long)args[2]) < 0x800) { - tcg_out_store(s, ST_STH, args[0], args[1], args[2]); + tcg_out_insn(s, RX, STH, args[0], args[1], 0, args[2]); } else if (((long)args[2]) >= -0x80000 && ((long)args[2]) < 0x80000) { /* FIXME: requires long displacement facility */ - tcg_out_e3(s, E3_STHY, args[0], args[1], args[2]); + tcg_out_insn(s, RXY, STHY, args[0], args[1], 0, args[2]); tcg_abort(); } else { tcg_abort(); @@ -833,15 +831,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, break; case INDEX_op_mov_i32: - dprintf("op 0x%x mov_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* XXX */ tcg_abort(); break; case INDEX_op_movi_i32: - dprintf("op 0x%x movi_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* XXX */ tcg_abort(); break; @@ -849,164 +843,144 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_add_i32: if (const_args[2]) { if (args[0] == args[1]) { - tcg_out_a7(s, A7_AHI, args[1], args[2]); + tcg_out_insn(s, RI, AHI, args[1], args[2]); } else { - tcg_out_rr(s, RR_LR, args[0], args[1]); - tcg_out_a7(s, A7_AHI, args[0], args[2]); + tcg_out_insn(s, RR, LR, args[0], args[1]); + tcg_out_insn(s, RI, AHI, args[0], args[2]); } } else if (args[0] == args[1]) { - tcg_out_rr(s, RR_AR, args[1], args[2]); + tcg_out_insn(s, RR, AR, args[1], args[2]); } else if (args[0] == args[2]) { - tcg_out_rr(s, RR_AR, args[0], args[1]); + tcg_out_insn(s, RR, AR, args[0], args[1]); } else { - tcg_out_rr(s, RR_LR, args[0], args[1]); - tcg_out_rr(s, RR_AR, args[0], args[2]); + tcg_out_insn(s, RR, LR, args[0], args[1]); + tcg_out_insn(s, RR, AR, args[0], args[2]); } break; case INDEX_op_sub_i32: - dprintf("op 0x%x sub_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (args[0] == args[1]) { /* sr %ra0/1, %ra2 */ - tcg_out_rr(s, RR_SR, args[1], args[2]); + tcg_out_insn(s, RR, SR, args[1], args[2]); } else if (args[0] == args[2]) { /* lr %r13, %raa0/2 */ - tcg_out_rr(s, RR_LR, TCG_REG_R13, args[2]); + tcg_out_insn(s, RR, LR, TCG_REG_R13, args[2]); /* lr %ra0/2, %ra1 */ - tcg_out_rr(s, RR_LR, args[0], args[1]); + tcg_out_insn(s, RR, LR, args[0], args[1]); /* sr %ra0/2, %r13 */ - tcg_out_rr(s, RR_SR, args[0], TCG_REG_R13); + tcg_out_insn(s, RR, SR, args[0], TCG_REG_R13); } else { /* lr %ra0, %ra1 */ - tcg_out_rr(s, RR_LR, args[0], args[1]); + tcg_out_insn(s, RR, LR, args[0], args[1]); /* sr %ra0, %ra2 */ - tcg_out_rr(s, RR_SR, args[0], args[2]); + tcg_out_insn(s, RR, SR, args[0], args[2]); } break; case INDEX_op_sub_i64: - dprintf("op 0x%x sub_i64 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (args[0] == args[1]) { /* sgr %ra0/1, %ra2 */ - tcg_out_b9(s, B9_SGR, args[1], args[2]); + tcg_out_insn(s, RRE, SGR, args[1], args[2]); } else if (args[0] == args[2]) { tcg_out_mov(s, TCG_REG_R13, args[2]); tcg_out_mov(s, args[0], args[1]); /* sgr %ra0/2, %r13 */ - tcg_out_b9(s, B9_SGR, args[0], TCG_REG_R13); + tcg_out_insn(s, RRE, SGR, args[0], TCG_REG_R13); } else { tcg_out_mov(s, args[0], args[1]); /* sgr %ra0, %ra2 */ - tcg_out_b9(s, B9_SGR, args[0], args[2]); + tcg_out_insn(s, RRE, SGR, args[0], args[2]); } break; case INDEX_op_add_i64: - dprintf("op 0x%x add_i64 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (args[0] == args[1]) { - tcg_out_b9(s, B9_AGR, args[1], args[2]); + tcg_out_insn(s, RRE, AGR, args[1], args[2]); } else if (args[0] == args[2]) { - tcg_out_b9(s, B9_AGR, args[0], args[1]); + tcg_out_insn(s, RRE, AGR, args[0], args[1]); } else { tcg_out_mov(s, args[0], args[1]); - tcg_out_b9(s, B9_AGR, args[0], args[2]); + tcg_out_insn(s, RRE, AGR, args[0], args[2]); } break; case INDEX_op_and_i32: op = RR_NR; -do_logic_i32: + do_logic_i32: if (args[0] == args[1]) { /* xr %ra0/1, %ra2 */ - tcg_out_rr(s, op, args[1], args[2]); + tcg_out_insn_RR(s, op, args[1], args[2]); } else if (args[0] == args[2]) { /* xr %ra0/2, %ra1 */ - tcg_out_rr(s, op, args[0], args[1]); + tcg_out_insn_RR(s, op, args[0], args[1]); } else { /* lr %ra0, %ra1 */ - tcg_out_rr(s, RR_LR, args[0], args[1]); + tcg_out_insn(s, RR, LR, args[0], args[1]); /* xr %ra0, %ra2 */ - tcg_out_rr(s, op, args[0], args[2]); + tcg_out_insn_RR(s, op, args[0], args[2]); } break; case INDEX_op_or_i32: op = RR_OR; goto do_logic_i32; - case INDEX_op_xor_i32: op = RR_XR; goto do_logic_i32; case INDEX_op_and_i64: - dprintf("op 0x%x and_i64 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); - op = B9_NGR; -do_logic_i64: + op = RRE_NGR; + do_logic_i64: if (args[0] == args[1]) { - tcg_out_b9(s, op, args[0], args[2]); + tcg_out_insn_RRE(s, op, args[0], args[2]); } else if (args[0] == args[2]) { - tcg_out_b9(s, op, args[0], args[1]); + tcg_out_insn_RRE(s, op, args[0], args[1]); } else { tcg_out_mov(s, args[0], args[1]); - tcg_out_b9(s, op, args[0], args[2]); + tcg_out_insn_RRE(s, op, args[0], args[2]); } break; case INDEX_op_or_i64: - op = B9_OGR; + op = RRE_OGR; goto do_logic_i64; - case INDEX_op_xor_i64: - op = B9_XGR; + op = RRE_XGR; goto do_logic_i64; case INDEX_op_neg_i32: - dprintf("op 0x%x neg_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* FIXME: optimize args[0] != args[1] case */ - tcg_out_rr(s, RR_LR, 13, args[1]); - /* lghi %ra0, 0 */ - tcg_out32(s, S390_INS_LGHI | (args[0] << 20)); - tcg_out_rr(s, RR_SR, args[0], 13); + tcg_out_insn(s, RR, LR, 13, args[1]); + tcg_out_movi(s, TCG_TYPE_I32, args[0], 0); + tcg_out_insn(s, RR, SR, args[0], 13); break; case INDEX_op_neg_i64: - dprintf("op 0x%x neg_i64 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); /* FIXME: optimize args[0] != args[1] case */ tcg_out_mov(s, TCG_REG_R13, args[1]); - /* lghi %ra0, 0 */ - tcg_out32(s, S390_INS_LGHI | (args[0] << 20)); - tcg_out_b9(s, B9_SGR, args[0], TCG_REG_R13); + tcg_out_movi(s, TCG_TYPE_I64, args[0], 0); + tcg_out_insn(s, RRE, SGR, args[0], TCG_REG_R13); break; case INDEX_op_mul_i32: - dprintf("op 0x%x mul_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (args[0] == args[1]) /* msr %ra0/1, %ra2 */ - tcg_out32(s, S390_INS_MSR | (args[0] << 4) | args[2]); + tcg_out_insn(s, RRE, MSR, args[0], args[2]); else if (args[0] == args[2]) /* msr %ra0/2, %ra1 */ - tcg_out32(s, S390_INS_MSR | (args[0] << 4) | args[1]); + tcg_out_insn(s, RRE, MSR, args[0], args[1]); else { - tcg_out_rr(s, RR_LR, args[0], args[1]); + tcg_out_insn(s, RR, LR, args[0], args[1]); /* msr %ra0, %ra2 */ - tcg_out32(s, S390_INS_MSR | (args[0] << 4) | args[2]); + tcg_out_insn(s, RRE, MSR, args[0], args[2]); } break; case INDEX_op_mul_i64: - dprintf("op 0x%x mul_i64 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); if (args[0] == args[1]) { - tcg_out_b9(s, B9_MSGR, args[0], args[2]); + tcg_out_insn(s, RRE, MSGR, args[0], args[2]); } else if (args[0] == args[2]) { - tcg_out_b9(s, B9_MSGR, args[0], args[1]); + tcg_out_insn(s, RRE, MSGR, args[0], args[1]); } else { /* XXX */ tcg_abort(); @@ -1015,27 +989,25 @@ do_logic_i64: case INDEX_op_divu_i32: case INDEX_op_remu_i32: - dprintf("op 0x%x div/remu_i32 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R12, 0); - tcg_out_rr(s, RR_LR, TCG_REG_R13, args[1]); - tcg_out_b9(s, B9_DLR, TCG_REG_R12, args[2]); + tcg_out_insn(s, RR, LR, TCG_REG_R13, args[1]); + tcg_out_insn(s, RRE, DLR, TCG_REG_R12, args[2]); if (opc == INDEX_op_divu_i32) { - tcg_out_rr(s, RR_LR, args[0], TCG_REG_R13); /* quotient */ + tcg_out_insn(s, RR, LR, args[0], TCG_REG_R13); /* quotient */ } else { - tcg_out_rr(s, RR_LR, args[0], TCG_REG_R12); /* remainder */ + tcg_out_insn(s, RR, LR, args[0], TCG_REG_R12); /* remainder */ } break; case INDEX_op_shl_i32: - op = SH32_SLL; - op2 = SH64_SLLG; - do_shift32: + op = RS_SLL; + op2 = RSY_SLLG; + do_shift32: if (const_args[2]) { if (args[0] == args[1]) { tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]); } else { - tcg_out_rr(s, RR_LR, args[0], args[1]); + tcg_out_insn(s, RR, LR, args[0], args[1]); tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]); } } else { @@ -1048,18 +1020,18 @@ do_logic_i64: break; case INDEX_op_shr_i32: - op = SH32_SRL; - op2 = SH64_SRLG; + op = RS_SRL; + op2 = RSY_SRLG; goto do_shift32; case INDEX_op_sar_i32: - op = SH32_SRA; - op2 = SH64_SRAG; + op = RS_SRA; + op2 = RSY_SRAG; goto do_shift32; case INDEX_op_shl_i64: - op = SH64_SLLG; - do_shift64: + op = RSY_SLLG; + do_shift64: if (const_args[2]) { tcg_out_sh64(s, op, args[0], args[1], SH64_REG_NONE, args[2]); } else { @@ -1068,67 +1040,60 @@ do_logic_i64: break; case INDEX_op_shr_i64: - op = SH64_SRLG; + op = RSY_SRLG; goto do_shift64; case INDEX_op_sar_i64: - op = SH64_SRAG; + op = RSY_SRAG; goto do_shift64; case INDEX_op_br: - dprintf("op 0x%x br 0x%lx 0x%lx 0x%lx\n", - opc, args[0], args[1], args[2]); l = &s->labels[args[0]]; if (l->has_value) { tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, l->u.value); } else { /* larl %r13, ... */ - tcg_out16(s, S390_INS_LARL | (TCG_REG_R13 << 4)); + tcg_out16(s, RIL_LARL | (TCG_REG_R13 << 4)); tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, args[0], -2); s->code_ptr += 4; } - tcg_out_rr(s, RR_BASR, TCG_REG_R13, TCG_REG_R13); + tcg_out_insn(s, RR, BASR, TCG_REG_R13, TCG_REG_R13); break; case INDEX_op_brcond_i64: - dprintf("op 0x%x brcond_i64 0x%lx 0x%lx (c %d) 0x%lx\n", - opc, args[0], args[1], const_args[1], args[2]); if (args[2] > TCG_COND_GT) { - /* unsigned */ - /* clgr %ra0, %ra1 */ - tcg_out_b9(s, B9_CLGR, args[0], args[1]); + /* unsigned */ + /* clgr %ra0, %ra1 */ + tcg_out_insn(s, RRE, CLGR, args[0], args[1]); } else { - /* signed */ - /* cgr %ra0, %ra1 */ - tcg_out_b9(s, B9_CGR, args[0], args[1]); + /* signed */ + /* cgr %ra0, %ra1 */ + tcg_out_insn(s, RRE, CGR, args[0], args[1]); } goto do_brcond; case INDEX_op_brcond_i32: - dprintf("op 0x%x brcond_i32 0x%lx 0x%lx (c %d) 0x%lx\n", - opc, args[0], args[1], const_args[1], args[2]); if (args[2] > TCG_COND_GT) { - /* unsigned */ - /* clr %ra0, %ra1 */ - tcg_out_rr(s, RR_CLR, args[0], args[1]); + /* unsigned */ + /* clr %ra0, %ra1 */ + tcg_out_insn(s, RR, CLR, args[0], args[1]); } else { - /* signed */ - /* cr %ra0, %ra1 */ - tcg_out_rr(s, RR_CR, args[0], args[1]); + /* signed */ + /* cr %ra0, %ra1 */ + tcg_out_insn(s, RR, CR, args[0], args[1]); } - do_brcond: + do_brcond: l = &s->labels[args[3]]; if (l->has_value) { tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R13, l->u.value); } else { /* larl %r13, ... */ - tcg_out16(s, S390_INS_LARL | (TCG_REG_R13 << 4)); + tcg_out16(s, RIL_LARL | (TCG_REG_R13 << 4)); tcg_out_reloc(s, s->code_ptr, R_390_PC32DBL, args[3], -2); s->code_ptr += 4; } /* bcr cond, %r13 */ - tcg_out16(s, S390_INS_BCR | TCG_REG_R13 | - (tcg_cond_to_s390_cond[args[2]] << 4)); + tcg_out_insn(s, RR, BCR, tcg_cond_to_s390_cond[args[2]], TCG_REG_R13); break; case INDEX_op_qemu_ld8u: @@ -1306,23 +1271,21 @@ void tcg_target_init(TCGContext *s) void tcg_target_qemu_prologue(TCGContext *s) { /* stmg %r6,%r15,48(%r15) (save registers) */ - tcg_out16(s, 0xeb6f); - tcg_out32(s, 0xf0300024); + tcg_out_insn(s, RXY, STMG, TCG_REG_R6, TCG_REG_R15, TCG_REG_R15, 48); /* aghi %r15,-160 (stack frame) */ - tcg_out32(s, 0xa7fbff60); + tcg_out_insn(s, RI, AGHI, TCG_REG_R15, -160); /* br %r2 (go to TB) */ - tcg_out16(s, S390_INS_BR | TCG_REG_R2); + tcg_out_insn(s, RR, BCR, 15, TCG_REG_R2); tb_ret_addr = s->code_ptr; /* lmg %r6,%r15,208(%r15) (restore registers) */ - tcg_out16(s, 0xeb6f); - tcg_out32(s, 0xf0d00004); + tcg_out_insn(s, RXY, LMG, TCG_REG_R6, TCG_REG_R15, TCG_REG_R15, 208); /* br %r14 (return) */ - tcg_out16(s, S390_INS_BR | TCG_REG_R14); + tcg_out_insn(s, RR, BCR, 15, TCG_REG_R14); } static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val) diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h index 7495258..c81f886 100644 --- a/tcg/s390/tcg-target.h +++ b/tcg/s390/tcg-target.h @@ -26,7 +26,7 @@ #define TCG_TARGET_REG_BITS 64 #define TCG_TARGET_WORDS_BIGENDIAN -enum { +typedef enum TCGReg { TCG_REG_R0 = 0, TCG_REG_R1, TCG_REG_R2, @@ -43,7 +43,8 @@ enum { TCG_REG_R13, TCG_REG_R14, TCG_REG_R15 -}; +} TCGReg; + #define TCG_TARGET_NB_REGS 16 /* optional instructions */