adds all arithmetic Zvk extensions
This commit is contained in:
@ -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};
|
||||
|
@ -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");
|
||||
}
|
||||
|
Reference in New Issue
Block a user