diff options
author | Nelson Chu <nelson.chu@sifive.com> | 2020-12-09 13:53:22 +0800 |
---|---|---|
committer | Nelson Chu <nelson.chu@sifive.com> | 2020-12-10 10:50:44 +0800 |
commit | c2137f55ad04e451d834048d4bfec1de2daea20e (patch) | |
tree | 71848a36ae6d0a7e129af78179952d016007340a /gas/config | |
parent | 8152e0407c25612c6a8079cc8e1a5c1fe14afdbf (diff) | |
download | binutils-c2137f55ad04e451d834048d4bfec1de2daea20e.zip binutils-c2137f55ad04e451d834048d4bfec1de2daea20e.tar.gz binutils-c2137f55ad04e451d834048d4bfec1de2daea20e.tar.bz2 |
RISC-V: Add sext.[bh] and zext.[bhw] pseudo instructions.
https://github.com/riscv/riscv-asm-manual/pull/61
We aleady have sext.w, so just add sext.b, sext.h, zext.b, zext.h
and zext.w. In a certain sense, zext.b is not a pseudo - It is an
alias of andi. Similarly, sext.b and sext.h are aliases of other
rvb instructions, when we enable b extension; But they are pseudos
when we just enable rvi. However, this patch does not consider the
rvb cases. Besides, zext.w is only valid in rv64.
gas/
* config/tc-riscv.c (riscv_ext): New function. Use md_assemblef
to expand the zext and sext pseudos, to give them a chance to be
expanded into c-ext instructions.
(macro): Handle M_ZEXTH, M_ZEXTW, M_SEXTB and M_SEXTH.
* testsuite/gas/riscv/ext.s: New testcase.
* testsuite/gas/riscv/ext-32.d: Likewise.
* testsuite/gas/riscv/ext-64.d: Likewise.
include/
* opcode/riscv.h (M_ZEXTH, M_ZEXTW, M_SEXTB, M_SEXTH.): Added.
opcodes/
* riscv-opc.c (riscv_opcodes): Add sext.[bh] and zext.[bhw].
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/tc-riscv.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index dfdbadf..ca7e52a 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -1433,6 +1433,23 @@ load_const (int reg, expressionS *ep) } } +/* Zero extend and sign extend byte/half-word/word. */ + +static void +riscv_ext (int destreg, int srcreg, unsigned shift, bfd_boolean sign) +{ + if (sign) + { + md_assemblef ("slli x%d, x%d, 0x%x", destreg, srcreg, shift); + md_assemblef ("srai x%d, x%d, 0x%x", destreg, destreg, shift); + } + else + { + md_assemblef ("slli x%d, x%d, 0x%x", destreg, srcreg, shift); + md_assemblef ("srli x%d, x%d, 0x%x", destreg, destreg, shift); + } +} + /* Expand RISC-V assembly macros into one or more instructions. */ static void macro (struct riscv_cl_insn *ip, expressionS *imm_expr, @@ -1554,6 +1571,22 @@ macro (struct riscv_cl_insn *ip, expressionS *imm_expr, riscv_call (rd, rs1, imm_expr, *imm_reloc); break; + case M_ZEXTH: + riscv_ext (rd, rs1, xlen - 16, FALSE); + break; + + case M_ZEXTW: + riscv_ext (rd, rs1, xlen - 32, FALSE); + break; + + case M_SEXTB: + riscv_ext (rd, rs1, xlen - 8, TRUE); + break; + + case M_SEXTH: + riscv_ext (rd, rs1, xlen - 16, TRUE); + break; + default: as_bad (_("Macro %s not implemented"), ip->insn_mo->name); break; |