summaryrefslogtreecommitdiff
path: root/arch/loongarch/include/asm/inst.h
diff options
context:
space:
mode:
authorHuacai Chen <chenhuacai@loongson.cn>2022-12-10 17:39:59 +0300
committerHuacai Chen <chenhuacai@loongson.cn>2022-12-14 03:36:11 +0300
commit19e5eb15b00c5841b4b9bd9777af2865a40d2f39 (patch)
treef471107baccd8668f7cd72a2e8f5b5f690e30506 /arch/loongarch/include/asm/inst.h
parent61a6fccc0bd2e8030b2672a52ef3f6706b2b2ee4 (diff)
downloadlinux-19e5eb15b00c5841b4b9bd9777af2865a40d2f39.tar.xz
LoongArch: Add alternative runtime patching mechanism
Introduce the "alternative" mechanism from ARM64 and x86 for LoongArch to apply runtime patching. The main purpose of this patch is to provide a framework. In future we can use this mechanism (i.e., the ALTERNATIVE and ALTERNATIVE_2 macros) to optimize hotspot functions according to cpu features. Signed-off-by: Jun Yi <yijun@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch/loongarch/include/asm/inst.h')
-rw-r--r--arch/loongarch/include/asm/inst.h18
1 files changed, 18 insertions, 0 deletions
diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
index 889d6c9fc2b6..67215af47b3d 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <asm/asm.h>
+#define INSN_NOP 0x03400000
#define INSN_BREAK 0x002a0000
#define ADDR_IMMMASK_LU52ID 0xFFF0000000000000
@@ -28,6 +29,7 @@ enum reg0i26_op {
enum reg1i20_op {
lu12iw_op = 0x0a,
lu32id_op = 0x0b,
+ pcaddi_op = 0x0c,
pcaddu12i_op = 0x0e,
pcaddu18i_op = 0x0f,
};
@@ -35,6 +37,8 @@ enum reg1i20_op {
enum reg1i21_op {
beqz_op = 0x10,
bnez_op = 0x11,
+ bceqz_op = 0x12, /* bits[9:8] = 0x00 */
+ bcnez_op = 0x12, /* bits[9:8] = 0x01 */
};
enum reg2_op {
@@ -315,6 +319,12 @@ static inline bool is_imm_negative(unsigned long val, unsigned int bit)
return val & (1UL << (bit - 1));
}
+static inline bool is_pc_ins(union loongarch_instruction *ip)
+{
+ return ip->reg1i20_format.opcode >= pcaddi_op &&
+ ip->reg1i20_format.opcode <= pcaddu18i_op;
+}
+
static inline bool is_branch_ins(union loongarch_instruction *ip)
{
return ip->reg1i21_format.opcode >= beqz_op &&
@@ -353,6 +363,14 @@ static inline bool unsigned_imm_check(unsigned long val, unsigned int bit)
return val < (1UL << bit);
}
+static inline unsigned long sign_extend(unsigned long val, unsigned int idx)
+{
+ if (!is_imm_negative(val, idx + 1))
+ return ((1UL << idx) - 1) & val;
+ else
+ return ~((1UL << idx) - 1) | val;
+}
+
#define DEF_EMIT_REG0I26_FORMAT(NAME, OP) \
static inline void emit_##NAME(union loongarch_instruction *insn, \
int offset) \