arm64: introduce aarch64_insn_gen_branch_reg()
Introduce function to generate unconditional branch (register) instructions. Signed-off-by: Zi Shen Lim <zlim.lnx@gmail.com> Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
This commit is contained in:
parent
617d2fbc45
commit
c0cafbae20
2 changed files with 40 additions and 2 deletions
|
@ -71,6 +71,7 @@ enum aarch64_insn_imm_type {
|
||||||
|
|
||||||
enum aarch64_insn_register_type {
|
enum aarch64_insn_register_type {
|
||||||
AARCH64_INSN_REGTYPE_RT,
|
AARCH64_INSN_REGTYPE_RT,
|
||||||
|
AARCH64_INSN_REGTYPE_RN,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum aarch64_insn_register {
|
enum aarch64_insn_register {
|
||||||
|
@ -119,6 +120,7 @@ enum aarch64_insn_variant {
|
||||||
enum aarch64_insn_branch_type {
|
enum aarch64_insn_branch_type {
|
||||||
AARCH64_INSN_BRANCH_NOLINK,
|
AARCH64_INSN_BRANCH_NOLINK,
|
||||||
AARCH64_INSN_BRANCH_LINK,
|
AARCH64_INSN_BRANCH_LINK,
|
||||||
|
AARCH64_INSN_BRANCH_RETURN,
|
||||||
AARCH64_INSN_BRANCH_COMP_ZERO,
|
AARCH64_INSN_BRANCH_COMP_ZERO,
|
||||||
AARCH64_INSN_BRANCH_COMP_NONZERO,
|
AARCH64_INSN_BRANCH_COMP_NONZERO,
|
||||||
};
|
};
|
||||||
|
@ -138,6 +140,9 @@ __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002)
|
||||||
__AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003)
|
__AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003)
|
||||||
__AARCH64_INSN_FUNCS(brk, 0xFFE0001F, 0xD4200000)
|
__AARCH64_INSN_FUNCS(brk, 0xFFE0001F, 0xD4200000)
|
||||||
__AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F)
|
__AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F)
|
||||||
|
__AARCH64_INSN_FUNCS(br, 0xFFFFFC1F, 0xD61F0000)
|
||||||
|
__AARCH64_INSN_FUNCS(blr, 0xFFFFFC1F, 0xD63F0000)
|
||||||
|
__AARCH64_INSN_FUNCS(ret, 0xFFFFFC1F, 0xD65F0000)
|
||||||
|
|
||||||
#undef __AARCH64_INSN_FUNCS
|
#undef __AARCH64_INSN_FUNCS
|
||||||
|
|
||||||
|
@ -156,6 +161,8 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
|
||||||
enum aarch64_insn_branch_type type);
|
enum aarch64_insn_branch_type type);
|
||||||
u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op);
|
u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op);
|
||||||
u32 aarch64_insn_gen_nop(void);
|
u32 aarch64_insn_gen_nop(void);
|
||||||
|
u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
|
||||||
|
enum aarch64_insn_branch_type type);
|
||||||
|
|
||||||
bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
|
bool aarch64_insn_hotpatch_safe(u32 old_insn, u32 new_insn);
|
||||||
|
|
||||||
|
|
|
@ -283,6 +283,9 @@ static u32 aarch64_insn_encode_register(enum aarch64_insn_register_type type,
|
||||||
case AARCH64_INSN_REGTYPE_RT:
|
case AARCH64_INSN_REGTYPE_RT:
|
||||||
shift = 0;
|
shift = 0;
|
||||||
break;
|
break;
|
||||||
|
case AARCH64_INSN_REGTYPE_RN:
|
||||||
|
shift = 5;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("%s: unknown register type encoding %d\n", __func__,
|
pr_err("%s: unknown register type encoding %d\n", __func__,
|
||||||
type);
|
type);
|
||||||
|
@ -325,10 +328,16 @@ u32 __kprobes aarch64_insn_gen_branch_imm(unsigned long pc, unsigned long addr,
|
||||||
*/
|
*/
|
||||||
offset = branch_imm_common(pc, addr, SZ_128M);
|
offset = branch_imm_common(pc, addr, SZ_128M);
|
||||||
|
|
||||||
if (type == AARCH64_INSN_BRANCH_LINK)
|
switch (type) {
|
||||||
|
case AARCH64_INSN_BRANCH_LINK:
|
||||||
insn = aarch64_insn_get_bl_value();
|
insn = aarch64_insn_get_bl_value();
|
||||||
else
|
break;
|
||||||
|
case AARCH64_INSN_BRANCH_NOLINK:
|
||||||
insn = aarch64_insn_get_b_value();
|
insn = aarch64_insn_get_b_value();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG_ON(1);
|
||||||
|
}
|
||||||
|
|
||||||
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn,
|
return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_26, insn,
|
||||||
offset >> 2);
|
offset >> 2);
|
||||||
|
@ -380,3 +389,25 @@ u32 __kprobes aarch64_insn_gen_nop(void)
|
||||||
{
|
{
|
||||||
return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
|
return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
|
||||||
|
enum aarch64_insn_branch_type type)
|
||||||
|
{
|
||||||
|
u32 insn;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case AARCH64_INSN_BRANCH_NOLINK:
|
||||||
|
insn = aarch64_insn_get_br_value();
|
||||||
|
break;
|
||||||
|
case AARCH64_INSN_BRANCH_LINK:
|
||||||
|
insn = aarch64_insn_get_blr_value();
|
||||||
|
break;
|
||||||
|
case AARCH64_INSN_BRANCH_RETURN:
|
||||||
|
insn = aarch64_insn_get_ret_value();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG_ON(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, reg);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue