diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 62e81528..235e6d09 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -74,6 +74,7 @@ add_library(dynarmic frontend/A64/translate/impl/data_processing_register.cpp frontend/A64/translate/impl/data_processing_shift.cpp frontend/A64/translate/impl/exception_generating.cpp + frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp frontend/A64/translate/impl/impl.cpp frontend/A64/translate/impl/impl.h frontend/A64/translate/impl/load_store_load_literal.cpp diff --git a/src/frontend/A64/decoder/a64.inc b/src/frontend/A64/decoder/a64.inc index c7ff429e..309fba19 100644 --- a/src/frontend/A64/decoder/a64.inc +++ b/src/frontend/A64/decoder/a64.inc @@ -940,15 +940,15 @@ INST(EOR_asimd, "EOR (vector)", "0Q101 //INST(FCCMPE_float, "FCCMPE", "00011110yy1mmmmmcccc01nnnnn1ffff") // Data Processing - FP and SIMD - Floating point data processing two register -//INST(FMUL_float, "FMUL (scalar)", "00011110yy1mmmmm000010nnnnnddddd") -//INST(FDIV_float, "FDIV (scalar)", "00011110yy1mmmmm000110nnnnnddddd") -//INST(FADD_float, "FADD (scalar)", "00011110yy1mmmmm001010nnnnnddddd") -//INST(FSUB_float, "FSUB (scalar)", "00011110yy1mmmmm001110nnnnnddddd") +INST(FMUL_float, "FMUL (scalar)", "00011110yy1mmmmm000010nnnnnddddd") +INST(FDIV_float, "FDIV (scalar)", "00011110yy1mmmmm000110nnnnnddddd") +INST(FADD_float, "FADD (scalar)", "00011110yy1mmmmm001010nnnnnddddd") +INST(FSUB_float, "FSUB (scalar)", "00011110yy1mmmmm001110nnnnnddddd") //INST(FMAX_float, "FMAX (scalar)", "00011110yy1mmmmm010010nnnnnddddd") //INST(FMIN_float, "FMIN (scalar)", "00011110yy1mmmmm010110nnnnnddddd") //INST(FMAXNM_float, "FMAXNM (scalar)", "00011110yy1mmmmm011010nnnnnddddd") //INST(FMINNM_float, "FMINNM (scalar)", "00011110yy1mmmmm011110nnnnnddddd") -//INST(FNMUL_float, "FNMUL (scalar)", "00011110yy1mmmmm100010nnnnnddddd") +INST(FNMUL_float, "FNMUL (scalar)", "00011110yy1mmmmm100010nnnnnddddd") // Data Processing - FP and SIMD - Floating point conditional select //INST(FCSEL_float, "FCSEL", "00011110yy1mmmmmcccc11nnnnnddddd") diff --git a/src/frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp b/src/frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp new file mode 100644 index 00000000..5817b39b --- /dev/null +++ b/src/frontend/A64/translate/impl/floating_point_data_processing_two_register.cpp @@ -0,0 +1,101 @@ +/* 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 + +#include "frontend/A64/translate/impl/impl.h" + +namespace Dynarmic::A64 { + +static boost::optional GetDataSize(Imm<2> type) { + switch (type.ZeroExtend()) { + case 0b00: + return 32; + case 0b01: + return 64; + case 0b11: + // FP16Ext, unimplemented. + return boost::none; + } + return boost::none; +} + +bool TranslatorVisitor::FMUL_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) { + auto datasize = GetDataSize(type); + if (!datasize) { + return UnallocatedEncoding(); + } + + const IR::U32U64 operand1 = V_scalar(*datasize, Vn); + const IR::U32U64 operand2 = V_scalar(*datasize, Vm); + + const IR::U32U64 result = ir.FPMul(operand1, operand2, true); + + V_scalar(*datasize, Vd, result); + return true; +} + +bool TranslatorVisitor::FDIV_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) { + auto datasize = GetDataSize(type); + if (!datasize) { + return UnallocatedEncoding(); + } + + const IR::U32U64 operand1 = V_scalar(*datasize, Vn); + const IR::U32U64 operand2 = V_scalar(*datasize, Vm); + + const IR::U32U64 result = ir.FPDiv(operand1, operand2, true); + + V_scalar(*datasize, Vd, result); + return true; +} + +bool TranslatorVisitor::FADD_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) { + auto datasize = GetDataSize(type); + if (!datasize) { + return UnallocatedEncoding(); + } + + const IR::U32U64 operand1 = V_scalar(*datasize, Vn); + const IR::U32U64 operand2 = V_scalar(*datasize, Vm); + + const IR::U32U64 result = ir.FPAdd(operand1, operand2, true); + + V_scalar(*datasize, Vd, result); + return true; +} + +bool TranslatorVisitor::FSUB_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) { + auto datasize = GetDataSize(type); + if (!datasize) { + return UnallocatedEncoding(); + } + + const IR::U32U64 operand1 = V_scalar(*datasize, Vn); + const IR::U32U64 operand2 = V_scalar(*datasize, Vm); + + const IR::U32U64 result = ir.FPSub(operand1, operand2, true); + + V_scalar(*datasize, Vd, result); + return true; +} + +bool TranslatorVisitor::FNMUL_float(Imm<2> type, Vec Vm, Vec Vn, Vec Vd) { + auto datasize = GetDataSize(type); + if (!datasize) { + return UnallocatedEncoding(); + } + + const IR::U32U64 operand1 = V_scalar(*datasize, Vn); + const IR::U32U64 operand2 = V_scalar(*datasize, Vm); + + const IR::U32U64 result = ir.FPNeg(ir.FPMul(operand1, operand2, true)); + + V_scalar(*datasize, Vd, result); + return true; +} + +} // namespace Dynarmic::A64 diff --git a/src/frontend/A64/translate/impl/impl.cpp b/src/frontend/A64/translate/impl/impl.cpp index 835d35c4..85c05b4d 100644 --- a/src/frontend/A64/translate/impl/impl.cpp +++ b/src/frontend/A64/translate/impl/impl.cpp @@ -151,6 +151,16 @@ void TranslatorVisitor::V(size_t bitsize, Vec vec, IR::U128 value) { } } +IR::UAny TranslatorVisitor::V_scalar(size_t bitsize, Vec vec) { + // TODO: Optimize + return ir.VectorGetElement(bitsize, ir.GetQ(vec), 0); +} + +void TranslatorVisitor::V_scalar(size_t /*bitsize*/, Vec vec, IR::UAny value) { + // TODO: Optimize + ir.SetQ(vec, ir.ZeroExtendToQuad(value)); +} + IR::UAnyU128 TranslatorVisitor::Mem(IR::U64 address, size_t bytesize, AccType /*acctype*/) { switch (bytesize) { case 1: diff --git a/src/frontend/A64/translate/impl/impl.h b/src/frontend/A64/translate/impl/impl.h index 59ee16ac..5b1aea66 100644 --- a/src/frontend/A64/translate/impl/impl.h +++ b/src/frontend/A64/translate/impl/impl.h @@ -50,6 +50,9 @@ struct TranslatorVisitor final { IR::U128 V(size_t bitsize, Vec vec); void V(size_t bitsize, Vec vec, IR::U128 value); + IR::UAny V_scalar(size_t bitsize, Vec vec); + void V_scalar(size_t bitsize, Vec vec, IR::UAny value); + IR::UAnyU128 Mem(IR::U64 address, size_t size, AccType acctype); void Mem(IR::U64 address, size_t size, AccType acctype, IR::UAnyU128 value);