/* * Atomic update of patched instruction is only available if this * instruction doesn't cross L1 cache line boundary. You can read about * the way we achieve this in arc/include/asm/jump_label.h
*/ staticinlinevoid instruction_align_assert(void *addr, int len)
{ unsignedlong a = (unsignedlong)addr;
if ((a >> L1_CACHE_SHIFT) != ((a + len - 1) >> L1_CACHE_SHIFT))
arc_jl_fatal("instruction (addr %px) cross L1 cache line border",
addr);
}
/* * ARCv2 'Branch unconditionally' instruction: * 00000ssssssssss1SSSSSSSSSSNRtttt * s S[n:0] lower bits signed immediate (number is bitfield size) * S S[m:n+1] upper bits signed immediate (number is bitfield size) * t S[24:21] upper bits signed immediate (branch unconditionally far) * N N <.d> delay slot mode * R R Reserved
*/ staticinline u32 arc_gen_branch(jump_label_t pc, jump_label_t target)
{
u32 instruction_l, instruction_r;
u32 pcl = pc & GENMASK(31, 2);
u32 u_offset = target - pcl;
u32 s, S, t;
/* * Offset in 32-bit branch instruction must to fit into s25. * Something is terribly broken if we get such huge offset within one * function.
*/ if ((s32)u_offset < -16777216 || (s32)u_offset > 16777214)
arc_jl_fatal("gen branch with offset (%d) not fit in s25",
(s32)u_offset);
/* * All instructions are aligned by 2 bytes so we should never get offset * here which is not 2 bytes aligned.
*/ if (u_offset & 0x1)
arc_jl_fatal("gen branch with offset (%d) unaligned to 2 bytes",
(s32)u_offset);
s = (u_offset >> 1) & GENMASK(9, 0);
S = (u_offset >> 11) & GENMASK(9, 0);
t = (u_offset >> 21) & GENMASK(3, 0);
/* 00000ssssssssss1 */
instruction_l = (s << 1) | 0x1; /* SSSSSSSSSSNRtttt */
instruction_r = (S << 6) | t;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.