if (ret < 0)
return ret;
- move_imm(ctx, t1, func_addr, is32);
+ move_addr(ctx, t1, func_addr);
emit_insn(ctx, jirl, t1, LOONGARCH_GPR_RA, 0);
move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0);
break;
emit_insn(ctx, addiw, reg, reg, 0);
}
+static inline void move_addr(struct jit_ctx *ctx, enum loongarch_gpr rd, u64 addr)
+{
+ u64 imm_11_0, imm_31_12, imm_51_32, imm_63_52;
+
+ /* lu12iw rd, imm_31_12 */
+ imm_31_12 = (addr >> 12) & 0xfffff;
+ emit_insn(ctx, lu12iw, rd, imm_31_12);
+
+ /* ori rd, rd, imm_11_0 */
+ imm_11_0 = addr & 0xfff;
+ emit_insn(ctx, ori, rd, rd, imm_11_0);
+
+ /* lu32id rd, imm_51_32 */
+ imm_51_32 = (addr >> 32) & 0xfffff;
+ emit_insn(ctx, lu32id, rd, imm_51_32);
+
+ /* lu52id rd, rd, imm_63_52 */
+ imm_63_52 = (addr >> 52) & 0xfff;
+ emit_insn(ctx, lu52id, rd, rd, imm_63_52);
+}
+
static inline void move_imm(struct jit_ctx *ctx, enum loongarch_gpr rd, long imm, bool is32)
{
long imm_11_0, imm_31_12, imm_51_32, imm_63_52, imm_51_0, imm_51_31;