}
 }
 
+static void
+wrp_zext(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, u8 dst)
+{
+       if (meta->flags & FLAG_INSN_DO_ZEXT)
+               wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+}
+
 static void
 wrp_immed_relo(struct nfp_prog *nfp_prog, swreg dst, u32 imm,
               enum nfp_relo_type relo)
 }
 
 static int
-data_ld(struct nfp_prog *nfp_prog, swreg offset, u8 dst_gpr, int size)
+data_ld(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, swreg offset,
+       u8 dst_gpr, int size)
 {
        unsigned int i;
        u16 shift, sz;
                        wrp_mov(nfp_prog, reg_both(dst_gpr + i), reg_xfer(i));
 
        if (i < 2)
-               wrp_immed(nfp_prog, reg_both(dst_gpr + 1), 0);
+               wrp_zext(nfp_prog, meta, dst_gpr);
 
        return 0;
 }
 
 static int
-data_ld_host_order(struct nfp_prog *nfp_prog, u8 dst_gpr,
-                  swreg lreg, swreg rreg, int size, enum cmd_mode mode)
+data_ld_host_order(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
+                  u8 dst_gpr, swreg lreg, swreg rreg, int size,
+                  enum cmd_mode mode)
 {
        unsigned int i;
        u8 mask, sz;
                        wrp_mov(nfp_prog, reg_both(dst_gpr + i), reg_xfer(i));
 
        if (i < 2)
-               wrp_immed(nfp_prog, reg_both(dst_gpr + 1), 0);
+               wrp_zext(nfp_prog, meta, dst_gpr);
 
        return 0;
 }
 
 static int
-data_ld_host_order_addr32(struct nfp_prog *nfp_prog, u8 src_gpr, swreg offset,
-                         u8 dst_gpr, u8 size)
+data_ld_host_order_addr32(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
+                         u8 src_gpr, swreg offset, u8 dst_gpr, u8 size)
 {
-       return data_ld_host_order(nfp_prog, dst_gpr, reg_a(src_gpr), offset,
-                                 size, CMD_MODE_32b);
+       return data_ld_host_order(nfp_prog, meta, dst_gpr, reg_a(src_gpr),
+                                 offset, size, CMD_MODE_32b);
 }
 
 static int
-data_ld_host_order_addr40(struct nfp_prog *nfp_prog, u8 src_gpr, swreg offset,
-                         u8 dst_gpr, u8 size)
+data_ld_host_order_addr40(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
+                         u8 src_gpr, swreg offset, u8 dst_gpr, u8 size)
 {
        swreg rega, regb;
 
        addr40_offset(nfp_prog, src_gpr, offset, ®a, ®b);
 
-       return data_ld_host_order(nfp_prog, dst_gpr, rega, regb,
+       return data_ld_host_order(nfp_prog, meta, dst_gpr, rega, regb,
                                  size, CMD_MODE_40b_BA);
 }
 
 static int
-construct_data_ind_ld(struct nfp_prog *nfp_prog, u16 offset, u16 src, u8 size)
+construct_data_ind_ld(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
+                     u16 offset, u16 src, u8 size)
 {
        swreg tmp_reg;
 
        emit_br_relo(nfp_prog, BR_BLO, BR_OFF_RELO, 0, RELO_BR_GO_ABORT);
 
        /* Load data */
-       return data_ld(nfp_prog, imm_b(nfp_prog), 0, size);
+       return data_ld(nfp_prog, meta, imm_b(nfp_prog), 0, size);
 }
 
-static int construct_data_ld(struct nfp_prog *nfp_prog, u16 offset, u8 size)
+static int
+construct_data_ld(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
+                 u16 offset, u8 size)
 {
        swreg tmp_reg;
 
 
        /* Load data */
        tmp_reg = re_load_imm_any(nfp_prog, offset, imm_b(nfp_prog));
-       return data_ld(nfp_prog, tmp_reg, 0, size);
+       return data_ld(nfp_prog, meta, tmp_reg, 0, size);
 }
 
 static int
        }
 
        if (clr_gpr && size < 8)
