diff options
author | Zi Shen Lim <zlim.lnx@gmail.com> | 2014-08-27 00:15:19 -0400 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2014-09-08 09:39:19 -0400 |
commit | 345e0d35ecdd7aff31881462a6f7786fda3241d9 (patch) | |
tree | a8f0b185fb6b0a41666e3265654bd4655f7823db /arch | |
parent | c0cafbae20d2878883ec3c06d6ea30ff38a6bf92 (diff) |
arm64: introduce aarch64_insn_gen_cond_branch_imm()
Introduce function to generate conditional branch (immediate)
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm64/include/asm/insn.h | 21 | ||||
-rw-r--r-- | arch/arm64/kernel/insn.c | 17 |
2 files changed, 38 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h index 5080962058b0..86a8a9cc9ec6 100644 --- a/arch/arm64/include/asm/insn.h +++ b/arch/arm64/include/asm/insn.h | |||
@@ -117,6 +117,24 @@ enum aarch64_insn_variant { | |||
117 | AARCH64_INSN_VARIANT_64BIT | 117 | AARCH64_INSN_VARIANT_64BIT |
118 | }; | 118 | }; |
119 | 119 | ||
120 | enum aarch64_insn_condition { | ||
121 | AARCH64_INSN_COND_EQ = 0x0, /* == */ | ||
122 | AARCH64_INSN_COND_NE = 0x1, /* != */ | ||
123 | AARCH64_INSN_COND_CS = 0x2, /* unsigned >= */ | ||
124 | AARCH64_INSN_COND_CC = 0x3, /* unsigned < */ | ||
125 | AARCH64_INSN_COND_MI = 0x4, /* < 0 */ | ||
126 | AARCH64_INSN_COND_PL = 0x5, /* >= 0 */ | ||
127 | AARCH64_INSN_COND_VS = 0x6, /* overflow */ | ||
128 | AARCH64_INSN_COND_VC = 0x7, /* no overflow */ | ||
129 | AARCH64_INSN_COND_HI = 0x8, /* unsigned > */ | ||
130 | AARCH64_INSN_COND_LS = 0x9, /* unsigned <= */ | ||
131 | AARCH64_INSN_COND_GE = 0xa, /* signed >= */ | ||
132 | AARCH64_INSN_COND_LT = 0xb, /* signed < */ | ||
133 | AARCH64_INSN_COND_GT = 0xc, /* signed > */ | ||
134 | AARCH64_INSN_COND_LE = 0xd, /* signed <= */ | ||
135 | AARCH64_INSN_COND_AL = 0xe, /* always */ | ||
136 | }; | ||
137 | |||
120 | enum aarch64_insn_branch_type { | 138 | enum aarch64_insn_branch_type { |
121 | AARCH64_INSN_BRANCH_NOLINK, | 139 | AARCH64_INSN_BRANCH_NOLINK, |
122 | AARCH64_INSN_BRANCH_LINK, | 140 | AARCH64_INSN_BRANCH_LINK, |
@@ -135,6 +153,7 @@ __AARCH64_INSN_FUNCS(b, 0xFC000000, 0x14000000) | |||
135 | __AARCH64_INSN_FUNCS(bl, 0xFC000000, 0x94000000) | 153 | __AARCH64_INSN_FUNCS(bl, 0xFC000000, 0x94000000) |
136 | __AARCH64_INSN_FUNCS(cbz, 0xFE000000, 0x34000000) | 154 | __AARCH64_INSN_FUNCS(cbz, 0xFE000000, 0x34000000) |
137 | __AARCH64_INSN_FUNCS(cbnz, 0xFE000000, 0x35000000) | 155 | __AARCH64_INSN_FUNCS(cbnz, 0xFE000000, 0x35000000) |
156 | __AARCH64_INSN_FUNCS(bcond, 0xFF000010, 0x54000000) | ||
138 | __AARCH64_INSN_FUNCS(svc, 0xFFE0001F, 0xD4000001) | 157 | __AARCH64_INSN_FUNCS(svc, 0xFFE0001F, 0xD4000001) |
139 | __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002) | 158 | __AARCH64_INSN_FUNCS(hvc, 0xFFE0001F, 0xD4000002) |
140 | __AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003) | 159 | __AARCH64_INSN_FUNCS(smc, 0xFFE0001F, 0xD4000003) |
@@ -159,6 +178,8 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, | |||
159 | enum aarch64_insn_register reg, | 178 | enum aarch64_insn_register reg, |
160 | enum aarch64_insn_variant variant, | 179 | enum aarch64_insn_variant variant, |
161 | enum aarch64_insn_branch_type type); | 180 | enum aarch64_insn_branch_type type); |
181 | u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr, | ||
182 | enum aarch64_insn_condition cond); | ||
162 | u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op); | 183 | u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op); |
163 | u32 aarch64_insn_gen_nop(void); | 184 | u32 aarch64_insn_gen_nop(void); |
164 | u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, | 185 | u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, |
diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 67979364daf6..b65edc02cf81 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c | |||
@@ -380,6 +380,23 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr, | |||
380 | offset >> 2); | 380 | offset >> 2); |
381 | } | 381 | } |
382 | 382 | ||
383 | u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr, | ||
384 | enum aarch64_insn_condition cond) | ||
385 | { | ||
386 | u32 insn; | ||
387 | long offset; | ||
388 | |||
389 | offset = branch_imm_common(pc, addr, SZ_1M); | ||
390 | |||
391 | insn = aarch64_insn_get_bcond_value(); | ||
392 | |||
393 | BUG_ON(cond < AARCH64_INSN_COND_EQ || cond > AARCH64_INSN_COND_AL); | ||
394 | insn |= cond; | ||
395 | |||
396 | return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_19, insn, | ||
397 | offset >> 2); | ||
398 | } | ||
399 | |||
383 | u32 __kprobes aarch64_insn_gen_hint(enum aarch64_insn_hint_op op) | 400 | u32 __kprobes aarch64_insn_gen_hint(enum aarch64_insn_hint_op op) |
384 | { | 401 | { |
385 | return aarch64_insn_get_hint_value() | op; | 402 | return aarch64_insn_get_hint_value() | op; |