You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

77 lines
3.9 KiB

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

<?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
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
See the License for the specific language governing permissions and
limitations under the License.
<section xmlns=""
<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
<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>