-               wrp_immed(nfp_prog, reg_both(gpr + 1), 0);
+               wrp_zext(nfp_prog, meta, gpr);
 
        while (size) {
                u32 slice_end;
              enum alu_op alu_op)
 {
        const struct bpf_insn *insn = &meta->insn;
+       u8 dst = insn->dst_reg * 2;
 
-       wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, insn->imm);
-       wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
+       wrp_alu_imm(nfp_prog, dst, alu_op, insn->imm);
+       wrp_zext(nfp_prog, meta, dst);
 
        return 0;
 }
        u8 dst = meta->insn.dst_reg * 2, src = meta->insn.src_reg * 2;
 
        emit_alu(nfp_prog, reg_both(dst), reg_a(dst), alu_op, reg_b(src));
-       wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
 
        return 0;
 }
        u8 dst = meta->insn.dst_reg * 2;
 
        emit_alu(nfp_prog, reg_both(dst), reg_imm(0), ALU_OP_SUB, reg_b(dst));
-       wrp_immed(nfp_prog, reg_both(meta->insn.dst_reg * 2 + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
 
        return 0;
 }
 
-static int __ashr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
+static int
+__ashr_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, u8 dst,
+          u8 shift_amt)
 {
        if (shift_amt) {
                /* Set signedness bit (MSB of result). */
                emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR,
                         reg_b(dst), SHF_SC_R_SHF, shift_amt);
        }
-       wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
 
        return 0;
 }
        umin = meta->umin_src;
        umax = meta->umax_src;
        if (umin == umax)
