From nobody Tue Sep 16 03:22:13 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=gmail.com ARC-Seal: i=1; a=rsa-sha256; t=1756225497; cv=none; d=zohomail.com; s=zohoarc; b=e2tzTh6v1zAW/aMBbcV+kSUnzxADyWv8td4k+QiiEz26sAwcpVKO6unW1oyXv9sjB+PB52f/5nEQnHexj4umJkWwtm4tO2NT4YguGOEaZImGZp+9LlWQfAqmU/5XnuJZ03px9ShZmG5FRDJiS+eYrZ/JsVEdchf4q2xxwssRVC0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1756225497; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=xmh/isBKa4ZFg3mNl1Ypgx0C/yjimFYLC8J+f5Zjo9M=; b=N07LYGAWypDmcT7QEoQcp74I+kMDKepMtcqsV6TC4fuHfN0s3acpN0vZKeVAdE5U+kPxS14iA2o4veFgoKHmlg0+wyeyusqt2h2rv4pbf/Y9ND8EIT9vmYiUDrIG/OXbRML6SQD8HvQRP1+0dBJhnxZDMUjEyl/GtAPxk3fu18M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1756225497398396.5301514709714; Tue, 26 Aug 2025 09:24:57 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1uqwHe-0004JJ-6c; Tue, 26 Aug 2025 12:12:30 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uqwHc-0004IM-6s; Tue, 26 Aug 2025 12:12:28 -0400 Received: from mail-pg1-x52f.google.com ([2607:f8b0:4864:20::52f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1uqwHZ-0007v4-43; Tue, 26 Aug 2025 12:12:27 -0400 Received: by mail-pg1-x52f.google.com with SMTP id 41be03b00d2f7-b4c3c36643aso240448a12.3; Tue, 26 Aug 2025 09:12:22 -0700 (PDT) Received: from ktock.. ([240d:1a:3b6:8b00:561f:1400:11f5:714b]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-32750bc341asm1749747a91.19.2025.08.26.09.12.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 26 Aug 2025 09:12:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1756224740; x=1756829540; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=xmh/isBKa4ZFg3mNl1Ypgx0C/yjimFYLC8J+f5Zjo9M=; b=d6gIOpzQ0SO1z4oN+Thh2z1NMMg2AK0Eg3Ov22ok69DKIhfRaLoppwMJOcFuqOVHdo pfCW8FlZi8IT6WKbNpdpdknDWuXTNlmiLBwnG6k89lTvvS4+ZuvD647cLyrKGXwz0xkx yAVq7k03+qnLtWVSDQWb1ldBq2+TUv2B9R74T1kcIY9Jc1Jhjhsb+Syz17hGZEqEoSwG Zz0GRXoDyezUO4lk1UlYn0aU7T8TF6w29qAemw9CJMlSHPOgaHVp2pHQQrJCHeR0GUZk 3aBpkJuJsZzR7Zkgzp3BLHCljI0kUBzTrQczn/0bMVMs/xR6yU5fr1wwQErEQSXReSm4 SC1Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1756224740; x=1756829540; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=xmh/isBKa4ZFg3mNl1Ypgx0C/yjimFYLC8J+f5Zjo9M=; b=Qz8NlH44fNOSnMuXwnaDi44iW1a2sXGqj/WfkuFvkscEROZgdanRqO2ulyvwSW3vjy 7lUkCFKNDChbb4xHOpvufYEgmgA1ewaEvQd77GnJMgY+V126dD5sEBMrerZBDneskvp1 ZeWWAdbb81GE688+5MWXx3/Zj0GBCC8/H6kgd/DPnccgwPnNnpmehE4pwuL6mSMT1f+L 2WTB99hTwE5tk9epscXUcaBUjC25eSoLKwCPFPZu2i7YOwkx2ggidB4GBDyMc5maecwR mJakRtr2kwNUMCKmNJXf6QxzyvHsiQDYR/Kjifu7OS00rX5Cq4kG/tHDTGxHiNskHfw2 +7Ug== X-Forwarded-Encrypted: i=1; AJvYcCVCIRIHoHh48gvyc7TU94yGsoMQDqmuJLxo1Aaq6V+iFXFU7pXZyM2JNpiqPtjxKSilfQLUiITh8g==@nongnu.org, AJvYcCVm7Dte3q2dJ0AjXVIWgWWqMW6FV0NlGJZjtki3PqMjFN5OWj194oZPOFMZUzILwnuWTp4hjilldyxxAg==@nongnu.org X-Gm-Message-State: AOJu0YzR09ASbnSE7Yv4dL0Q3Fh24QNDYr8Gdd+NexUZmm+gJHcuF1nK ybqb8ZPNYWerbeE33eX6gxvv49baNIlWNSayotcVfcP89A8tkXPSL5N5HFNE3Q== X-Gm-Gg: ASbGncuxCasfVhWuW6luSXDzrBAopzGkmZDxWSketihL1bqYmHdUzKjwXarezE0y7Ja 5QPQ8mZU54KWpOaNhYkEu1y1FcoBPxufPhJrwf+SFyuApm+EBYthJ9ofVGJSciHFCT6q/44dTJ0 9gyHK8oxVgKqp21tjMgNoIJ7v/BKiCBMrrsRquujvSt5UCTnkFnas35d0SgZTL9h0FZoSVeaOnF JWB+VGWWR25oHMMiI/i2QbUIbgRi98P9o8Sn8jQQ6+h7At7aYXHb2KuXDx7XUc8873r/9cHuS7r v9hjGYqEZwZmGEpPgDGz3Mk+gDg4cE1/VyHLR3G3PnHMn8CNS++WByF5O5cFtwtyAIhRU75LziL SFqOcHRHxlgnzLJmhYUQnEw== X-Google-Smtp-Source: AGHT+IHOjmPY9hbN9IjIowiaYbHiOb+tmSlp+lTaq4T2aDb5MExZ9C0bPGKf4uptBbCF9Kg82zhShw== X-Received: by 2002:a17:90b:3d10:b0:325:5e59:11b6 with SMTP id 98e67ed59e1d1-3255e5913f6mr13689135a91.14.1756224739538; Tue, 26 Aug 2025 09:12:19 -0700 (PDT) From: Kohei Tokunaga To: qemu-devel@nongnu.org Cc: =?UTF-8?q?Alex=20Benn=C3=A9e?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Thomas Huth , Paolo Bonzini , Richard Henderson , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Daniel=20P=20=2E=20Berrang=C3=A9?= , WANG Xuerui , Aurelien Jarno , Huacai Chen , Jiaxun Yang , Aleksandar Rikalo , Palmer Dabbelt , Alistair Francis , Stefan Weil , qemu-arm@nongnu.org, qemu-riscv@nongnu.org, Stefan Hajnoczi , Pierrick Bouvier , ktokunaga.mail@gmail.com Subject: [PATCH v2 12/35] tcg/wasm: Add setcond/negsetcond/movcond instructions Date: Wed, 27 Aug 2025 01:10:17 +0900 Message-ID: <9dbeb865a3d0a4cbf9b1e4c4da6c76d977bb927e.1756216429.git.ktokunaga.mail@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=2607:f8b0:4864:20::52f; envelope-from=ktokunaga.mail@gmail.com; helo=mail-pg1-x52f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @gmail.com) X-ZM-MESSAGEID: 1756225498687116600 Content-Type: text/plain; charset="utf-8" These TCG instructions are implemented by using Wasm's if and else instructions. TCI instructions are also generated in the same way as the original TCI backend. Since support for TCG_COND_TSTEQ and TCG_COND_TSTNE is not yet implemented, TCG_TARGET_HAS_tst is set to 0. Signed-off-by: Kohei Tokunaga --- tcg/wasm.c | 136 +++++++++++++++++++- tcg/wasm/tcg-target-has.h | 7 ++ tcg/wasm/tcg-target-opc.h.inc | 8 ++ tcg/wasm/tcg-target.c.inc | 230 ++++++++++++++++++++++++++++++++++ 4 files changed, 380 insertions(+), 1 deletion(-) create mode 100644 tcg/wasm/tcg-target-has.h create mode 100644 tcg/wasm/tcg-target-opc.h.inc V2: - This commit generates both Wasm and TCI instrucitons. - Fixed the neg implementation in the negsetcond operation to "ret =3D 0 - arg" diff --git a/tcg/wasm.c b/tcg/wasm.c index b63b88e011..183dad10a2 100644 --- a/tcg/wasm.c +++ b/tcg/wasm.c @@ -21,6 +21,12 @@ #include "qemu/osdep.h" #include "tcg/tcg.h" =20 +static void tci_args_rr(uint32_t insn, TCGReg *r0, TCGReg *r1) +{ + *r0 =3D extract32(insn, 8, 4); + *r1 =3D extract32(insn, 12, 4); +} + static void tci_args_rrr(uint32_t insn, TCGReg *r0, TCGReg *r1, TCGReg *r2) { *r0 =3D extract32(insn, 8, 4); @@ -37,6 +43,110 @@ static void tci_args_rrbb(uint32_t insn, TCGReg *r0, TC= GReg *r1, *i3 =3D extract32(insn, 22, 6); } =20 +static void tci_args_rrrc(uint32_t insn, + TCGReg *r0, TCGReg *r1, TCGReg *r2, TCGCond *c3) +{ + *r0 =3D extract32(insn, 8, 4); + *r1 =3D extract32(insn, 12, 4); + *r2 =3D extract32(insn, 16, 4); + *c3 =3D extract32(insn, 20, 4); +} + +static void tci_args_rrrrrc(uint32_t insn, TCGReg *r0, TCGReg *r1, + TCGReg *r2, TCGReg *r3, TCGReg *r4, TCGCond *c= 5) +{ + *r0 =3D extract32(insn, 8, 4); + *r1 =3D extract32(insn, 12, 4); + *r2 =3D extract32(insn, 16, 4); + *r3 =3D extract32(insn, 20, 4); + *r4 =3D extract32(insn, 24, 4); + *c5 =3D extract32(insn, 28, 4); +} + +static bool tci_compare32(uint32_t u0, uint32_t u1, TCGCond condition) +{ + bool result =3D false; + int32_t i0 =3D u0; + int32_t i1 =3D u1; + switch (condition) { + case TCG_COND_EQ: + result =3D (u0 =3D=3D u1); + break; + case TCG_COND_NE: + result =3D (u0 !=3D u1); + break; + case TCG_COND_LT: + result =3D (i0 < i1); + break; + case TCG_COND_GE: + result =3D (i0 >=3D i1); + break; + case TCG_COND_LE: + result =3D (i0 <=3D i1); + break; + case TCG_COND_GT: + result =3D (i0 > i1); + break; + case TCG_COND_LTU: + result =3D (u0 < u1); + break; + case TCG_COND_GEU: + result =3D (u0 >=3D u1); + break; + case TCG_COND_LEU: + result =3D (u0 <=3D u1); + break; + case TCG_COND_GTU: + result =3D (u0 > u1); + break; + default: + g_assert_not_reached(); + } + return result; +} + +static bool tci_compare64(uint64_t u0, uint64_t u1, TCGCond condition) +{ + bool result =3D false; + int64_t i0 =3D u0; + int64_t i1 =3D u1; + switch (condition) { + case TCG_COND_EQ: + result =3D (u0 =3D=3D u1); + break; + case TCG_COND_NE: + result =3D (u0 !=3D u1); + break; + case TCG_COND_LT: + result =3D (i0 < i1); + break; + case TCG_COND_GE: + result =3D (i0 >=3D i1); + break; + case TCG_COND_LE: + result =3D (i0 <=3D i1); + break; + case TCG_COND_GT: + result =3D (i0 > i1); + break; + case TCG_COND_LTU: + result =3D (u0 < u1); + break; + case TCG_COND_GEU: + result =3D (u0 >=3D u1); + break; + case TCG_COND_LEU: + result =3D (u0 <=3D u1); + break; + case TCG_COND_GTU: + result =3D (u0 > u1); + break; + default: + g_assert_not_reached(); + } + return result; +} + static uintptr_t tcg_qemu_tb_exec_tci(CPUArchState *env, const void *v_tb_= ptr) { const uint32_t *tb_ptr =3D v_tb_ptr; @@ -50,8 +160,10 @@ static uintptr_t tcg_qemu_tb_exec_tci(CPUArchState *env= , const void *v_tb_ptr) for (;;) { uint32_t insn; TCGOpcode opc; - TCGReg r0, r1, r2; + TCGReg r0, r1, r2, r3, r4; uint8_t pos, len; + TCGCond condition; + uint32_t tmp32; =20 insn =3D *tb_ptr++; opc =3D extract32(insn, 0, 8); @@ -102,6 +214,28 @@ static uintptr_t tcg_qemu_tb_exec_tci(CPUArchState *en= v, const void *v_tb_ptr) regs[r0] =3D ((tcg_target_long)regs[r1] >> (regs[r2] % TCG_TARGET_REG_BITS)); break; + case INDEX_op_neg: + tci_args_rr(insn, &r0, &r1); + regs[r0] =3D -regs[r1]; + break; + case INDEX_op_setcond: + tci_args_rrrc(insn, &r0, &r1, &r2, &condition); + regs[r0] =3D tci_compare64(regs[r1], regs[r2], condition); + break; + case INDEX_op_movcond: + tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition); + tmp32 =3D tci_compare64(regs[r1], regs[r2], condition); + regs[r0] =3D regs[tmp32 ? r3 : r4]; + break; + case INDEX_op_tci_setcond32: + tci_args_rrrc(insn, &r0, &r1, &r2, &condition); + regs[r0] =3D tci_compare32(regs[r1], regs[r2], condition); + break; + case INDEX_op_tci_movcond32: + tci_args_rrrrrc(insn, &r0, &r1, &r2, &r3, &r4, &condition); + tmp32 =3D tci_compare32(regs[r1], regs[r2], condition); + regs[r0] =3D regs[tmp32 ? r3 : r4]; + break; default: g_assert_not_reached(); } diff --git a/tcg/wasm/tcg-target-has.h b/tcg/wasm/tcg-target-has.h new file mode 100644 index 0000000000..7e3caf8790 --- /dev/null +++ b/tcg/wasm/tcg-target-has.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef TCG_TARGET_HAS_H +#define TCG_TARGET_HAS_H + +#define TCG_TARGET_HAS_tst 0 + +#endif diff --git a/tcg/wasm/tcg-target-opc.h.inc b/tcg/wasm/tcg-target-opc.h.inc new file mode 100644 index 0000000000..57274d4569 --- /dev/null +++ b/tcg/wasm/tcg-target-opc.h.inc @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Based on tci/tcg-target-opc.h.inc + * + * These opcodes for use between the tci generator and interpreter. + */ +DEF(tci_setcond32, 1, 2, 1, TCG_OPF_NOT_PRESENT) +DEF(tci_movcond32, 1, 2, 1, TCG_OPF_NOT_PRESENT) diff --git a/tcg/wasm/tcg-target.c.inc b/tcg/wasm/tcg-target.c.inc index 3a2a707619..70de3bbf83 100644 --- a/tcg/wasm/tcg-target.c.inc +++ b/tcg/wasm/tcg-target.c.inc @@ -137,9 +137,37 @@ static const uint8_t tcg_target_reg_index[TCG_TARGET_N= B_REGS] =3D { #define REG_IDX(r) tcg_target_reg_index[r] =20 typedef enum { + OPC_IF =3D 0x04, + OPC_ELSE =3D 0x05, + OPC_END =3D 0x0b, OPC_GLOBAL_GET =3D 0x23, OPC_GLOBAL_SET =3D 0x24, =20 + OPC_I32_CONST =3D 0x41, + OPC_I64_CONST =3D 0x42, + + OPC_I32_EQ =3D 0x46, + OPC_I32_NE =3D 0x47, + OPC_I32_LT_S =3D 0x48, + OPC_I32_LT_U =3D 0x49, + OPC_I32_GT_S =3D 0x4a, + OPC_I32_GT_U =3D 0x4b, + OPC_I32_LE_S =3D 0x4c, + OPC_I32_LE_U =3D 0x4d, + OPC_I32_GE_S =3D 0x4e, + OPC_I32_GE_U =3D 0x4f, + + OPC_I64_EQ =3D 0x51, + OPC_I64_NE =3D 0x52, + OPC_I64_LT_S =3D 0x53, + OPC_I64_LT_U =3D 0x54, + OPC_I64_GT_S =3D 0x55, + OPC_I64_GT_U =3D 0x56, + OPC_I64_LE_S =3D 0x57, + OPC_I64_LE_U =3D 0x58, + OPC_I64_GE_S =3D 0x59, + OPC_I64_GE_U =3D 0x5a, + OPC_I32_SHR_S =3D 0x75, OPC_I32_SHR_U =3D 0x76, =20 @@ -157,6 +185,10 @@ typedef enum { OPC_I64_EXTEND_I32_U =3D 0xad, } WasmInsn; =20 +typedef enum { + BLOCK_I64 =3D 0x7e, +} WasmBlockType; + #define BUF_SIZE 1024 typedef struct LinkedBufEntry { uint8_t data[BUF_SIZE]; @@ -191,6 +223,23 @@ static void linked_buf_out_leb128(LinkedBuf *p, uint64= _t v) } while (v !=3D 0); } =20 +static void linked_buf_out_sleb128(LinkedBuf *p, int64_t v) +{ + bool more =3D true; + uint8_t b; + while (more) { + b =3D v & 0x7f; + v >>=3D 7; + if (((v =3D=3D 0) && ((b & 0x40) =3D=3D 0)) || + ((v =3D=3D -1) && ((b & 0x40) !=3D 0))) { + more =3D false; + } else { + b |=3D 0x80; + } + linked_buf_out8(p, b); + } +} + /* * wasm code is generataed in the dynamically allocated buffer which * are managed as a linked list. @@ -209,6 +258,10 @@ static void tcg_wasm_out_leb128(TCGContext *s, uint64_= t v) { linked_buf_out_leb128(&sub_buf, v); } +static void tcg_wasm_out_sleb128(TCGContext *s, int64_t v) +{ + linked_buf_out_sleb128(&sub_buf, v); +} =20 static void tcg_wasm_out_op(TCGContext *s, WasmInsn opc) { @@ -219,6 +272,25 @@ static void tcg_wasm_out_op_idx(TCGContext *s, WasmIns= n opc, uint32_t idx) tcg_wasm_out8(s, opc); tcg_wasm_out_leb128(s, idx); } +static void tcg_wasm_out_op_block(TCGContext *s, WasmInsn opc, WasmBlockTy= pe t) +{ + tcg_wasm_out8(s, opc); + tcg_wasm_out8(s, t); +} +static void tcg_wasm_out_op_const(TCGContext *s, WasmInsn opc, int64_t v) +{ + tcg_wasm_out8(s, opc); + switch (opc) { + case OPC_I32_CONST: + tcg_wasm_out_sleb128(s, (int32_t)v); + break; + case OPC_I64_CONST: + tcg_wasm_out_sleb128(s, v); + break; + default: + g_assert_not_reached(); + } +} =20 static void tcg_wasm_out_o1_i2( TCGContext *s, WasmInsn opc, TCGReg ret, TCGReg arg1, TCGReg arg2) @@ -250,6 +322,85 @@ static void tcg_wasm_out_o1_i2_type( } } =20 +static const struct { + WasmInsn i32; + WasmInsn i64; +} tcg_cond_to_inst[] =3D { + [TCG_COND_EQ] =3D { OPC_I32_EQ, OPC_I64_EQ }, + [TCG_COND_NE] =3D { OPC_I32_NE, OPC_I64_NE }, + [TCG_COND_LT] =3D { OPC_I32_LT_S, OPC_I64_LT_S }, + [TCG_COND_GE] =3D { OPC_I32_GE_S, OPC_I64_GE_S }, + [TCG_COND_LE] =3D { OPC_I32_LE_S, OPC_I64_LE_S }, + [TCG_COND_GT] =3D { OPC_I32_GT_S, OPC_I64_GT_S }, + [TCG_COND_LTU] =3D { OPC_I32_LT_U, OPC_I64_LT_U }, + [TCG_COND_GEU] =3D { OPC_I32_GE_U, OPC_I64_GE_U }, + [TCG_COND_LEU] =3D { OPC_I32_LE_U, OPC_I64_LE_U }, + [TCG_COND_GTU] =3D { OPC_I32_GT_U, OPC_I64_GT_U } +}; + +static void tcg_wasm_out_cond( + TCGContext *s, TCGType type, TCGCond cond, TCGReg arg1, TCGReg arg2) +{ + switch (type) { + case TCG_TYPE_I32: + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg1)); + tcg_wasm_out_op(s, OPC_I32_WRAP_I64); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg2)); + tcg_wasm_out_op(s, OPC_I32_WRAP_I64); + tcg_wasm_out_op(s, tcg_cond_to_inst[cond].i32); + break; + case TCG_TYPE_I64: + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg1)); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(arg2)); + tcg_wasm_out_op(s, tcg_cond_to_inst[cond].i64); + break; + default: + g_assert_not_reached(); + } +} + +static void tcg_wasm_out_setcond(TCGContext *s, TCGType type, TCGReg ret, + TCGReg arg1, TCGReg arg2, TCGCond cond) +{ + tcg_wasm_out_cond(s, type, cond, arg1, arg2); + tcg_wasm_out_op(s, OPC_I64_EXTEND_I32_U); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); +} + +static void tcg_wasm_out_negsetcond(TCGContext *s, TCGType type, TCGReg re= t, + TCGReg arg1, TCGReg arg2, TCGCond cond) +{ + tcg_wasm_out_op_const(s, OPC_I64_CONST, 0); + tcg_wasm_out_cond(s, type, cond, arg1, arg2); + tcg_wasm_out_op(s, OPC_I64_EXTEND_I32_U); + tcg_wasm_out_op(s, OPC_I64_SUB); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); +} + +static void tcg_wasm_out_movcond(TCGContext *s, TCGType type, TCGReg ret, + TCGReg c1, TCGReg c2, + TCGReg v1, TCGReg v2, + TCGCond cond) +{ + tcg_wasm_out_cond(s, type, cond, c1, c2); + tcg_wasm_out_op_block(s, OPC_IF, BLOCK_I64); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(v1)); + tcg_wasm_out_op(s, OPC_ELSE); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_GET, REG_IDX(v2)); + tcg_wasm_out_op(s, OPC_END); + tcg_wasm_out_op_idx(s, OPC_GLOBAL_SET, REG_IDX(ret)); +} + +static void tcg_out_op_rr(TCGContext *s, TCGOpcode op, TCGReg r0, TCGReg r= 1) +{ + tcg_insn_unit_tci insn =3D 0; + + insn =3D deposit32(insn, 0, 8, op); + insn =3D deposit32(insn, 8, 4, r0); + insn =3D deposit32(insn, 12, 4, r1); + tcg_out32(s, insn); +} + static void tcg_out_op_rrr(TCGContext *s, TCGOpcode op, TCGReg r0, TCGReg r1, TCGReg r2) { @@ -277,6 +428,35 @@ static void tcg_out_op_rrbb(TCGContext *s, TCGOpcode o= p, TCGReg r0, tcg_out32(s, insn); } =20 +static void tcg_out_op_rrrc(TCGContext *s, TCGOpcode op, + TCGReg r0, TCGReg r1, TCGReg r2, TCGCond c3) +{ + tcg_insn_unit_tci insn =3D 0; + + insn =3D deposit32(insn, 0, 8, op); + insn =3D deposit32(insn, 8, 4, r0); + insn =3D deposit32(insn, 12, 4, r1); + insn =3D deposit32(insn, 16, 4, r2); + insn =3D deposit32(insn, 20, 4, c3); + tcg_out32(s, insn); +} + +static void tcg_out_op_rrrrrc(TCGContext *s, TCGOpcode op, + TCGReg r0, TCGReg r1, TCGReg r2, + TCGReg r3, TCGReg r4, TCGCond c5) +{ + tcg_insn_unit_tci insn =3D 0; + + insn =3D deposit32(insn, 0, 8, op); + insn =3D deposit32(insn, 8, 4, r0); + insn =3D deposit32(insn, 12, 4, r1); + insn =3D deposit32(insn, 16, 4, r2); + insn =3D deposit32(insn, 20, 4, r3); + insn =3D deposit32(insn, 24, 4, r4); + insn =3D deposit32(insn, 28, 4, c5); + tcg_out32(s, insn); +} + static void tgen_and(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { @@ -397,6 +577,56 @@ static const TCGOutOpBinary outop_sar =3D { .out_rrr =3D tgen_sar, }; =20 +static void tgen_setcond_tci(TCGContext *s, TCGType type, TCGCond cond, + TCGReg dest, TCGReg arg1, TCGReg arg2) +{ + TCGOpcode opc =3D (type =3D=3D TCG_TYPE_I32 + ? INDEX_op_tci_setcond32 + : INDEX_op_setcond); + tcg_out_op_rrrc(s, opc, dest, arg1, arg2, cond); +} + +static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond, + TCGReg dest, TCGReg arg1, TCGReg arg2) +{ + tgen_setcond_tci(s, type, cond, dest, arg1, arg2); + tcg_wasm_out_setcond(s, type, dest, arg1, arg2, cond); +} + +static const TCGOutOpSetcond outop_setcond =3D { + .base.static_constraint =3D C_O1_I2(r, r, r), + .out_rrr =3D tgen_setcond, +}; + +static void tgen_negsetcond(TCGContext *s, TCGType type, TCGCond cond, + TCGReg dest, TCGReg arg1, TCGReg arg2) +{ + tgen_setcond_tci(s, type, cond, dest, arg1, arg2); + tcg_out_op_rr(s, INDEX_op_neg, dest, dest); + tcg_wasm_out_negsetcond(s, type, dest, arg1, arg2, cond); +} + +static const TCGOutOpSetcond outop_negsetcond =3D { + .base.static_constraint =3D C_O1_I2(r, r, r), + .out_rrr =3D tgen_negsetcond, +}; + +static void tgen_movcond(TCGContext *s, TCGType type, TCGCond cond, + TCGReg ret, TCGReg c1, TCGArg c2, bool const_c2, + TCGArg vt, bool const_vt, TCGArg vf, bool consf_v= f) +{ + TCGOpcode opc =3D (type =3D=3D TCG_TYPE_I32 + ? INDEX_op_tci_movcond32 + : INDEX_op_movcond); + tcg_out_op_rrrrrc(s, opc, ret, c1, c2, vt, vf, cond); + tcg_wasm_out_movcond(s, type, ret, c1, c2, vt, vf, cond); +} + +static const TCGOutOpMovcond outop_movcond =3D { + .base.static_constraint =3D C_O1_I4(r, r, r, r, r), + .out =3D tgen_movcond, +}; + static void tcg_out_tb_start(TCGContext *s) { init_sub_buf(); --=20 2.43.0