Skip to content

Commit 9b6584e

Browse files
committed
MIPS: jump_label: Use compact branches for >= r6
MIPSr6 introduced compact branches which have no delay slots. Make use of them for jump labels in order to avoid the need for a nop to fill the branch or jump delay slot, saving 4 bytes of code for each static branch. Signed-off-by: Paul Burton <[email protected]> Cc: [email protected]
1 parent c838b58 commit 9b6584e

File tree

2 files changed

+34
-8
lines changed

2 files changed

+34
-8
lines changed

arch/mips/include/asm/jump_label.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#ifndef __ASSEMBLY__
1212

1313
#include <linux/types.h>
14+
#include <asm/isa-rev.h>
1415

1516
#define JUMP_LABEL_NOP_SIZE 4
1617

@@ -21,9 +22,14 @@
2122
#endif
2223

2324
#ifdef CONFIG_CPU_MICROMIPS
24-
#define B_INSN "b32"
25+
# define B_INSN "b32"
26+
# define J_INSN "j32"
27+
#elif MIPS_ISA_REV >= 6
28+
# define B_INSN "bc"
29+
# define J_INSN "bc"
2530
#else
26-
#define B_INSN "b"
31+
# define B_INSN "b"
32+
# define J_INSN "j"
2733
#endif
2834

2935
static __always_inline bool arch_static_branch(struct static_key *key, bool branch)
@@ -42,7 +48,7 @@ static __always_inline bool arch_static_branch(struct static_key *key, bool bran
4248

4349
static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch)
4450
{
45-
asm_volatile_goto("1:\tj %l[l_yes]\n\t"
51+
asm_volatile_goto("1:\t" J_INSN " %l[l_yes]\n\t"
4652
".pushsection __jump_table, \"aw\"\n\t"
4753
WORD_INSN " 1b, %l[l_yes], %0\n\t"
4854
".popsection\n\t"

arch/mips/kernel/jump_label.c

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,38 @@ void arch_jump_label_transform(struct jump_entry *e,
4040
{
4141
union mips_instruction *insn_p;
4242
union mips_instruction insn;
43+
long offset;
4344

4445
insn_p = (union mips_instruction *)msk_isa16_mode(e->code);
4546

46-
/* Jump only works within an aligned region its delay slot is in. */
47-
BUG_ON((e->target & ~J_RANGE_MASK) != ((e->code + 4) & ~J_RANGE_MASK));
48-
4947
/* Target must have the right alignment and ISA must be preserved. */
5048
BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT);
5149

5250
if (type == JUMP_LABEL_JMP) {
53-
insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op;
54-
insn.j_format.target = e->target >> J_RANGE_SHIFT;
51+
if (!IS_ENABLED(CONFIG_CPU_MICROMIPS) && MIPS_ISA_REV >= 6) {
52+
offset = e->target - ((unsigned long)insn_p + 4);
53+
offset >>= 2;
54+
55+
/*
56+
* The branch offset must fit in the instruction's 26
57+
* bit field.
58+
*/
59+
WARN_ON((offset >= BIT(25)) ||
60+
(offset < -(long)BIT(25)));
61+
62+
insn.j_format.opcode = bc6_op;
63+
insn.j_format.target = offset;
64+
} else {
65+
/*
66+
* Jump only works within an aligned region its delay
67+
* slot is in.
68+
*/
69+
WARN_ON((e->target & ~J_RANGE_MASK) !=
70+
((e->code + 4) & ~J_RANGE_MASK));
71+
72+
insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op;
73+
insn.j_format.target = e->target >> J_RANGE_SHIFT;
74+
}
5575
} else {
5676
insn.word = 0; /* nop */
5777
}

0 commit comments

Comments
 (0)