-               return __ashr_imm(nfp_prog, dst, umin);
+               return __ashr_imm(nfp_prog, meta, dst, umin);
 
        src = insn->src_reg * 2;
        /* NOTE: the first insn will set both indirect shift amount (source A)
        emit_alu(nfp_prog, reg_none(), reg_a(src), ALU_OP_OR, reg_b(dst));
        emit_shf_indir(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR,
                       reg_b(dst), SHF_SC_R_SHF);
-       wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
 
        return 0;
 }
        const struct bpf_insn *insn = &meta->insn;
        u8 dst = insn->dst_reg * 2;
 
-       return __ashr_imm(nfp_prog, dst, insn->imm);
+       return __ashr_imm(nfp_prog, meta, dst, insn->imm);
 }
 
-static int __shr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
+static int
+__shr_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, u8 dst,
+         u8 shift_amt)
 {
        if (shift_amt)
                emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE,
                         reg_b(dst), SHF_SC_R_SHF, shift_amt);
-       wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
        return 0;
 }
 
        const struct bpf_insn *insn = &meta->insn;
        u8 dst = insn->dst_reg * 2;
 
-       return __shr_imm(nfp_prog, dst, insn->imm);
+       return __shr_imm(nfp_prog, meta, dst, insn->imm);
 }
 
 static int shr_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
        umin = meta->umin_src;
        umax = meta->umax_src;
        if (umin == umax)
-               return __shr_imm(nfp_prog, dst, umin);
+               return __shr_imm(nfp_prog, meta, dst, umin);
 
        src = insn->src_reg * 2;
        emit_alu(nfp_prog, reg_none(), reg_a(src), ALU_OP_OR, reg_imm(0));
        emit_shf_indir(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE,
                       reg_b(dst), SHF_SC_R_SHF);
-       wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
        return 0;
 }
 
-static int __shl_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt)
+static int
+__shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta, u8 dst,
+         u8 shift_amt)
 {
        if (shift_amt)
                emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_NONE,
                         reg_b(dst), SHF_SC_L_SHF, shift_amt);
-       wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
        return 0;
 }
 
        const struct bpf_insn *insn = &meta->insn;
        u8 dst = insn->dst_reg * 2;
 
-       return __shl_imm(nfp_prog, dst, insn->imm);
+       return __shl_imm(nfp_prog, meta, dst, insn->imm);
 }
 
 static int shl_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
        umin = meta->umin_src;
        umax = meta->umax_src;
        if (umin == umax)
-               return __shl_imm(nfp_prog, dst, umin);
+               return __shl_imm(nfp_prog, meta, dst, umin);
 
        src = insn->src_reg * 2;
        shl_reg64_lt32_low(nfp_prog, dst, src);
-       wrp_immed(nfp_prog, reg_both(dst + 1), 0);
+       wrp_zext(nfp_prog, meta, dst);
        return 0;
 }
 
 
 static int data_ld1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return construct_data_ld(nfp_prog, meta->insn.imm, 1);
+       return construct_data_ld(nfp_prog, meta, meta->insn.imm, 1);
 }
 
 static int data_ld2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return construct_data_ld(nfp_prog, meta->insn.imm, 2);
+       return construct_data_ld(nfp_prog, meta, meta->insn.imm, 2);
 }
 
 static int data_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return construct_data_ld(nfp_prog, meta->insn.imm, 4);
+       return construct_data_ld(nfp_prog, meta, meta->insn.imm, 4);
 }
 
 static int data_ind_ld1(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return construct_data_ind_ld(nfp_prog, meta->insn.imm,
+       return construct_data_ind_ld(nfp_prog, meta, meta->insn.imm,
                                     meta->insn.src_reg * 2, 1);
 }
 
 static int data_ind_ld2(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return construct_data_ind_ld(nfp_prog, meta->insn.imm,
+       return construct_data_ind_ld(nfp_prog, meta, meta->insn.imm,
                                     meta->insn.src_reg * 2, 2);
 }
 
 static int data_ind_ld4(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return construct_data_ind_ld(nfp_prog, meta->insn.imm,
+       return construct_data_ind_ld(nfp_prog, meta, meta->insn.imm,
                                     meta->insn.src_reg * 2, 4);
 }
 
 
        tmp_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog));
 
-       return data_ld_host_order_addr32(nfp_prog, meta->insn.src_reg * 2,
+       return data_ld_host_order_addr32(nfp_prog, meta, meta->insn.src_reg * 2,
                                         tmp_reg, meta->insn.dst_reg * 2, size);
 }
 
 
        tmp_reg = re_load_imm_any(nfp_prog, meta->insn.off, imm_b(nfp_prog));
 
-       return data_ld_host_order_addr40(nfp_prog, meta->insn.src_reg * 2,
+       return data_ld_host_order_addr40(nfp_prog, meta, meta->insn.src_reg * 2,
                                         tmp_reg, meta->insn.dst_reg * 2, size);
 }
 
        wrp_reg_subpart(nfp_prog, dst_lo, src_lo, len_lo, off);
 
        if (!len_mid) {
-               wrp_immed(nfp_prog, dst_hi, 0);
+               wrp_zext(nfp_prog, meta, dst_gpr);
                return 0;
        }
 
 
        if (size <= REG_WIDTH) {
                wrp_reg_or_subpart(nfp_prog, dst_lo, src_mid, len_mid, len_lo);
-               wrp_immed(nfp_prog, dst_hi, 0);
+               wrp_zext(nfp_prog, meta, dst_gpr);
        } else {
                swreg src_hi = reg_xfer(idx + 2);
 
 
        if (size < REG_WIDTH) {
                wrp_reg_subpart(nfp_prog, dst_lo, src_lo, size, 0);
-               wrp_immed(nfp_prog, dst_hi, 0);
+               wrp_zext(nfp_prog, meta, dst_gpr);
        } else if (size == REG_WIDTH) {
                wrp_mov(nfp_prog, dst_lo, src_lo);
-               wrp_immed(nfp_prog, dst_hi, 0);
+               wrp_zext(nfp_prog, meta, dst_gpr);
        } else {
                swreg src_hi = reg_xfer(idx + 1);