@@ -6499,6 +6499,93 @@ RVOP(vid_v, {
64996499 rvv_exec_vid (rv , ir , ir -> vd );
65006500})
65016501
6502+ /* Integer extension (V 1.0 §11.3): widen each SEW/factor-wide source
6503+ * element into a full SEW-wide destination element, either zero- or
6504+ * sign-extended. The source EEW is SEW/factor with EMUL = LMUL/factor,
6505+ * so the source group span is derived from that narrower width while the
6506+ * destination keeps the SEW-based span.
6507+ */
6508+ static inline bool rvv_exec_int_extend (riscv_t * rv ,
6509+ const rv_insn_t * ir ,
6510+ uint32_t factor ,
6511+ bool is_signed )
6512+ {
6513+ uint32_t sew_bits = rvv_sew_bits (rv -> csr_vtype );
6514+ uint32_t src_bits = sew_bits / factor ;
6515+ uint32_t vlmax = rvv_vlmax (rv -> csr_vtype );
6516+ uint64_t fill = rvv_elem_mask64 (sew_bits );
6517+ uint8_t vma = (rv -> csr_vtype >> 7 ) & 0x1 ;
6518+ uint8_t vta = (rv -> csr_vtype >> 6 ) & 0x1 ;
6519+ uint32_t src_span , dest_span = rvv_group_regs (rv -> csr_vtype );
6520+ uint32_t lmul_num , lmul_den ;
6521+ bool src_emul_below_one ;
6522+
6523+ /* EMUL of the source is (EEW/SEW)*LMUL (V 1.0 §11.3); compare it to 1
6524+ * without losing the fractional case, which rvv_eew_reg_span() clamps
6525+ * to a span of one register.
6526+ */
6527+ rvv_lmul_ratio (rv -> csr_vtype , & lmul_num , & lmul_den );
6528+ src_emul_below_one =
6529+ ((uint64_t ) lmul_num * src_bits ) < ((uint64_t ) lmul_den * sew_bits );
6530+
6531+ /* A source narrower than 8 bits has no architectural encoding; this
6532+ * rejects e.g. vzext.vf8 at SEW=32 (V 1.0 §11.3).
6533+ */
6534+ if (src_bits < 8 )
6535+ return rvv_trap_illegal_state (rv , 0 );
6536+ if (!rvv_eew_reg_span (rv , src_bits , & src_span ) ||
6537+ !rvv_validate_data_reg (rv -> csr_vtype , ir -> vd ) ||
6538+ !rvv_validate_eew_reg (rv , src_bits , ir -> vs2 ))
6539+ return rvv_trap_illegal_state (rv , 0 );
6540+ /* Per V 1.0 §5.2, a destination whose EEW exceeds the source EEW may
6541+ * overlap the source only when the source EMUL is at least 1 and the
6542+ * overlap sits in the HIGHEST-numbered part of the destination group
6543+ * (at LMUL=8, `vzext.vf4 v0, v6` is legal but `v0, v0` is not). This
6544+ * differs from the widening-arithmetic rule in
6545+ * rvv_cross_eew_overlap_illegal(), which pins both groups to a shared
6546+ * base register, so the check is spelled out here.
6547+ */
6548+ if (rvv_reg_spans_overlap (ir -> vd , dest_span , ir -> vs2 , src_span ) &&
6549+ (src_emul_below_one || ((ir -> vs2 + src_span ) != (ir -> vd + dest_span ))))
6550+ return rvv_trap_illegal_state (rv , 0 );
6551+
6552+ for (uint32_t elem = rv -> csr_vstart ; elem < rv -> csr_vl ; elem ++ ) {
6553+ uint64_t value ;
6554+ if (!rvv_mask_enabled_for_elem (rv , ir , elem )) {
6555+ if (vma )
6556+ rvv_set_elem_ext (rv , ir -> vd , elem , sew_bits , fill );
6557+ continue ;
6558+ }
6559+ value = rvv_get_elem_ext (rv , ir -> vs2 , elem , src_bits );
6560+ if (is_signed )
6561+ value = (uint64_t ) rvv_sign_extend64 (value , src_bits );
6562+ rvv_set_elem_ext (rv , ir -> vd , elem , sew_bits ,
6563+ value & rvv_elem_mask64 (sew_bits ));
6564+ }
6565+ if (vta ) {
6566+ for (uint32_t elem = rv -> csr_vl ; elem < vlmax ; elem ++ )
6567+ rvv_set_elem_ext (rv , ir -> vd , elem , sew_bits , fill );
6568+ }
6569+
6570+ rv -> csr_vstart = 0 ;
6571+ return true;
6572+ }
6573+
6574+ #define RVV_INT_EXTEND_OP (name , factor , is_signed ) \
6575+ RVOP(name, { \
6576+ if (rvv_require_operable(rv)) \
6577+ return false; \
6578+ if (!rvv_exec_int_extend(rv, ir, factor, is_signed)) \
6579+ return false; \
6580+ })
6581+
6582+ RVV_INT_EXTEND_OP (vzext_vf2 , 2 , false)
6583+ RVV_INT_EXTEND_OP (vsext_vf2 , 2 , true)
6584+ RVV_INT_EXTEND_OP (vzext_vf4 , 4 , false)
6585+ RVV_INT_EXTEND_OP (vsext_vf4 , 4 , true)
6586+ RVV_INT_EXTEND_OP (vzext_vf8 , 8 , false)
6587+ RVV_INT_EXTEND_OP (vsext_vf8 , 8 , true)
6588+
65026589#if RV32_HAS (EXT_F )
65036590typedef uint32_t (* rvv_fp32_binop_fn )(uint32_t lhs , uint32_t rhs );
65046591typedef uint32_t (* rvv_fp32_triop_fn )(uint32_t dest ,
0 commit comments