adds all arithmetic Zvk extensions

This commit is contained in:
2025-06-30 10:41:22 +02:00
parent cd866fd74d
commit a768bde7f2
2 changed files with 147 additions and 0 deletions

View File

@ -962,6 +962,20 @@ if(vector != null) {%>
throw new std::runtime_error("Unsupported sew bit value");
}
}
void vector_unary_op(uint8_t* V, uint8_t unary_op, uint64_t vl, uint64_t vstart, softvector::vtype_t vtype, bool vm, uint8_t vd, uint8_t vs2, uint8_t sew_val){
switch(sew_val){
case 0b000:
return softvector::vector_unary_op<${vlen}, uint8_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 0b001:
return softvector::vector_unary_op<${vlen}, uint16_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 0b010:
return softvector::vector_unary_op<${vlen}, uint32_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
case 0b011:
return softvector::vector_unary_op<${vlen}, uint64_t>(V, unary_op, vl, vstart, vtype, vm, vd, vs2);
default:
throw new std::runtime_error("Unsupported sew_val");
}
}
<%}%>
uint64_t fetch_count{0};
uint64_t tval{0};

View File

@ -180,6 +180,8 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
switch(funct6) {
case 0b000000: // VADD
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 + vs1; };
case 0b000001: // VANDN
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 & ~vs1; };
case 0b000010: // VSUB
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 - vs1; };
case 0b000011: // VRSUB
@ -205,6 +207,22 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
return static_cast<std::make_signed_t<dest_elem_t>>(static_cast<std::make_signed_t<src2_elem_t>>(vs2) -
static_cast<std::make_signed_t<src1_elem_t>>(vs1));
};
case 0b010100: // VROR
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
auto shamt = vs1 & shift_mask<src1_elem_t>();
return (vs2 >> shamt) | (vs2 << (bits - shamt));
};
case 0b010101: { // VROL
if(funct3 == OPIVI)
return get_funct<dest_elem_t>(0b010100, funct3);
else
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
auto shamt = vs1 & shift_mask<src1_elem_t>();
return (vs2 << shamt) | (vs2 >> (bits - shamt));
};
}
case 0b100101: // VSLL
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) { return vs2 << (vs1 & shift_mask<src2_elem_t>()); };
case 0b101000: // VSRL
@ -219,6 +237,28 @@ std::function<dest_elem_t(dest_elem_t, src2_elem_t, src1_elem_t)> get_funct(unsi
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
return static_cast<std::make_signed_t<src2_elem_t>>(vs2) >> (vs1 & shift_mask<src2_elem_t>());
};
case 0b110101: // VWSLL
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
return static_cast<dest_elem_t>(vs2) << (vs1 & (shift_mask<dest_elem_t>()));
};
case 0b001100: // VCLMUL
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
dest_elem_t output = 0;
for(size_t i = 0; i <= sizeof(dest_elem_t) * 8 - 1; i++) {
if((vs2 >> i) & 1)
output = output ^ (vs1 << i);
}
return output;
};
case 0b001101: // VCLMULH
return [](dest_elem_t vd, src2_elem_t vs2, src1_elem_t vs1) {
dest_elem_t output = 0;
for(size_t i = 1; i < sizeof(dest_elem_t) * 8; i++) {
if((vs2 >> i) & 1)
output = output ^ (vs1 >> (sizeof(dest_elem_t) * 8 - i));
}
return output;
};
default:
throw new std::runtime_error("Unknown funct6 in get_funct");
}
@ -534,6 +574,99 @@ std::function<dest_elem_t(src2_elem_t)> get_unary_fn(unsigned unary_op) {
case 0b00100: // VZEXT.VF4
case 0b00010: // VZEXT.VF8
return [](src2_elem_t vs2) { return vs2; };
case 0b01000: // VBREV8
return [](src2_elem_t vs2) {
constexpr unsigned byte_count = sizeof(src2_elem_t);
dest_elem_t result = 0;
for(size_t i = 0; i < byte_count; ++i) {
uint8_t byte = (vs2 >> (i * 8)) & 0xFF;
byte = ((byte & 0xF0) >> 4) | ((byte & 0x0F) << 4);
byte = ((byte & 0xCC) >> 2) | ((byte & 0x33) << 2);
byte = ((byte & 0xAA) >> 1) | ((byte & 0x55) << 1);
result |= byte << (i * 8);
}
return result;
};
case 0b01001: // VREV8
return [](src2_elem_t vs2) {
constexpr unsigned byte_count = sizeof(src2_elem_t);
dest_elem_t result = 0;
for(size_t i = 0; i < byte_count; ++i) {
result <<= 8;
result |= (vs2 & 0xFF);
vs2 >>= 8;
}
return result;
};
case 0b01010: // VBREV
return [](src2_elem_t vs2) {
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
dest_elem_t result = 0;
for(size_t i = 0; i < bits; ++i) {
result <<= 1;
result |= (vs2 & 1);
vs2 >>= 1;
}
return result;
};
case 0b01100: // VCLZ
return [](src2_elem_t vs2) {
if(std::is_same_v<src2_elem_t, unsigned int>)
return static_cast<dest_elem_t>(__builtin_clz(vs2));
else if(std::is_same_v<src2_elem_t, unsigned long>)
return static_cast<dest_elem_t>(__builtin_clzl(vs2));
else if(std::is_same_v<src2_elem_t, unsigned long long>)
return static_cast<dest_elem_t>(__builtin_clzll(vs2));
else {
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
if(vs2 == 0)
return bits;
dest_elem_t count = 0;
for(size_t i = bits - 1; i >= 0; --i) {
if((vs2 >> i) & 1)
break;
++count;
}
return count;
}
};
case 0b01101: // VCTZ
return [](src2_elem_t vs2) {
if(std::is_same_v<src2_elem_t, unsigned int>)
return static_cast<dest_elem_t>(__builtin_ctz(vs2));
else if(std::is_same_v<src2_elem_t, unsigned long>)
return static_cast<dest_elem_t>(__builtin_ctzl(vs2));
else if(std::is_same_v<src2_elem_t, unsigned long long>)
return static_cast<dest_elem_t>(__builtin_ctzll(vs2));
else {
constexpr dest_elem_t bits = sizeof(src2_elem_t) * 8;
if(vs2 == 0)
return bits;
dest_elem_t count = 0;
while((vs2 & 1) == 0) {
++count;
vs2 >>= 1;
}
return count;
}
};
case 0b01110: // VCPOP
return [](src2_elem_t vs2) {
if(std::is_same_v<src2_elem_t, unsigned int>)
return static_cast<dest_elem_t>(__builtin_popcount(vs2));
else if(std::is_same_v<src2_elem_t, unsigned long>)
return static_cast<dest_elem_t>(__builtin_popcountl(vs2));
else if(std::is_same_v<src2_elem_t, unsigned long long>)
return static_cast<dest_elem_t>(__builtin_popcountll(vs2));
else {
dest_elem_t count = 0;
while(vs2) {
count += vs2 & 1;
vs2 >>= 1;
}
return count;
}
};
default:
throw new std::runtime_error("Unknown funct in get_unary_fn");
}