A64: Implement SCVTF, UCVTF (scalar, fixed-point)

This commit is contained in:
MerryMage 2018-09-18 20:45:17 +01:00
parent 8051f60db0
commit 027b0ef725
2 changed files with 58 additions and 2 deletions

View file

@ -878,8 +878,8 @@ INST(SHA512SU0, "SHA512SU0", "11001
INST(SM4E, "SM4E", "1100111011000000100001nnnnnddddd") INST(SM4E, "SM4E", "1100111011000000100001nnnnnddddd")
// Data Processing - FP and SIMD - Conversion between floating point and fixed point // Data Processing - FP and SIMD - Conversion between floating point and fixed point
//INST(SCVTF_float_fix, "SCVTF (scalar, fixed-point)", "z0011110yy000010ppppppnnnnnddddd") INST(SCVTF_float_fix, "SCVTF (scalar, fixed-point)", "z0011110yy000010ppppppnnnnnddddd")
//INST(UCVTF_float_fix, "UCVTF (scalar, fixed-point)", "z0011110yy000011ppppppnnnnnddddd") INST(UCVTF_float_fix, "UCVTF (scalar, fixed-point)", "z0011110yy000011ppppppnnnnnddddd")
INST(FCVTZS_float_fix, "FCVTZS (scalar, fixed-point)", "z0011110yy011000ppppppnnnnnddddd") INST(FCVTZS_float_fix, "FCVTZS (scalar, fixed-point)", "z0011110yy011000ppppppnnnnnddddd")
INST(FCVTZU_float_fix, "FCVTZU (scalar, fixed-point)", "z0011110yy011001ppppppnnnnnddddd") INST(FCVTZU_float_fix, "FCVTZU (scalar, fixed-point)", "z0011110yy011001ppppppnnnnnddddd")

View file

@ -10,6 +10,62 @@
namespace Dynarmic::A64 { namespace Dynarmic::A64 {
bool TranslatorVisitor::SCVTF_float_fix(bool sf, Imm<2> type, Imm<6> scale, Reg Rn, Vec Vd) {
const size_t intsize = sf ? 64 : 32;
const auto fltsize = FPGetDataSize(type);
if (!fltsize || *fltsize == 16) {
return UnallocatedEncoding();
}
if (!sf && !scale.Bit<5>()) {
return UnallocatedEncoding();
}
const u8 fracbits = 64 - scale.ZeroExtend<u8>();
const FP::RoundingMode rounding_mode = ir.current_location->FPCR().RMode();
const IR::U32U64 intval = X(intsize, Rn);
const IR::U32U64 fltval = [&]() -> IR::U32U64 {
switch (*fltsize) {
case 32:
return ir.FPSignedFixedToSingle(intval, fracbits, rounding_mode);
case 64:
return ir.FPSignedFixedToDouble(intval, fracbits, rounding_mode);
}
UNREACHABLE();
return {};
}();
V_scalar(*fltsize, Vd, fltval);
return true;
}
bool TranslatorVisitor::UCVTF_float_fix(bool sf, Imm<2> type, Imm<6> scale, Reg Rn, Vec Vd) {
const size_t intsize = sf ? 64 : 32;
const auto fltsize = FPGetDataSize(type);
if (!fltsize || *fltsize == 16) {
return UnallocatedEncoding();
}
if (!sf && !scale.Bit<5>()) {
return UnallocatedEncoding();
}
const u8 fracbits = 64 - scale.ZeroExtend<u8>();
const FP::RoundingMode rounding_mode = ir.current_location->FPCR().RMode();
const IR::U32U64 intval = X(intsize, Rn);
const IR::U32U64 fltval = [&]() -> IR::U32U64 {
switch (*fltsize) {
case 32:
return ir.FPUnsignedFixedToSingle(intval, fracbits, rounding_mode);
case 64:
return ir.FPUnsignedFixedToDouble(intval, fracbits, rounding_mode);
}
UNREACHABLE();
return {};
}();
V_scalar(*fltsize, Vd, fltval);
return true;
}
bool TranslatorVisitor::FCVTZS_float_fix(bool sf, Imm<2> type, Imm<6> scale, Vec Vn, Reg Rd) { bool TranslatorVisitor::FCVTZS_float_fix(bool sf, Imm<2> type, Imm<6> scale, Vec Vn, Reg Rd) {
const size_t intsize = sf ? 64 : 32; const size_t intsize = sf ? 64 : 32;
const auto fltsize = FPGetDataSize(type); const auto fltsize = FPGetDataSize(type);