Charlie Jenkins <[email protected]> writes:
> @@ -78,14 +79,24 @@ static void riscv_alternative_fix_auipc_jalr(void *ptr, 
> u32 auipc_insn,
>                                            u32 jalr_insn, int patch_offset)
>  {
>       u32 call[2] = { auipc_insn, jalr_insn };
> +     u32 auipc_imm;
>       s32 imm;
>  
>       /* get and adjust new target address */
> -     imm = riscv_insn_extract_utype_itype_imm(auipc_insn, jalr_insn);
> +     imm = riscv_insn_auipc_extract_imm(auipc_insn) + 
> riscv_insn_jalr_extract_imm(jalr_insn);
>       imm -= patch_offset;
>  
> +     /*
> +      * When the 32-bit immediate is split across auipc and jalr, the
> +      * constructed immediates need to be treated as individually sign
> +      * extended numbers. Add the sign bit of the lower 12 bits to the upper
> +      * 20 bits to undo the bleeding of the sign.
> +      */
> +     auipc_imm = (imm & BIT(11)) << 1;
> +
>       /* update instructions */
> -     riscv_insn_insert_utype_itype_imm(&call[0], &call[1], imm);
> +     riscv_insn_auipc_insert_imm(&call[0], auipc_imm);
> +     riscv_insn_jalr_insert_imm(&call[1], imm);

Looking at the old riscv_insn_insert_utype_itype_imm(), for auipc we have

        *utype_insn &= ~(RV_U_IMM_31_12_MASK);
        *utype_insn |= (imm & RV_U_IMM_31_12_MASK) + ((imm & BIT(11)) << 1);

but the new code does

        auipc_imm = (imm & BIT(11)) << 1;
        *_insn &= ~GENMASK(31, 12);
        *_insn |= (((auipc_imm >> 12) & GENMASK(19, 0)) << 12);

which is not equivalent. The new code is missing (imm & RV_U_IMM_31_12_MASK)
from the old code.

Or am I confused somewhere?

Nam

Reply via email to