Bochs/bochs/cpu/cpu_templates_pfp.h
2024-10-26 23:49:04 +03:00

369 lines
12 KiB
C++

/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2023 The Bochs Project
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
/////////////////////////////////////////////////////////////////////////
#ifndef BX_CPU_PFP_TEMPLATES_H
#define BX_CPU_PFP_TEMPLATES_H
#include "cpu/softfloat3e/include/softfloat.h"
extern softfloat_status_t mxcsr_to_softfloat_status_word(bx_mxcsr_t mxcsr);
#if BX_SUPPORT_EVEX == 0
#define softfloat_status_word_rc_override(status, i)
#else
extern void softfloat_status_word_rc_override(softfloat_status_t &status, bxInstruction_c *i);
#endif
template <xmm_pfp_1op func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_SSE_PFP_1OP(bxInstruction_c *i)
{
#if BX_CPU_LEVEL >= 6
BxPackedXmmRegister op = BX_READ_XMM_REG(i->src());
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
(func)(&op, status);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
BX_WRITE_XMM_REG(i->dst(), op);
#endif
BX_NEXT_INSTR(i);
}
template <xmm_pfp_2op func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_SSE_PFP_2OP(bxInstruction_c *i)
{
#if BX_CPU_LEVEL >= 6
BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src());
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
(func)(&op1, &op2, status);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
BX_WRITE_XMM_REG(i->dst(), op1);
#endif
BX_NEXT_INSTR(i);
}
#if BX_SUPPORT_AVX
template <xmm_pfp_1op func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX_PFP_1OP(bxInstruction_c *i)
{
BxPackedAvxRegister op = BX_READ_AVX_REG(i->src());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0; n < len; n++) {
(func)(&op.vmm128(n), status);
}
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
BX_WRITE_AVX_REGZ(i->dst(), op, len);
BX_NEXT_INSTR(i);
}
template <xmm_pfp_2op func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX_PFP_2OP(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0; n < len; n++) {
(func)(&op1.vmm128(n), &op2.vmm128(n), status);
}
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
BX_NEXT_INSTR(i);
}
template <xmm_pfp_3op func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX_PFP_3OP(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1());
BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2());
BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0; n < len; n++)
(func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
BX_NEXT_INSTR(i);
}
#if BX_SUPPORT_EVEX
#include "simd_int.h"
template <xmm_pfp_1op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_1OP_HALF(bxInstruction_c *i)
{
BxPackedAvxRegister op = BX_READ_AVX_REG(i->src());
unsigned mask = BX_READ_32BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 8)
(func)(&op.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_pblendw(&BX_READ_AVX_REG(i->dst()), &op, mask, WORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_1op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_1OP_SINGLE(bxInstruction_c *i)
{
BxPackedAvxRegister op = BX_READ_AVX_REG(i->src());
unsigned mask = BX_READ_16BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 4)
(func)(&op.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_blendps(&BX_READ_AVX_REG(i->dst()), &op, mask, DWORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_1op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_1OP_DOUBLE(bxInstruction_c *i)
{
BxPackedAvxRegister op = BX_READ_AVX_REG(i->src());
unsigned mask = BX_READ_8BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 2)
(func)(&op.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_blendpd(&BX_READ_AVX_REG(i->dst()), &op, mask, QWORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_2op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_2OP_SINGLE(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2());
unsigned mask = BX_READ_16BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 4)
(func)(&op1.vmm128(n), &op2.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_blendps(&BX_READ_AVX_REG(i->dst()), &op1, mask, DWORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_2op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_2OP_DOUBLE(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2());
unsigned mask = BX_READ_8BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 2)
(func)(&op1.vmm128(n), &op2.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_blendpd(&BX_READ_AVX_REG(i->dst()), &op1, mask, QWORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_2op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_2OP_HALF(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2());
unsigned mask = BX_READ_32BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 8)
(func)(&op1.vmm128(n), &op2.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_pblendw(&BX_READ_AVX_REG(i->dst()), &op1, mask, WORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_3op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_3OP_SINGLE(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1());
BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2());
BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3());
unsigned mask = BX_READ_16BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 4)
(func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_blendps(&BX_READ_AVX_REG(i->dst()), &op1, mask, DWORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_3op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_3OP_DOUBLE(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1());
BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2());
BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3());
unsigned mask = BX_READ_8BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 2)
(func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_blendpd(&BX_READ_AVX_REG(i->dst()), &op1, mask, QWORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
}
BX_NEXT_INSTR(i);
}
template <xmm_pfp_3op_mask func>
void BX_CPP_AttrRegparmN(1) BX_CPU_C::HANDLE_AVX512_MASK_PFP_3OP_HALF(bxInstruction_c *i)
{
BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1());
BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2());
BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3());
unsigned mask = BX_READ_32BIT_OPMASK(i->opmask());
unsigned len = i->getVL();
softfloat_status_t status = mxcsr_to_softfloat_status_word(MXCSR);
softfloat_status_word_rc_override(status, i);
for (unsigned n=0, tmp_mask = mask; n < len; n++, tmp_mask >>= 8)
(func)(&op1.vmm128(n), &op2.vmm128(n), &op3.vmm128(n), status, tmp_mask);
check_exceptionsSSE(softfloat_getExceptionFlags(&status));
if (! i->isZeroMasking()) {
simd_pblendw(&BX_READ_AVX_REG(i->dst()), &op1, mask, WORD_ELEMENTS(len));
BX_CLEAR_AVX_REGZ(i->dst(), len);
}
else {
BX_WRITE_AVX_REGZ(i->dst(), op1, len);
}
BX_NEXT_INSTR(i);
}
#endif // BX_SUPPORT_EVEX
#endif // BX_SUPPORT_AVX
#endif