mirror of
https://github.com/libretro/parallel-ps2.git
synced 2026-11-11 03:11:30 -10:00
Three changes, one intent: bare `make` and bare cmake now build the C89 emitter with nothing to specify, and common/emitter contains only the six headers the recompilers actually use (c89emit.h, x86emitter.h, x86types.h, instructions.h, legacy_instructions.h, x86emitter_shim.h). Default flip. Makefile gains `C89_EMITTER ?= 1` -- set BEFORE the Makefile.common include, because the source exclusion there reads it. The first attempt set it next to the CXXFLAGS append at line 839, after the include: the define applied but the exclusion never fired, and the build went on linking reference objects it no longer needed. Caught by `make -n` grep: a bare plan now names zero reference objects, a C89_EMITTER=0 plan names all eight. CMake's option defaults to ON with the same semantics (-DC89_EMITTER=OFF for the reference). Reference headers. internal.h, legacy_internal.h and the thirteen-header implement/ tree move to tests/emitter/reference beside the sources that need them. internal.h now includes the implement set itself -- it is the reference implementation's own root and must be self-sufficient; x86types.h includes them only under the reference configuration, for the extern declarations in instructions.h's #else branches. The three G*Type operator enums move into x86types.h: recompilers name their values, which makes them API, not implementation. iR5900-32.cpp's MOVQ-workaround include of internal.h was already reference-gated and is repointed. cmake's installed- header list is repointed too (the stale entries failed configure). Legacy jump API. The fourteen rel8/rel32 wrappers become macros over two static helpers (J8Rel, J32Rel), matching the C89 core's idiom. The helpers are static -- internal linkage per TU -- so there is no header-linkage subtlety left to get wrong, where the previous inline definitions carried one. The speculative conditional mode initially drafted into J32Rel was removed before commit: only the unconditional form has callers. The legacy SSE C-API wrappers (SSE_MINSS_XMM_to_XMM and friends) now emit through E_SSE_RR directly instead of hopping through the C++ shim objects. Their constants are proven end-to-end in newbind: reference function vs C89 macro across all register pairs, 2,048 cases within the 110,070 total. Verified: six suites green, switchover identical, both compile gates 31/31 in both configurations, bare make links at 11,351,104 bytes with zero reference encoder symbols and boots, cmake configure passes in both configurations. The cmake three-target build has not completed in this container (cmake 4 needs -DCMAKE_POLICY_VERSION_MINIMUM=3.5 for the vendored cpuinfo; GL dev packages were also missing) -- it needs one run on a normally-provisioned machine. C89_EMITTER=0 static: the gates and suites compile and byte-verify that configuration; its last full link ran two commits ago unchanged.
205 lines
7.6 KiB
C++
205 lines
7.6 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
*
|
|
* PCSX2 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 Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* PCSX2 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with PCSX2.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
namespace x86Emitter
|
|
{
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// _SimdShiftHelper
|
|
// --------------------------------------------------------------------------------------
|
|
struct _SimdShiftHelper
|
|
{
|
|
u8 Prefix;
|
|
u16 Opcode;
|
|
u16 OpcodeImm;
|
|
u8 Modcode;
|
|
|
|
void operator()(const xRegisterSSE& to, const xRegisterSSE& from) const;
|
|
void operator()(const xRegisterSSE& to, const xIndirectVoid& from) const;
|
|
|
|
void operator()(const xRegisterSSE& to, u8 imm8) const;
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// xImplSimd_Shift / xImplSimd_ShiftWithoutQ
|
|
// --------------------------------------------------------------------------------------
|
|
|
|
// Used for PSRA, which lacks the Q form.
|
|
//
|
|
struct xImplSimd_ShiftWithoutQ
|
|
{
|
|
const _SimdShiftHelper W;
|
|
const _SimdShiftHelper D;
|
|
};
|
|
|
|
// Implements PSRL and PSLL
|
|
//
|
|
struct xImplSimd_Shift
|
|
{
|
|
const _SimdShiftHelper W;
|
|
const _SimdShiftHelper D;
|
|
const _SimdShiftHelper Q;
|
|
|
|
void DQ(const xRegisterSSE& to, u8 imm8) const;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
struct xImplSimd_AddSub
|
|
{
|
|
const xImplSimd_DestRegEither B;
|
|
const xImplSimd_DestRegEither W;
|
|
const xImplSimd_DestRegEither D;
|
|
const xImplSimd_DestRegEither Q;
|
|
|
|
// Add/Sub packed signed byte [8bit] integers from src into dest, and saturate the results.
|
|
const xImplSimd_DestRegEither SB;
|
|
|
|
// Add/Sub packed signed word [16bit] integers from src into dest, and saturate the results.
|
|
const xImplSimd_DestRegEither SW;
|
|
|
|
// Add/Sub packed unsigned byte [8bit] integers from src into dest, and saturate the results.
|
|
const xImplSimd_DestRegEither USB;
|
|
|
|
// Add/Sub packed unsigned word [16bit] integers from src into dest, and saturate the results.
|
|
const xImplSimd_DestRegEither USW;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
struct xImplSimd_PMul
|
|
{
|
|
const xImplSimd_DestRegEither LW;
|
|
const xImplSimd_DestRegEither HW;
|
|
const xImplSimd_DestRegEither HUW;
|
|
const xImplSimd_DestRegEither UDQ;
|
|
|
|
// [SSE-3] PMULHRSW multiplies vertically each signed 16-bit integer from dest with the
|
|
// corresponding signed 16-bit integer of source, producing intermediate signed 32-bit
|
|
// integers. Each intermediate 32-bit integer is truncated to the 18 most significant
|
|
// bits. Rounding is always performed by adding 1 to the least significant bit of the
|
|
// 18-bit intermediate result. The final result is obtained by selecting the 16 bits
|
|
// immediately to the right of the most significant bit of each 18-bit intermediate
|
|
// result and packed to the destination operand.
|
|
//
|
|
// Both operands can be MMX or XMM registers. Source can be register or memory.
|
|
//
|
|
const xImplSimd_DestRegEither HRSW;
|
|
|
|
// [SSE-4.1] Multiply the packed dword signed integers in dest with src, and store
|
|
// the low 32 bits of each product in xmm1.
|
|
const xImplSimd_DestRegSSE LD;
|
|
|
|
// [SSE-4.1] Multiply the packed signed dword integers in dest with src.
|
|
const xImplSimd_DestRegSSE DQ;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// For instructions that have PS/SS form only (most commonly reciprocal Sqrt functions)
|
|
//
|
|
struct xImplSimd_rSqrt
|
|
{
|
|
const xImplSimd_DestRegSSE PS;
|
|
const xImplSimd_DestRegSSE SS;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// SQRT has PS/SS/SD forms, but not the PD form.
|
|
//
|
|
struct xImplSimd_Sqrt
|
|
{
|
|
const xImplSimd_DestRegSSE PS;
|
|
const xImplSimd_DestRegSSE SS;
|
|
const xImplSimd_DestRegSSE SD;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// Packed absolute value. [sSSE3 only]
|
|
//
|
|
struct xImplSimd_PAbsolute
|
|
{
|
|
// [sSSE-3] Computes the absolute value of bytes in the src, and stores the result
|
|
// in dest, as UNSIGNED.
|
|
const xImplSimd_DestRegEither B;
|
|
|
|
// [sSSE-3] Computes the absolute value of word in the src, and stores the result
|
|
// in dest, as UNSIGNED.
|
|
const xImplSimd_DestRegEither W;
|
|
|
|
// [sSSE-3] Computes the absolute value of doublewords in the src, and stores the
|
|
// result in dest, as UNSIGNED.
|
|
const xImplSimd_DestRegEither D;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// Packed Multiply and Add!!
|
|
//
|
|
struct xImplSimd_PMultAdd
|
|
{
|
|
// Multiplies the individual signed words of dest by the corresponding signed words
|
|
// of src, producing temporary signed, doubleword results. The adjacent doubleword
|
|
// results are then summed and stored in the destination operand.
|
|
//
|
|
// DEST[31:0] = ( DEST[15:0] * SRC[15:0]) + (DEST[31:16] * SRC[31:16] );
|
|
// DEST[63:32] = ( DEST[47:32] * SRC[47:32]) + (DEST[63:48] * SRC[63:48] );
|
|
// [.. repeat in the case of XMM src/dest operands ..]
|
|
//
|
|
const xImplSimd_DestRegEither WD;
|
|
|
|
// [sSSE-3] multiplies vertically each unsigned byte of dest with the corresponding
|
|
// signed byte of src, producing intermediate signed 16-bit integers. Each adjacent
|
|
// pair of signed words is added and the saturated result is packed to dest.
|
|
// For example, the lowest-order bytes (bits 7-0) in src and dest are multiplied
|
|
// and the intermediate signed word result is added with the corresponding
|
|
// intermediate result from the 2nd lowest-order bytes (bits 15-8) of the operands;
|
|
// the sign-saturated result is stored in the lowest word of dest (bits 15-0).
|
|
// The same operation is performed on the other pairs of adjacent bytes.
|
|
//
|
|
// In Coder Speak:
|
|
// DEST[15-0] = SaturateToSignedWord( SRC[15-8] * DEST[15-8] + SRC[7-0] * DEST[7-0] );
|
|
// DEST[31-16] = SaturateToSignedWord( SRC[31-24] * DEST[31-24] + SRC[23-16] * DEST[23-16] );
|
|
// [.. repeat for each 16 bits up to 64 (mmx) or 128 (xmm) ..]
|
|
//
|
|
const xImplSimd_DestRegEither UBSW;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// DotProduct calculation (SSE4.1 only!)
|
|
//
|
|
struct xImplSimd_DotProduct
|
|
{
|
|
// [SSE-4.1] Conditionally multiplies the packed single precision floating-point
|
|
// values in dest with the packed single-precision floats in src depending on a
|
|
// mask extracted from the high 4 bits of the immediate byte. If a condition mask
|
|
// bit in Imm8[7:4] is zero, the corresponding multiplication is replaced by a value
|
|
// of 0.0. The four resulting single-precision values are summed into an inter-
|
|
// mediate result.
|
|
//
|
|
// The intermediate result is conditionally broadcasted to the destination using a
|
|
// broadcast mask specified by bits [3:0] of the immediate byte. If a broadcast
|
|
// mask bit is 1, the intermediate result is copied to the corresponding dword
|
|
// element in dest. If a broadcast mask bit is zero, the corresponding element in
|
|
// the destination is set to zero.
|
|
//
|
|
xImplSimd_DestRegImmSSE PS;
|
|
|
|
// [SSE-4.1]
|
|
xImplSimd_DestRegImmSSE PD;
|
|
};
|
|
|
|
} // End namespace x86Emitter
|