|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<!--
|
|
|
|
|
Copyright (c) 2017 OpenPOWER Foundation
|
|
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
|
limitations under the License.
|
|
|
|
|
|
|
|
|
|
-->
|
|
|
|
|
<section xmlns="http://docbook.org/ns/docbook"
|
|
|
|
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
|
|
|
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
|
|
|
version="5.0"
|
|
|
|
|
xml:id="sec_handling_mmx">
|
|
|
|
|
<title>Dealing with MMX</title>
|
|
|
|
|
|
|
|
|
|
<para>MMX is actually the harder case. The <literal>__m64</literal>
|
|
|
|
|
type supports SIMD vector
|
|
|
|
|
int types (char, short, int, long). The Intel API defines
|
|
|
|
|
<literal>__m64</literal> as:
|
|
|
|
|
<programlisting><![CDATA[typedef int __m64 __attribute__ ((__vector_size__ (8), __may_alias__));]]></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>Which is problematic for the PowerPC target (not really supported in
|
|
|
|
|
GCC) and we would prefer to use a native PowerISA type that can be passed in a
|
|
|
|
|
single register. The PowerISA Rotate Under Mask instructions can easily
|
|
|
|
|
extract and insert integer fields of a General Purpose Register (GPR). This
|
|
|
|
|
implies that MMX integer types can be handled as an internal union of arrays for
|
|
|
|
|
the supported element types. So a 64-bit unsigned long long is the best type
|
|
|
|
|
for parameter passing and return values, especially for the 64-bit (_si64)
|
|
|
|
|
operations as these normally generate a single PowerISA instruction.
|
|
|
|
|
So for the PowerPC implementation we will define
|
|
|
|
|
<literal>__m64</literal> as:
|
|
|
|
|
<programlisting><![CDATA[typedef __attribute__ ((__aligned__ (8))) unsigned long long __m64;]]></programlisting></para>
|
|
|
|
|
|
|
|
|
|
<para>The SSE extensions include some copy / convert operations for
|
|
|
|
|
<literal>_m128</literal> to /
|
|
|
|
|
from <literal>_m64</literal> and this includes some int to / from float conversions. However in
|
|
|
|
|
these cases the float operands always reside in SSE (XMM) registers (which
|
|
|
|
|
match the PowerISA vector registers) and the MMX registers only contain integer
|
|
|
|
|
values. POWER8 (PowerISA-2.07) has direct move instructions between GPRs and
|
|
|
|
|
VSRs. So these transfers are normally a single instruction and any conversions
|
|
|
|
|
can be handled in the vector unit.</para>
|
|
|
|
|
|
|
|
|
|
<para>When transferring a <literal>__m64</literal> value to a vector register we should also
|
|
|
|
|
execute a xxsplatd instruction to insure there is valid data in all four
|
|
|
|
|
float element lanes before doing floating point operations. This avoids causing
|
|
|
|
|
extraneous floating point exceptions that might be generated by uninitialized
|
|
|
|
|
parts of the vector. The top two lanes will have the floating point results
|
|
|
|
|
that are in position for direct transfer to a GPR or stored via Store Float
|
|
|
|
|
Double (stfd). These operation are internal to the intrinsic implementation and
|
|
|
|
|
there is no requirement to keep temporary vectors in correct Little Endian
|
|
|
|
|
form.</para>
|
|
|
|
|
|
|
|
|
|
<para>Also for the smaller element sizes and higher element counts (MMX
|
|
|
|
|
<literal>_pi8</literal> and <literal>_p16</literal> types)
|
|
|
|
|
the number of Rotate Under Mask instructions required to
|
|
|
|
|
disassemble the 64-bit <literal>__m64</literal>
|
|
|
|
|
into elements, perform the element calculations,
|
|
|
|
|
and reassemble the elements in a single <literal>__m64</literal>
|
|
|
|
|
value can get larger. In this
|
|
|
|
|
case we can generate shorter instruction sequences by transfering (via direct
|
|
|
|
|
move instruction) the GPR <literal>__m64</literal> value to the
|
|
|
|
|
a vector register, performance the
|
|
|
|
|
SIMD operation there, then transfer the <literal>__m64</literal>
|
|
|
|
|
result back to a GPR.</para>
|
|
|
|
|
|
|
|
|
|
</section>
|
|
|
|
|
|