From patchwork Wed Nov 22 15:25:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lyut Nersisyan X-Patchwork-Id: 168412 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:612c:2b07:b0:403:3b70:6f57 with SMTP id io7csp1403015vqb; Wed, 22 Nov 2023 07:25:33 -0800 (PST) X-Google-Smtp-Source: AGHT+IEcouIWOHX6vLyVrk3OE39K8sEVG6Oky5Z09MACs0I5FAPcmWk0bIeLiIkyRb8nAVTUzyQL X-Received: by 2002:ac8:444f:0:b0:423:80b2:858 with SMTP id m15-20020ac8444f000000b0042380b20858mr1220253qtn.36.1700666733138; Wed, 22 Nov 2023 07:25:33 -0800 (PST) Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id fg22-20020a05622a581600b00423745f1117si2654981qtb.712.2023.11.22.07.25.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Nov 2023 07:25:33 -0800 (PST) Received-SPF: pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20230601 header.b="RlApeBF/"; arc=fail (body hash mismatch); spf=pass (google.com: domain of binutils-bounces+ouuuleilei=gmail.com@sourceware.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="binutils-bounces+ouuuleilei=gmail.com@sourceware.org"; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DE0683858024 for ; Wed, 22 Nov 2023 15:25:32 +0000 (GMT) X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mail-yb1-xb30.google.com (mail-yb1-xb30.google.com [IPv6:2607:f8b0:4864:20::b30]) by sourceware.org (Postfix) with ESMTPS id 7865E3858C50 for ; Wed, 22 Nov 2023 15:25:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7865E3858C50 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7865E3858C50 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::b30 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700666728; cv=none; b=uBAzl1vuH1Ob66nkOzLbQ1FxED/h1GhlnfS+1ZKu5keZikYMwt80RXnbZ/YslmYLyo4n71z8IsO1GWlRcfNXyHEoPYXS5530dAEO7YmN8uvkljkV4yiq2bgHeHFggb4tVEsYd7aKKBjwXD354RbmKXlLMjN0yB38zrATrDhytOQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1700666728; c=relaxed/simple; bh=H1OFJ01J2pJ+uGvm9qf/6Hqj3MUlHUjui9y2JWeqNew=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=ALfbhda4DMTyusdFA4o4xaFjhZGen/4iuvicGjaWGx7w1V4whAj6M/kv+QIqxOKpQ10Eo30TqFnaSR3bJ8zErGA1MdZo6Un6CMvZMPFhi2EB1HmtvWIcN401pDbOvP+2gJA/mCHxA1dwPpWZ6p3tgOy3wFYgmf47DhZK8eXyJco= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-yb1-xb30.google.com with SMTP id 3f1490d57ef6-db35caa1749so4715465276.2 for ; Wed, 22 Nov 2023 07:25:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1700666725; x=1701271525; darn=sourceware.org; h=cc:to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=H1OFJ01J2pJ+uGvm9qf/6Hqj3MUlHUjui9y2JWeqNew=; b=RlApeBF/vIJOQz/Vx+Ul1PV30J4sqKriu0sR5SN/dWbtN8GMf6U8KA/Y+V7D4YS8TM j/XpRlKRF3T/wLLjDbMdYVqmU+qIcKR8Uc228bkXbhkDU9FFYcp8N7lZOTtNm12Tq3xp SHNHDfR0RE16vCSVo6U9MLMPeK+syVEfJHHgdX++uK9/HP6VNy6y4i3kzotjquBHFW4v RXmCOkgN+n08pPqX7Rz9BUgoywSc/kHMqHI/TldbMHPJoyLuTT+NwEjR+QTCvji7eVrF A5OGNOX14Eww/3hoRsKu1lsKK6ODEYeEhUD0dTk68R+p+fj6bval3ucEbqBMQVLkM+/l Pinw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1700666725; x=1701271525; h=cc:to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=H1OFJ01J2pJ+uGvm9qf/6Hqj3MUlHUjui9y2JWeqNew=; b=U5fOQliq+rPHKPjeC1l18kQe1n72rgCUStZZGkwQlh3LO4sxkpk0OfFVap+0h7aGkp Zfg8JdKhSGCmmsPTSUubyL8zeATFPHfOaAm/KviFmzE+4km56488fAM+OVf9DNRs0dZ2 64Ipi3zEIUDFtXN7ncXWagUJi9+Q5Q0E8s0cbvAQkHnUIm3kS3syx0pCVoZ5+C/YYKSA u5agQCWUPvSG12vfGTtTKNZ4GDiK3iqZk5W7oOq+AcmJrtph6J7HV18etCO9rSyQvwhS HygNrcAgHdkYChNBGM3yws+V+BUE1n0ExZMVJ0CfU+1ohRUuZyOVmJDHS25yDCtSnQto iIXg== X-Gm-Message-State: AOJu0YxxOrTCQUq4wisE2YwMSULOsDze7fseCwnYipY5xGRj74fX0Yok gpjQW2NKuUrMLjxHY+ec2708VOndCU1kLIm5v2HpnWDDiDGyZw== X-Received: by 2002:a5b:3c8:0:b0:d9b:311f:e9cc with SMTP id t8-20020a5b03c8000000b00d9b311fe9ccmr2334438ybp.34.1700666724689; Wed, 22 Nov 2023 07:25:24 -0800 (PST) MIME-Version: 1.0 From: Lyut Nersisyan Date: Wed, 22 Nov 2023 19:25:14 +0400 Message-ID: Subject: [REVIEW ONLY] UNRATIFIED RISC-V: Add support for the 'Zimop' extension To: binutils@sourceware.org Cc: sevak.sargsyan@rau.am, jivanhakobyan9@gmail.com, jlaw@ventanamicro.com X-Spam-Status: No, score=-9.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: binutils-bounces+ouuuleilei=gmail.com@sourceware.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1783278320335641483 X-GMAIL-MSGID: 1783278320335641483 [DO NOT MERGE] Until this extension is frozen/ratified and final version number is determined, this patch should not be merged upstream. This commit uses unratified version 0.1 as in the documentation file name (instead of possible 1.0 after ratification). The 'Zimop' extension provides may be operations instructions. This commit adds instruction and extension support for this extension. This is based on the draft specification: bfd/ChangeLog: * elfxx-riscv.c (riscv_supported_std_z_ext): Add 'Zimop' to the supported list. (riscv_multi_subset_supports, riscv_multi_subset_supports_ext): Add handling for new instruction class. gas/ChangeLog: * testsuite/gas/riscv/zimop.s: New test. * testsuite/gas/riscv/zalasr-32.d: Likewise. * testsuite/gas/riscv/zalasr-64.d: Likewise. include/ChangeLog: * opcode/riscv-opc.h (MATCH_MOP_R_[0...31], MASK_MOP_R, MATCH_MOP_RR_[0...7], MASK_MOP_RR): New. * opcode/riscv.h (enum riscv_insn_class): Add new instruction class INSN_CLASS_ZIMOP. opcodes/ChangeLog: * riscv-opc.c (riscv_opcodes): Add instructions from the 'Zimop' extension. diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c index c9acf124626..cacb793820f 100644 --- a/bfd/elfxx-riscv.c +++ b/bfd/elfxx-riscv.c @@ -1268,6 +1268,7 @@ static struct riscv_supported_ext riscv_supported_std_z_ext[] = {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 }, {"zmmul", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zawrs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, + {"zimop", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 }, {"zfa", ISA_SPEC_CLASS_DRAFT, 0, 1, 0 }, {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, @@ -2421,6 +2422,8 @@ riscv_multi_subset_supports (riscv_parse_subset_t *rps, return riscv_subset_supports (rps, "a"); case INSN_CLASS_ZAWRS: return riscv_subset_supports (rps, "zawrs"); + case INSN_CLASS_ZIMOP: + return riscv_subset_supports (rps, "zimop"); case INSN_CLASS_F: return riscv_subset_supports (rps, "f"); case INSN_CLASS_D: @@ -2635,6 +2638,8 @@ riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps, return "a"; case INSN_CLASS_ZAWRS: return "zawrs"; + case INSN_CLASS_ZIMOP: + return "zimop"; case INSN_CLASS_F: return "f"; case INSN_CLASS_D: diff --git a/gas/testsuite/gas/riscv/zimop-32.d b/gas/testsuite/gas/riscv/zimop-32.d new file mode 100644 index 00000000000..9420a4f1f38 --- /dev/null +++ b/gas/testsuite/gas/riscv/zimop-32.d @@ -0,0 +1,12 @@ +#as: -march=rv32gc_zimop +#source: zimop.s +#objdump: -d + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000 : +[ ]+0:[ ]+81c5c573[ ]+mop.r.0[ ]+a0,a1 +[ ]+4:[ ]+ced64573[ ]+mop.rr.7[ ]+a0,a2,a3 diff --git a/gas/testsuite/gas/riscv/zimop-64.d b/gas/testsuite/gas/riscv/zimop-64.d new file mode 100644 index 00000000000..1d6d6f9f8f3 --- /dev/null +++ b/gas/testsuite/gas/riscv/zimop-64.d @@ -0,0 +1,12 @@ +#as: -march=rv64gc_zimop +#source: zimop.s +#objdump: -d + +.*:[ ]+file format .* + + +Disassembly of section .text: + +0+000 : +[ ]+0:[ ]+81c5c573[ ]+mop.r.0[ ]+a0,a1 +[ ]+4:[ ]+ced64573[ ]+mop.rr.7[ ]+a0,a2,a3 diff --git a/gas/testsuite/gas/riscv/zimop.s b/gas/testsuite/gas/riscv/zimop.s new file mode 100644 index 00000000000..2333a56715c --- /dev/null +++ b/gas/testsuite/gas/riscv/zimop.s @@ -0,0 +1,3 @@ +target: + mop.r.0 a0, a1 + mop.rr.7 a0, a2, a3 diff --git a/include/opcode/riscv-opc.h b/include/opcode/riscv-opc.h index 24217062edc..63ba34472bc 100644 --- a/include/opcode/riscv-opc.h +++ b/include/opcode/riscv-opc.h @@ -2320,6 +2320,49 @@ #define MASK_WRS_NTO 0xffffffff #define MATCH_WRS_STO 0x01d00073 #define MASK_WRS_STO 0xffffffff +/* Zimop instructions. */ +#define MATCH_MOP_R_0 0x81c04073 +#define MATCH_MOP_R_1 0x81d04073 +#define MATCH_MOP_R_2 0x81e04073 +#define MATCH_MOP_R_3 0x81f04073 +#define MATCH_MOP_R_4 0x85c04073 +#define MATCH_MOP_R_5 0x85d04073 +#define MATCH_MOP_R_6 0x85e04073 +#define MATCH_MOP_R_7 0x85f04073 +#define MATCH_MOP_R_8 0x89c04073 +#define MATCH_MOP_R_9 0x89d04073 +#define MATCH_MOP_R_10 0x89e04073 +#define MATCH_MOP_R_11 0x89f04073 +#define MATCH_MOP_R_12 0x8dc04073 +#define MATCH_MOP_R_13 0x8dd04073 +#define MATCH_MOP_R_14 0x8de04073 +#define MATCH_MOP_R_15 0x8df04073 +#define MATCH_MOP_R_16 0xc1c04073 +#define MATCH_MOP_R_17 0xc1d04073 +#define MATCH_MOP_R_18 0xc1e04073 +#define MATCH_MOP_R_19 0xc1f04073 +#define MATCH_MOP_R_20 0xc5c04073 +#define MATCH_MOP_R_21 0xc5d04073 +#define MATCH_MOP_R_22 0xc5e04073 +#define MATCH_MOP_R_23 0xc5f04073 +#define MATCH_MOP_R_24 0xc9c04073 +#define MATCH_MOP_R_25 0xc9d04073 +#define MATCH_MOP_R_26 0xc9e04073 +#define MATCH_MOP_R_27 0xc9f04073 +#define MATCH_MOP_R_28 0xcdc04073 +#define MATCH_MOP_R_29 0xcdd04073 +#define MATCH_MOP_R_30 0xcde04073 +#define MATCH_MOP_R_31 0xcdf04073 +#define MASK_MOP_R 0xfff0707f +#define MATCH_MOP_RR_0 0x82004073 +#define MATCH_MOP_RR_1 0x86004073 +#define MATCH_MOP_RR_2 0x8a004073 +#define MATCH_MOP_RR_3 0x8e004073 +#define MATCH_MOP_RR_4 0xc2004073 +#define MATCH_MOP_RR_5 0xc6004073 +#define MATCH_MOP_RR_6 0xca004073 +#define MATCH_MOP_RR_7 0xce004073 +#define MASK_MOP_RR 0xfe00707f /* Vendor-specific (CORE-V) Xcvmac instructions. */ #define MATCH_CV_MAC 0x9000302b #define MASK_CV_MAC 0xfe00707f diff --git a/include/opcode/riscv.h b/include/opcode/riscv.h index 710a9b73189..06c826cc03e 100644 --- a/include/opcode/riscv.h +++ b/include/opcode/riscv.h @@ -407,6 +407,7 @@ enum riscv_insn_class INSN_CLASS_ZIHINTPAUSE, INSN_CLASS_ZMMUL, INSN_CLASS_ZAWRS, + INSN_CLASS_ZIMOP, INSN_CLASS_F_INX, INSN_CLASS_D_INX, INSN_CLASS_Q_INX, diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c index 72d727cd77e..4ddcd699559 100644 --- a/opcodes/riscv-opc.c +++ b/opcodes/riscv-opc.c @@ -988,6 +988,48 @@ const struct riscv_opcode riscv_opcodes[] = {"wrs.nto", 0, INSN_CLASS_ZAWRS, "", MATCH_WRS_NTO, MASK_WRS_NTO, match_opcode, 0 }, {"wrs.sto", 0, INSN_CLASS_ZAWRS, "", MATCH_WRS_STO, MASK_WRS_STO, match_opcode, 0 }, +/* Zimop instructions. */ +{"mop.r.0", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_0, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.1", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_1, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.2", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_2, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.3", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_3, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.4", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_4, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.5", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_5, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.6", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_6, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.7", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_7, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.8", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_8, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.9", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_9, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.10", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_10, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.11", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_11, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.12", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_12, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.13", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_13, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.14", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_14, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.15", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_15, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.16", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_16, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.17", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_17, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.18", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_18, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.19", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_19, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.20", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_20, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.21", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_21, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.22", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_22, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.23", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_23, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.24", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_24, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.25", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_25, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.26", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_26, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.27", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_27, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.28", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_28, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.29", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_29, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.30", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_30, MASK_MOP_R, match_opcode, 0 }, +{"mop.r.31", 0, INSN_CLASS_ZIMOP, "d,s", MATCH_MOP_R_31, MASK_MOP_R, match_opcode, 0 }, +{"mop.rr.0", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_0, MASK_MOP_RR, match_opcode, 0 }, +{"mop.rr.1", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_1, MASK_MOP_RR, match_opcode, 0 }, +{"mop.rr.2", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_2, MASK_MOP_RR, match_opcode, 0 }, +{"mop.rr.3", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_3, MASK_MOP_RR, match_opcode, 0 }, +{"mop.rr.4", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_4, MASK_MOP_RR, match_opcode, 0 }, +{"mop.rr.5", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_5, MASK_MOP_RR, match_opcode, 0 }, +{"mop.rr.6", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_6, MASK_MOP_RR, match_opcode, 0 }, +{"mop.rr.7", 0, INSN_CLASS_ZIMOP, "d,s,t", MATCH_MOP_RR_7, MASK_MOP_RR, match_opcode, 0 }, + /* Zfa instructions. */ {"fli.s", 0, INSN_CLASS_ZFA, "D,Wfv", MATCH_FLI_S, MASK_FLI_S, match_opcode, 0 }, {"fli.d", 0, INSN_CLASS_D_AND_ZFA, "D,Wfv", MATCH_FLI_D, MASK_FLI_D, match_opcode, 0 },