A64: Partially implement FCVTZU (scalar, fixed-point) and FCVTZS (scalar, fixed-point)

This commit is contained in:
MerryMage 2018-02-20 18:45:28 +00:00
parent e4697b1676
commit be57608353
4 changed files with 92 additions and 2 deletions

View file

@ -79,6 +79,7 @@ add_library(dynarmic
frontend/A64/translate/impl/data_processing_shift.cpp frontend/A64/translate/impl/data_processing_shift.cpp
frontend/A64/translate/impl/exception_generating.cpp frontend/A64/translate/impl/exception_generating.cpp
frontend/A64/translate/impl/floating_point_compare.cpp frontend/A64/translate/impl/floating_point_compare.cpp
frontend/A64/translate/impl/floating_point_conversion_fixed_point.cpp
frontend/A64/translate/impl/floating_point_conversion_integer.cpp frontend/A64/translate/impl/floating_point_conversion_integer.cpp
frontend/A64/translate/impl/floating_point_conditional_compare.cpp frontend/A64/translate/impl/floating_point_conditional_compare.cpp
frontend/A64/translate/impl/floating_point_conditional_select.cpp frontend/A64/translate/impl/floating_point_conditional_select.cpp

View file

@ -876,8 +876,8 @@ INST(USHLL, "USHLL, USHLL2", "0Q101
// 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")
// Data Processing - FP and SIMD - Conversion between floating point and integer // Data Processing - FP and SIMD - Conversion between floating point and integer
//INST(FCVTNS_float, "FCVTNS (scalar)", "z0011110yy100000000000nnnnnddddd") //INST(FCVTNS_float, "FCVTNS (scalar)", "z0011110yy100000000000nnnnnddddd")

View file

@ -0,0 +1,87 @@
/* This file is part of the dynarmic project.
* Copyright (c) 2018 MerryMage
* This software may be used and distributed according to the terms of the GNU
* General Public License version 2 or any later version.
*/
#include <boost/optional.hpp>
#include "frontend/A64/translate/impl/impl.h"
namespace Dynarmic::A64 {
static boost::optional<size_t> GetDataSize(Imm<2> type) {
switch (type.ZeroExtend()) {
case 0b00:
return 32;
case 0b01:
return 64;
case 0b11:
return 16;
}
return boost::none;
}
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 auto fltsize = GetDataSize(type);
if (!fltsize || *fltsize == 16) {
return UnallocatedEncoding();
}
if (!sf && !scale.Bit<5>()) {
return UnallocatedEncoding();
}
const u8 fracbits = 64 - scale.ZeroExtend<u8>();
const IR::U32U64 fltscale = I(*fltsize, u64(fracbits + (*fltsize == 32 ? 127 : 1023)) << (*fltsize == 32 ? 23 : 52));
const IR::U32U64 fltval = ir.FPMul(V_scalar(*fltsize, Vn), fltscale, true);
IR::U32U64 intval;
if (intsize == 32 && *fltsize == 32) {
intval = ir.FPSingleToS32(fltval, true, true);
} else if (intsize == 32 && *fltsize == 64) {
intval = ir.FPDoubleToS32(fltval, true, true);
} else if (intsize == 64 && *fltsize == 32) {
return InterpretThisInstruction();
} else if (intsize == 64 && *fltsize == 64) {
return InterpretThisInstruction();
} else {
UNREACHABLE();
}
X(intsize, Rd, intval);
return true;
}
bool TranslatorVisitor::FCVTZU_float_fix(bool sf, Imm<2> type, Imm<6> scale, Vec Vn, Reg Rd) {
const size_t intsize = sf ? 64 : 32;
const auto fltsize = GetDataSize(type);
if (!fltsize || *fltsize == 16) {
return UnallocatedEncoding();
}
if (!sf && !scale.Bit<5>()) {
return UnallocatedEncoding();
}
const u8 fracbits = 64 - scale.ZeroExtend<u8>();
const IR::U32U64 fltscale = I(*fltsize, u64(fracbits + (*fltsize == 32 ? 127 : 1023)) << (*fltsize == 32 ? 23 : 52));
const IR::U32U64 fltval = ir.FPMul(V_scalar(*fltsize, Vn), fltscale, true);
IR::U32U64 intval;
if (intsize == 32 && *fltsize == 32) {
intval = ir.FPSingleToU32(fltval, true, true);
} else if (intsize == 32 && *fltsize == 64) {
intval = ir.FPDoubleToU32(fltval, true, true);
} else if (intsize == 64 && *fltsize == 32) {
return InterpretThisInstruction();
} else if (intsize == 64 && *fltsize == 64) {
return InterpretThisInstruction();
} else {
UNREACHABLE();
}
X(intsize, Rd, intval);
return true;
}
} // namespace Dynarmic::A64

View file

@ -162,12 +162,14 @@ static void RunTestInstance(const std::array<u64, 31>& regs, const std::array<Ve
jit.SetVectors(vecs); jit.SetVectors(vecs);
jit.SetPC(instructions_offset * 4); jit.SetPC(instructions_offset * 4);
jit.SetSP(0x08000000); jit.SetSP(0x08000000);
jit.SetFpcr(0);
jit.SetPstate(pstate); jit.SetPstate(pstate);
jit.ClearCache(); jit.ClearCache();
uni.SetRegisters(regs); uni.SetRegisters(regs);
uni.SetVectors(vecs); uni.SetVectors(vecs);
uni.SetPC(instructions_offset * 4); uni.SetPC(instructions_offset * 4);
uni.SetSP(0x08000000); uni.SetSP(0x08000000);
uni.SetFpcr(0);
uni.SetPstate(pstate); uni.SetPstate(pstate);
uni.ClearPageCache(); uni.ClearPageCache();