aboutsummaryrefslogtreecommitdiff
path: root/gas/config/tc-riscv.c
diff options
context:
space:
mode:
authorNelson Chu <nelson.chu@sifive.com>2020-12-09 13:53:22 +0800
committerNelson Chu <nelson.chu@sifive.com>2020-12-10 10:50:44 +0800
commitc2137f55ad04e451d834048d4bfec1de2daea20e (patch)
tree71848a36ae6d0a7e129af78179952d016007340a /gas/config/tc-riscv.c
parent8152e0407c25612c6a8079cc8e1a5c1fe14afdbf (diff)
downloadgdb-c2137f55ad04e451d834048d4bfec1de2daea20e.zip
gdb-c2137f55ad04e451d834048d4bfec1de2daea20e.tar.gz
gdb-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/tc-riscv.c')
-rw-r--r--gas/config/tc-riscv.c33
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;