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 <paul.burton@mips.com> Cc: linux-mips@vger.kernel.org
This commit is contained in:
		
							parent
							
								
									c838b580ca
								
							
						
					
					
						commit
						9b6584e35f
					
				| @ -11,6 +11,7 @@ | ||||
| #ifndef __ASSEMBLY__ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| #include <asm/isa-rev.h> | ||||
| 
 | ||||
| #define JUMP_LABEL_NOP_SIZE 4 | ||||
| 
 | ||||
| @ -21,9 +22,14 @@ | ||||
| #endif | ||||
| 
 | ||||
| #ifdef CONFIG_CPU_MICROMIPS | ||||
| #define B_INSN "b32" | ||||
| # define B_INSN "b32" | ||||
| # define J_INSN "j32" | ||||
| #elif MIPS_ISA_REV >= 6 | ||||
| # define B_INSN "bc" | ||||
| # define J_INSN "bc" | ||||
| #else | ||||
| #define B_INSN "b" | ||||
| # define B_INSN "b" | ||||
| # define J_INSN "j" | ||||
| #endif | ||||
| 
 | ||||
| static __always_inline bool arch_static_branch(struct static_key *key, bool branch) | ||||
| @ -42,7 +48,7 @@ l_yes: | ||||
| 
 | ||||
| static __always_inline bool arch_static_branch_jump(struct static_key *key, bool branch) | ||||
| { | ||||
| 	asm_volatile_goto("1:\tj %l[l_yes]\n\t" | ||||
| 	asm_volatile_goto("1:\t" J_INSN " %l[l_yes]\n\t" | ||||
| 		".pushsection __jump_table,  \"aw\"\n\t" | ||||
| 		WORD_INSN " 1b, %l[l_yes], %0\n\t" | ||||
| 		".popsection\n\t" | ||||
|  | ||||
| @ -40,18 +40,38 @@ void arch_jump_label_transform(struct jump_entry *e, | ||||
| { | ||||
| 	union mips_instruction *insn_p; | ||||
| 	union mips_instruction insn; | ||||
| 	long offset; | ||||
| 
 | ||||
| 	insn_p = (union mips_instruction *)msk_isa16_mode(e->code); | ||||
| 
 | ||||
| 	/* Jump only works within an aligned region its delay slot is in. */ | ||||
| 	BUG_ON((e->target & ~J_RANGE_MASK) != ((e->code + 4) & ~J_RANGE_MASK)); | ||||
| 
 | ||||
| 	/* Target must have the right alignment and ISA must be preserved. */ | ||||
| 	BUG_ON((e->target & J_ALIGN_MASK) != J_ISA_BIT); | ||||
| 
 | ||||
| 	if (type == JUMP_LABEL_JMP) { | ||||
| 		insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op; | ||||
| 		insn.j_format.target = e->target >> J_RANGE_SHIFT; | ||||
| 		if (!IS_ENABLED(CONFIG_CPU_MICROMIPS) && MIPS_ISA_REV >= 6) { | ||||
| 			offset = e->target - ((unsigned long)insn_p + 4); | ||||
| 			offset >>= 2; | ||||
| 
 | ||||
| 			/*
 | ||||
| 			 * The branch offset must fit in the instruction's 26 | ||||
| 			 * bit field. | ||||
| 			 */ | ||||
| 			WARN_ON((offset >= BIT(25)) || | ||||
| 				(offset < -(long)BIT(25))); | ||||
| 
 | ||||
| 			insn.j_format.opcode = bc6_op; | ||||
| 			insn.j_format.target = offset; | ||||
| 		} else { | ||||
| 			/*
 | ||||
| 			 * Jump only works within an aligned region its delay | ||||
| 			 * slot is in. | ||||
| 			 */ | ||||
| 			WARN_ON((e->target & ~J_RANGE_MASK) != | ||||
| 				((e->code + 4) & ~J_RANGE_MASK)); | ||||
| 
 | ||||
| 			insn.j_format.opcode = J_ISA_BIT ? mm_j32_op : j_op; | ||||
| 			insn.j_format.target = e->target >> J_RANGE_SHIFT; | ||||
| 		} | ||||
| 	} else { | ||||
| 		insn.word = 0; /* nop */ | ||||
| 	} | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user