riscv: Introduce support for defining instructions
When compiling with toolchains that haven't yet been taught about new instructions we need to encode them ourselves. Create a new file where support for instruction definitions will evolve. We initiate the file with a macro called INSN_R(), which implements the R-type instruction encoding. INSN_R() will use the assembler's .insn directive when available, which should give the assembler a chance to do some validation. When .insn is not available we fall back to manual encoding. Not only should using instruction encoding macros improve readability and maintainability of code over the alternative of inserting instructions directly (e.g. '.word 0xc0de'), but we should also gain potential for more optimized code after compilation because the compiler will have control over the input and output registers used. Signed-off-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Anup Patel <anup@brainfault.org> Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
parent
7fc4426959
commit
5ac43ab2e3
@ -227,6 +227,9 @@ config RISCV_DMA_NONCOHERENT
|
||||
select ARCH_HAS_SETUP_DMA_OPS
|
||||
select DMA_DIRECT_REMAP
|
||||
|
||||
config AS_HAS_INSN
|
||||
def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
|
||||
|
||||
source "arch/riscv/Kconfig.socs"
|
||||
source "arch/riscv/Kconfig.erratas"
|
||||
|
||||
|
90
arch/riscv/include/asm/insn-def.h
Normal file
90
arch/riscv/include/asm/insn-def.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __ASM_INSN_DEF_H
|
||||
#define __ASM_INSN_DEF_H
|
||||
|
||||
#include <asm/asm.h>
|
||||
|
||||
#define INSN_R_FUNC7_SHIFT 25
|
||||
#define INSN_R_RS2_SHIFT 20
|
||||
#define INSN_R_RS1_SHIFT 15
|
||||
#define INSN_R_FUNC3_SHIFT 12
|
||||
#define INSN_R_RD_SHIFT 7
|
||||
#define INSN_R_OPCODE_SHIFT 0
|
||||
|
||||
#ifdef __ASSEMBLY__
|
||||
|
||||
#ifdef CONFIG_AS_HAS_INSN
|
||||
|
||||
.macro insn_r, opcode, func3, func7, rd, rs1, rs2
|
||||
.insn r \opcode, \func3, \func7, \rd, \rs1, \rs2
|
||||
.endm
|
||||
|
||||
#else
|
||||
|
||||
#include <asm/gpr-num.h>
|
||||
|
||||
.macro insn_r, opcode, func3, func7, rd, rs1, rs2
|
||||
.4byte ((\opcode << INSN_R_OPCODE_SHIFT) | \
|
||||
(\func3 << INSN_R_FUNC3_SHIFT) | \
|
||||
(\func7 << INSN_R_FUNC7_SHIFT) | \
|
||||
(.L__gpr_num_\rd << INSN_R_RD_SHIFT) | \
|
||||
(.L__gpr_num_\rs1 << INSN_R_RS1_SHIFT) | \
|
||||
(.L__gpr_num_\rs2 << INSN_R_RS2_SHIFT))
|
||||
.endm
|
||||
|
||||
#endif
|
||||
|
||||
#define __INSN_R(...) insn_r __VA_ARGS__
|
||||
|
||||
#else /* ! __ASSEMBLY__ */
|
||||
|
||||
#ifdef CONFIG_AS_HAS_INSN
|
||||
|
||||
#define __INSN_R(opcode, func3, func7, rd, rs1, rs2) \
|
||||
".insn r " opcode ", " func3 ", " func7 ", " rd ", " rs1 ", " rs2 "\n"
|
||||
|
||||
#else
|
||||
|
||||
#include <linux/stringify.h>
|
||||
#include <asm/gpr-num.h>
|
||||
|
||||
#define DEFINE_INSN_R \
|
||||
__DEFINE_ASM_GPR_NUMS \
|
||||
" .macro insn_r, opcode, func3, func7, rd, rs1, rs2\n" \
|
||||
" .4byte ((\\opcode << " __stringify(INSN_R_OPCODE_SHIFT) ") |" \
|
||||
" (\\func3 << " __stringify(INSN_R_FUNC3_SHIFT) ") |" \
|
||||
" (\\func7 << " __stringify(INSN_R_FUNC7_SHIFT) ") |" \
|
||||
" (.L__gpr_num_\\rd << " __stringify(INSN_R_RD_SHIFT) ") |" \
|
||||
" (.L__gpr_num_\\rs1 << " __stringify(INSN_R_RS1_SHIFT) ") |" \
|
||||
" (.L__gpr_num_\\rs2 << " __stringify(INSN_R_RS2_SHIFT) "))\n" \
|
||||
" .endm\n"
|
||||
|
||||
#define UNDEFINE_INSN_R \
|
||||
" .purgem insn_r\n"
|
||||
|
||||
#define __INSN_R(opcode, func3, func7, rd, rs1, rs2) \
|
||||
DEFINE_INSN_R \
|
||||
"insn_r " opcode ", " func3 ", " func7 ", " rd ", " rs1 ", " rs2 "\n" \
|
||||
UNDEFINE_INSN_R
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ! __ASSEMBLY__ */
|
||||
|
||||
#define INSN_R(opcode, func3, func7, rd, rs1, rs2) \
|
||||
__INSN_R(RV_##opcode, RV_##func3, RV_##func7, \
|
||||
RV_##rd, RV_##rs1, RV_##rs2)
|
||||
|
||||
#define RV_OPCODE(v) __ASM_STR(v)
|
||||
#define RV_FUNC3(v) __ASM_STR(v)
|
||||
#define RV_FUNC7(v) __ASM_STR(v)
|
||||
#define RV_RD(v) __ASM_STR(v)
|
||||
#define RV_RS1(v) __ASM_STR(v)
|
||||
#define RV_RS2(v) __ASM_STR(v)
|
||||
#define __RV_REG(v) __ASM_STR(x ## v)
|
||||
#define RV___RD(v) __RV_REG(v)
|
||||
#define RV___RS1(v) __RV_REG(v)
|
||||
#define RV___RS2(v) __RV_REG(v)
|
||||
|
||||
#endif /* __ASM_INSN_DEF_H */
|
Loading…
x
Reference in New Issue
Block a user