[PATCH v2] RISC-V: map zext.h to pack/packw if Zbkb is enabled

Andrew Waterman andrew@sifive.com
Tue Aug 6 07:52:53 GMT 2024


LGTM.

There has been some confusion about which extensions contain the
zext.h instruction.  According to the ISA spec, Zbb contains zext.h,
and Zbkb contains pack[w].  But pack[w] with rs2=x0 _is_ zext.h.  By
implication, it is correct to say that Zbkb contains zext.h, even
though the spec does not say so explicitly.  To this end, I'll propose
a non-normative clarification to the ISA spec.  Regardless, this patch
seems like the way to go.


On Mon, Aug 5, 2024 at 8:56 PM Hau Hsu <hau.hsu@sifive.com> wrote:
>
> `zext.h` is zero-extend halfword instruction that belongs to Zbb.
> Currently `zext.h` falls back to 2 shifts if Zbb is not enabled.
> However the encoding and operation is a special case of
> `pack/packw rd, rs1, rs2`, which belongs to Zbkb. The instructions pack
> the low halves of rs1 and rs2 into rd.  When rs2 is zero (x0), they
> behave like zero-extend instruction, and the encoding are exactly the
> same as zext.h.
>
> Thus we can map `zext.h` to `pack` or `packw` (rv64) if Zbkb is enabled,
> instead of 2 shifts. This reduces one instruction.
>
> This patch does this by making `zext.h` also available for Zbkb.
>
> opcode/
>     * riscv-opc.c (riscv_opcodes): Update `zext.h` entries to use
>       `ZBB_OR_ZBKB` instruction class.
>
> gas/
>     * testsuite/gas/riscv/zext-to-pack.s: Add test for mapping zext to
>       pack/packw encoding.
>     * testsuite/gas/riscv/zext-to-pack-encoding.d: Likewise.
>     * testsuite/gas/riscv/zext-to-packw-encoding.d: Likewise.
> ---
>  gas/testsuite/gas/riscv/zext-to-pack-encoding.d  | 11 +++++++++++
>  gas/testsuite/gas/riscv/zext-to-pack.s           |  2 ++
>  gas/testsuite/gas/riscv/zext-to-packw-encoding.d | 11 +++++++++++
>  opcodes/riscv-opc.c                              |  4 ++--
>  4 files changed, 26 insertions(+), 2 deletions(-)
>  create mode 100644 gas/testsuite/gas/riscv/zext-to-pack-encoding.d
>  create mode 100644 gas/testsuite/gas/riscv/zext-to-pack.s
>  create mode 100644 gas/testsuite/gas/riscv/zext-to-packw-encoding.d
>
> diff --git a/gas/testsuite/gas/riscv/zext-to-pack-encoding.d b/gas/testsuite/gas/riscv/zext-to-pack-encoding.d
> new file mode 100644
> index 00000000000..86fcbce0ff0
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zext-to-pack-encoding.d
> @@ -0,0 +1,11 @@
> +#as: -march=rv32i_zbkb
> +#source: zext-to-pack.s
> +#objdump: -d
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+[0-9a-f]+:[   ]+08054533[     ]+zext.h[       ]+a0,a0
> diff --git a/gas/testsuite/gas/riscv/zext-to-pack.s b/gas/testsuite/gas/riscv/zext-to-pack.s
> new file mode 100644
> index 00000000000..bb2be3dcaa6
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zext-to-pack.s
> @@ -0,0 +1,2 @@
> +target:
> +       zext.h  a0, a0
> diff --git a/gas/testsuite/gas/riscv/zext-to-packw-encoding.d b/gas/testsuite/gas/riscv/zext-to-packw-encoding.d
> new file mode 100644
> index 00000000000..04e21e7288c
> --- /dev/null
> +++ b/gas/testsuite/gas/riscv/zext-to-packw-encoding.d
> @@ -0,0 +1,11 @@
> +#as: -march=rv64i_zbkb
> +#source: zext-to-pack.s
> +#objdump: -d
> +
> +.*:[   ]+file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+000 <target>:
> +[      ]+[0-9a-f]+:[   ]+0805453b[     ]+zext.h[       ]+a0,a0
> diff --git a/opcodes/riscv-opc.c b/opcodes/riscv-opc.c
> index 14ec2903cdd..1ec23408547 100644
> --- a/opcodes/riscv-opc.c
> +++ b/opcodes/riscv-opc.c
> @@ -1186,8 +1186,8 @@ const struct riscv_opcode riscv_opcodes[] =
>  {"sext.h",     0, INSN_CLASS_ZBB,  "d,s",   MATCH_SEXT_H, MASK_SEXT_H, match_opcode, 0 },
>  {"sext.h",     0, INSN_CLASS_I,         "d,s",   0, (int) M_EXTH, NULL, INSN_MACRO },
>  {"zext.h",     0, INSN_CLASS_ZCB_AND_ZBB,  "Cs,Cw", MATCH_C_ZEXT_H, MASK_C_ZEXT_H, match_opcode, INSN_ALIAS },
> -{"zext.h",    32, INSN_CLASS_ZBB,  "d,s",   MATCH_PACK, MASK_PACK | MASK_RS2, match_opcode, 0 },
> -{"zext.h",    64, INSN_CLASS_ZBB,  "d,s",   MATCH_PACKW, MASK_PACKW | MASK_RS2, match_opcode, 0 },
> +{"zext.h",    32, INSN_CLASS_ZBB_OR_ZBKB,  "d,s",   MATCH_PACK, MASK_PACK | MASK_RS2, match_opcode, 0 },
> +{"zext.h",    64, INSN_CLASS_ZBB_OR_ZBKB,  "d,s",   MATCH_PACKW, MASK_PACKW | MASK_RS2, match_opcode, 0 },
>  {"zext.h",     0, INSN_CLASS_I,         "d,s",   0, (int) M_EXTH, NULL, INSN_MACRO },
>  {"orc.b",      0, INSN_CLASS_ZBB,  "d,s",   MATCH_GORCI | MATCH_SHAMT_ORC_B, MASK_GORCI | MASK_SHAMT, match_opcode, 0 },
>  {"clzw",      64, INSN_CLASS_ZBB,  "d,s",   MATCH_CLZW, MASK_CLZW, match_opcode, 0 },
> --
> 2.39.3
>


More information about the Binutils mailing list