<div dir="ltr">hello,
<span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">I have modified the patch according to your suggestio.And, <span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">when you have time,you can review the patch.
<span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">If you have any questions, you can bring them up for me.Thank you every much!</span>
</span>
</span>
</div><br><div class="gmail_quote"><div dir="ltr">刁先举 <<a href="mailto:xianjudiao@gmail.com">xianjudiao@gmail.com</a>> 于2018年9月25日周二 上午9:47写道:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div dir="ltr">I have seen your suggestion,and thank you. <br></div><div dir="ltr">1) Now,I split the optimized code into two patches,and this
patch add new functions to pixman-mmx.c. <br></div><div>2) For
loongson-mmintrin.h,
<span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">I've got rid of some redundant functions.
<span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">This is my fault. I'm very sorry!</span></span></div><div><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none"><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">3) For "-march = loongson3a",
<span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">I have asked my colleagues who are working on theloongson platform compiler. They said that there are no options like loongson* yet, but they added some new options, which have been submitted to the community, but have not been merge into the master branch, so we can wait.</span></span></span></div><div><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none"><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none"><span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">4) For
"$CFLAGS" = "-g -mabi=n64",
<span style="color:rgb(46,48,51);font-family:Arial,"Microsoft YaHei",微软雅黑,宋体,"Malgun Gothic",Meiryo,sans-serif;font-size:13px;font-style:normal;font-variant:normal;font-weight:normal;letter-spacing:normal;line-height:18px;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;background-color:rgb(255,255,255);display:inline;float:none">I don't know how to modify it best. Can you give me some advic?,thank you very much!</span>
</span>
</span>
</span>
</div></div><br><div class="gmail_quote"><div dir="ltr"><<a href="mailto:pixman-request@lists.freedesktop.org" target="_blank">pixman-request@lists.freedesktop.org</a>> 于2018年9月20日周四 上午2:56写道:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Send Pixman mailing list submissions to<br>
<a href="mailto:pixman@lists.freedesktop.org" target="_blank">pixman@lists.freedesktop.org</a><br>
<br>
To subscribe or unsubscribe via the World Wide Web, visit<br>
<a href="https://lists.freedesktop.org/mailman/listinfo/pixman" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/pixman</a><br>
or, via email, send a message with subject or body 'help' to<br>
<a href="mailto:pixman-request@lists.freedesktop.org" target="_blank">pixman-request@lists.freedesktop.org</a><br>
<br>
You can reach the person managing the list at<br>
<a href="mailto:pixman-owner@lists.freedesktop.org" target="_blank">pixman-owner@lists.freedesktop.org</a><br>
<br>
When replying, please edit your Subject line so it is more specific<br>
than "Re: Contents of Pixman digest..."<br>
<br>
<br>
Today's Topics:<br>
<br>
1. Re: [PATCH] mmx: compile on MIPS for Loongson-3A MMI<br>
optimizations (Matt Turner)<br>
<br>
<br>
----------------------------------------------------------------------<br>
<br>
Message: 1<br>
Date: Wed, 19 Sep 2018 11:56:00 -0700<br>
From: Matt Turner <<a href="mailto:mattst88@gmail.com" target="_blank">mattst88@gmail.com</a>><br>
To: <a href="mailto:xianjudiao@gmail.com" target="_blank">xianjudiao@gmail.com</a><br>
Cc: <a href="mailto:pixman@lists.freedesktop.org" target="_blank">pixman@lists.freedesktop.org</a><br>
Subject: Re: [Pixman] [PATCH] mmx: compile on MIPS for Loongson-3A MMI<br>
optimizations<br>
Message-ID:<br>
<CAEdQ38F2kr6Fo7yLkSNkO_aTM=<a href="mailto:Ycw5Xx9F6az0L%2BDHQS1fOKBw@mail.gmail.com" target="_blank">Ycw5Xx9F6az0L+DHQS1fOKBw@mail.gmail.com</a>><br>
Content-Type: text/plain; charset="UTF-8"<br>
<br>
On Tue, Sep 18, 2018 at 2:34 AM <<a href="mailto:xianjudiao@gmail.com" target="_blank">xianjudiao@gmail.com</a>> wrote:<br>
><br>
> From: Xianju Diao <<a href="mailto:xianjudiao@gmail.com" target="_blank">xianjudiao@gmail.com</a>><br>
><br>
> make check:<br>
> when I enable the USE_OPENMP, the test of 'glyph-test' and 'cover-test' will failed on Loongson-3A3000.<br>
> Neither of the two test examples passed without optimizing the code.Maybe be multi-core synchronization<br>
> of cpu bug,I will continue to debug this problem, Now, I use the critical of openMP, 'glyph-test' and '<br>
> cover-test' can passed.<br>
><br>
> benchmark:<br>
> Running cairo-perf-trace benchmark on Loongson-3A.<br>
> image image16<br>
> gvim 5.425 -> 5.069 5.531 -> 5.236<br>
> popler-reseau 2.149 -> 2.13 2.152 -> 2.139<br>
> swfdec-giant-steps-full 18.672 -> 8.215 33.167 -> 18.28<br>
> swfdec-giant-steps 7.014 -> 2.455 12.48 -> 5.982<br>
> xfce4-terminal-al 13.695 -> 5.241 15.703 -> 5.859<br>
> gonme-system-monitor 12.783 -> 7.058 12.780 -> 7.104<br>
> grads-heat-map 0.482 -> 0.486 0.516 -> 0.514<br>
> firefox-talos-svg 141.138 -> 134.621 152.495 -> 159.069<br>
> firefox-talos-gfx 23.119 -> 14.437 24.870 -> 15.161<br>
> firefox-world-map 32.018 -> 27.139 33.817 -> 28.085<br>
> firefox-periodic-table 12.305 -> 12.443 12.876 -> 12.913<br>
> evolution 7.071 -> 3.564 8.550 -> 3.784<br>
> firefox-planet-gnome 77.926 -> 67.526 81.554 -> 65.840<br>
> ocitysmap 4.934 -> 1.702 4.937 -> 1.701<br>
> ---<br>
<br>
Thanks for the patch. I will review it when I have time (I'm preparing<br>
for a trip at the moment).<br>
<br>
I have a Loongson3 system that I have found to be unstable. I assume<br>
it is due to the hardware bugs that must be worked around in gcc and<br>
binutils. I have patched both of them with the patches I found in<br>
<a href="https://github.com/loongson-community/binutils-gdb" rel="noreferrer" target="_blank">https://github.com/loongson-community/binutils-gdb</a> etc, but I still<br>
have instability. I would appreciate it very much if you could offer<br>
some suggestions or help in improving the stability of my system.<br>
<br>
Looks like there are a couple of different things happening in this<br>
patch. We should try to split them up. One patch could be making the<br>
assembly memcpy implementation usable on mips64. A separate patch<br>
would add new functions to pixman-mmx.c.<br>
<br>
A few quick comments inline.<br>
<br>
> <a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> | 7 +-<br>
> pixman/Makefile.am | 4 +-<br>
> pixman/loongson-mmintrin.h | 46 ++<br>
> pixman/pixman-combine32.h | 6 +<br>
> pixman/pixman-mips-dspr2-asm.h | 2 +-<br>
> pixman/pixman-mips-memcpy-asm.S | 324 +++++-------<br>
> pixman/pixman-mmx.c | 1088 ++++++++++++++++++++++++++++++++++++++-<br>
> pixman/pixman-private.h | 32 +-<br>
> pixman/pixman-solid-fill.c | 49 +-<br>
> pixman/pixman-utils.c | 65 ++-<br>
> test/Makefile.am | 2 +-<br>
> test/utils.c | 8 +<br>
<br>
This diff stat doesn't correspond to this patch.<br>
<br>
> 12 files changed, 1418 insertions(+), 215 deletions(-)<br>
><br>
> diff --git a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> index e833e45..3e3dde5 100644<br>
> --- a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> +++ b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
> @@ -154,9 +154,9 @@ AC_CHECK_DECL([__amd64], [AMD64_ABI="yes"], [AMD64_ABI="no"])<br>
> # has set CFLAGS.<br>
> if test $SUNCC = yes && \<br>
> test "x$test_CFLAGS" = "x" && \<br>
> - test "$CFLAGS" = "-g"<br>
> + test "$CFLAGS" = "-g -mabi=n64"<br>
> then<br>
> - CFLAGS="-O -g"<br>
> + CFLAGS="-O -g -mabi=n64"<br>
<br>
This isn't acceptable.<br>
<br>
> fi<br>
><br>
> #<br>
> @@ -183,6 +183,7 @@ AC_SUBST(LT_VERSION_INFO)<br>
> # Check for dependencies<br>
><br>
> PIXMAN_CHECK_CFLAG([-Wall])<br>
> +PIXMAN_CHECK_CFLAG([-mabi=n64])<br>
> PIXMAN_CHECK_CFLAG([-Wdeclaration-after-statement])<br>
> PIXMAN_CHECK_CFLAG([-Wno-unused-local-typedefs])<br>
> PIXMAN_CHECK_CFLAG([-fno-strict-aliasing])<br>
> @@ -273,7 +274,7 @@ dnl ===========================================================================<br>
> dnl Check for Loongson Multimedia Instructions<br>
><br>
> if test "x$LS_CFLAGS" = "x" ; then<br>
> - LS_CFLAGS="-march=loongson2f"<br>
> + LS_CFLAGS="-march=loongson3a"<br>
<br>
Also not acceptable. I see that recent gcc and binutils have gotten<br>
new options for enabling MMI separately from -march=loongson*. Maybe<br>
we could use those if available.<br>
<br>
I'm not sure there is currently a good solution. Let me think about it.<br>
<br>
> fi<br>
><br>
> have_loongson_mmi=no<br>
> diff --git a/pixman/Makefile.am b/pixman/Makefile.am<br>
> index 581b6f6..e3a080c 100644<br>
> --- a/pixman/Makefile.am<br>
> +++ b/pixman/Makefile.am<br>
> @@ -122,7 +122,7 @@ libpixman_mips_dspr2_la_SOURCES = \<br>
> pixman-mips-dspr2.h \<br>
> pixman-mips-dspr2-asm.S \<br>
> pixman-mips-dspr2-asm.h \<br>
> - pixman-mips-memcpy-asm.S<br>
> + #pixman-mips-memcpy-asm.S<br>
<br>
Can't do this.<br>
<br>
> libpixman_1_la_LIBADD += <a href="http://libpixman-mips-dspr2.la" rel="noreferrer" target="_blank">libpixman-mips-dspr2.la</a><br>
><br>
> ASM_CFLAGS_mips_dspr2=<br>
> @@ -131,7 +131,7 @@ endif<br>
> # loongson code<br>
> if USE_LOONGSON_MMI<br>
> noinst_LTLIBRARIES += <a href="http://libpixman-loongson-mmi.la" rel="noreferrer" target="_blank">libpixman-loongson-mmi.la</a><br>
> -libpixman_loongson_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h<br>
> +libpixman_loongson_mmi_la_SOURCES = pixman-mmx.c loongson-mmintrin.h pixman-mips-memcpy-asm.S<br>
> libpixman_loongson_mmi_la_CFLAGS = $(LS_CFLAGS)<br>
> libpixman_1_la_LDFLAGS += $(LS_LDFLAGS)<br>
> libpixman_1_la_LIBADD += <a href="http://libpixman-loongson-mmi.la" rel="noreferrer" target="_blank">libpixman-loongson-mmi.la</a><br>
> diff --git a/pixman/loongson-mmintrin.h b/pixman/loongson-mmintrin.h<br>
> index 086c6e0..f049463 100644<br>
> --- a/pixman/loongson-mmintrin.h<br>
> +++ b/pixman/loongson-mmintrin.h<br>
> @@ -89,6 +89,17 @@ _mm_adds_pu8 (__m64 __m1, __m64 __m2)<br>
> }<br>
><br>
> extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> +_mm_andn_si64 (__m64 __m1, __m64 __m2)<br>
<br>
Doesn't seem to be used.<br>
<br>
> +{<br>
> + __m64 ret;<br>
> + asm("pandn %0, %1, %2\n\t"<br>
> + : "=f" (ret)<br>
> + : "f" (__m1), "f"(__m2)<br>
> + );<br>
> + return ret;<br>
> +}<br>
> +<br>
> +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> _mm_and_si64 (__m64 __m1, __m64 __m2)<br>
> {<br>
> __m64 ret;<br>
> @@ -100,6 +111,17 @@ _mm_and_si64 (__m64 __m1, __m64 __m2)<br>
> }<br>
><br>
> extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> +_mm_cmpeq_pi16 (__m64 __m1, __m64 __m2)<br>
<br>
Doesn't seem to be used.<br>
<br>
> +{<br>
> + __m64 ret;<br>
<br>
Whitespace mistake.<br>
<br>
> + asm("pcmpeqh %0, %1, %2\n\t"<br>
> + : "=f" (ret)<br>
> + : "f" (__m1), "f" (__m2)<br>
> + );<br>
> + return ret;<br>
> +}<br>
> +<br>
> +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> _mm_cmpeq_pi32 (__m64 __m1, __m64 __m2)<br>
> {<br>
> __m64 ret;<br>
> @@ -110,6 +132,30 @@ _mm_cmpeq_pi32 (__m64 __m1, __m64 __m2)<br>
> return ret;<br>
> }<br>
><br>
> +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> +loongson_fand (__m64 __m1, __m64 __m2)<br>
<br>
Doesn't seem to be used.<br>
<br>
> +{<br>
> + __m64 ret;<br>
> + asm("fand %0, %1, %2\n\t"<br>
> + : "=f" (ret)<br>
> + : "f" (__m1), "f" (__m2)<br>
> + );<br>
> + return ret;<br>
> +}<br>
> +<br>
> +<br>
> +extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> +_mm_cmpgt_pi16 (__m64 __m1, __m64 __m2)<br>
> +{<br>
> + __m64 ret;<br>
> + asm("pcmpgth %0, %1, %2\n\t"<br>
> + : "=f" (ret)<br>
> + : "f" (__m1), "f" (__m2)<br>
> + );<br>
> + return ret;<br>
> +}<br>
> +<br>
> +<br>
> extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> _mm_empty (void)<br>
> {<br>
> diff --git a/pixman/pixman-combine32.h b/pixman/pixman-combine32.h<br>
> index cdd56a6..27f62d9 100644<br>
> --- a/pixman/pixman-combine32.h<br>
> +++ b/pixman/pixman-combine32.h<br>
> @@ -14,6 +14,12 @@<br>
> #define RB_ONE_HALF 0x800080<br>
> #define RB_MASK_PLUS_ONE 0x10000100<br>
><br>
> +#define RGB_MASK 0xffffff<br>
> +#define RGB_DMASK 0xffffffffffffULL<br>
> +#define R_DMASK 0x0000ffff00000000ULL<br>
> +#define G_DMASK 0x00000000ffff0000ULL<br>
> +#define B_DMASK 0x000000000000ffffULL<br>
> +<br>
> #define ALPHA_8(x) ((x) >> A_SHIFT)<br>
> #define RED_8(x) (((x) >> R_SHIFT) & MASK)<br>
> #define GREEN_8(x) (((x) >> G_SHIFT) & MASK)<br>
> diff --git a/pixman/pixman-mips-dspr2-asm.h b/pixman/pixman-mips-dspr2-asm.h<br>
> index e238566..63d7d96 100644<br>
> --- a/pixman/pixman-mips-dspr2-asm.h<br>
> +++ b/pixman/pixman-mips-dspr2-asm.h<br>
> @@ -77,7 +77,7 @@<br>
> .ent symbol, 0; \<br>
> symbol: .frame sp, 0, ra; \<br>
> .set push; \<br>
> - .set arch=mips32r2; \<br>
> + .set arch=mips64r2; \<br>
<br>
Can't do this.<br>
<br>
> .set noreorder; \<br>
> .set noat;<br>
><br>
> diff --git a/pixman/pixman-mips-memcpy-asm.S b/pixman/pixman-mips-memcpy-asm.S<br>
> index 9ad6da5..a140191 100644<br>
> --- a/pixman/pixman-mips-memcpy-asm.S<br>
> +++ b/pixman/pixman-mips-memcpy-asm.S<br>
> @@ -54,19 +54,20 @@ LEAF_MIPS32R2(pixman_mips_fast_memcpy)<br>
><br>
> /* Test if the src and dst are word-aligned, or can be made word-aligned */<br>
> xor t8, a1, a0<br>
> - andi t8, t8, 0x3 /* t8 is a0/a1 word-displacement */<br>
> + andi t8, t8, 0x7 /* t8 is a0/a1 word-displacement */<br>
><br>
> bne t8, zero, $unaligned<br>
> negu a3, a0<br>
><br>
> - andi a3, a3, 0x3 /* we need to copy a3 bytes to make a0/a1 aligned */<br>
> + andi a3, a3, 0x7 /* we need to copy a3 bytes to make a0/a1 aligned */<br>
> beq a3, zero, $chk16w /* when a3=0 then the dst (a0) is word-aligned */<br>
> subu a2, a2, a3 /* now a2 is the remining bytes count */<br>
><br>
> - LWHI t8, 0(a1)<br>
> - addu a1, a1, a3<br>
> - SWHI t8, 0(a0)<br>
> - addu a0, a0, a3<br>
> + ld t8, 0(a1)<br>
> + daddu a1, a1, a3<br>
> + sdl t8, 7(a0)<br>
> + sdr t8, 0(a0)<br>
> + daddu a0, a0, a3<br>
><br>
> /* Now the dst/src are mutually word-aligned with word-aligned addresses */<br>
> $chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */<br>
> @@ -76,9 +77,9 @@ $chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */<br>
> /* There will be at most 1 32-byte chunk after it */<br>
> subu a3, a2, t8 /* subtract from a2 the reminder */<br>
> /* Here a3 counts bytes in 16w chunks */<br>
> - addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */<br>
> + daddu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */<br>
><br>
> - addu t0, a0, a2 /* t0 is the "past the end" address */<br>
> + daddu t0, a0, a2 /* t0 is the "past the end" address */<br>
><br>
> /*<br>
> * When in the loop we exercise "pref 30, x(a0)", the a0+x should not be past<br>
> @@ -89,119 +90,98 @@ $chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */<br>
> */<br>
> subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */<br>
><br>
> - pref 0, 0(a1) /* bring the first line of src, addr 0 */<br>
> - pref 0, 32(a1) /* bring the second line of src, addr 32 */<br>
> - pref 0, 64(a1) /* bring the third line of src, addr 64 */<br>
> - pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */<br>
> + lw $0, 0(a1) /* bring the first line of src, addr 0 */<br>
> + lw $0, 32(a1) /* bring the second line of src, addr 32 */<br>
> + lw $0, 64(a1) /* bring the third line of src, addr 64 */<br>
> + lw $0, 32(a0) /* safe, as we have at least 64 bytes ahead */<br>
> /* In case the a0 > t9 don't use "pref 30" at all */<br>
> sgtu v1, a0, t9<br>
> bgtz v1, $loop16w /* skip "pref 30, 64(a0)" for too short arrays */<br>
> nop<br>
> /* otherwise, start with using pref30 */<br>
> - pref 30, 64(a0)<br>
> + lw $0, 64(a0)<br>
> $loop16w:<br>
> - pref 0, 96(a1)<br>
> - lw t0, 0(a1)<br>
> + lw $0, 96(a1)<br>
> + ld t0, 0(a1)<br>
> bgtz v1, $skip_pref30_96 /* skip "pref 30, 96(a0)" */<br>
> - lw t1, 4(a1)<br>
> - pref 30, 96(a0) /* continue setting up the dest, addr 96 */<br>
> + lw $0, 96(a0) /* continue setting up the dest, addr 96 */<br>
> $skip_pref30_96:<br>
> - lw t2, 8(a1)<br>
> - lw t3, 12(a1)<br>
> - lw t4, 16(a1)<br>
> - lw t5, 20(a1)<br>
> - lw t6, 24(a1)<br>
> - lw t7, 28(a1)<br>
> - pref 0, 128(a1) /* bring the next lines of src, addr 128 */<br>
> -<br>
> - sw t0, 0(a0)<br>
> - sw t1, 4(a0)<br>
> - sw t2, 8(a0)<br>
> - sw t3, 12(a0)<br>
> - sw t4, 16(a0)<br>
> - sw t5, 20(a0)<br>
> - sw t6, 24(a0)<br>
> - sw t7, 28(a0)<br>
> -<br>
> - lw t0, 32(a1)<br>
> + ld t2, 8(a1)<br>
> + ld t4, 16(a1)<br>
> + ld t6, 24(a1)<br>
> + lw $0, 128(a1) /* bring the next lines of src, addr 128 */<br>
> + lw $0, 0x0(a0)<br>
> +<br>
> + sd t0, 0(a0)<br>
> + sd t2, 8(a0)<br>
> + sd t4, 16(a0)<br>
> + sd t6, 24(a0)<br>
> +<br>
> + ld t0, 32(a1)<br>
> bgtz v1, $skip_pref30_128 /* skip "pref 30, 128(a0)" */<br>
> - lw t1, 36(a1)<br>
> - pref 30, 128(a0) /* continue setting up the dest, addr 128 */<br>
> + lw $0, 128(a0) /* continue setting up the dest, addr 128 */<br>
> $skip_pref30_128:<br>
> - lw t2, 40(a1)<br>
> - lw t3, 44(a1)<br>
> - lw t4, 48(a1)<br>
> - lw t5, 52(a1)<br>
> - lw t6, 56(a1)<br>
> - lw t7, 60(a1)<br>
> - pref 0, 160(a1) /* bring the next lines of src, addr 160 */<br>
> -<br>
> - sw t0, 32(a0)<br>
> - sw t1, 36(a0)<br>
> - sw t2, 40(a0)<br>
> - sw t3, 44(a0)<br>
> - sw t4, 48(a0)<br>
> - sw t5, 52(a0)<br>
> - sw t6, 56(a0)<br>
> - sw t7, 60(a0)<br>
> -<br>
> - addiu a0, a0, 64 /* adding 64 to dest */<br>
> + ld t2, 40(a1)<br>
> + ld t4, 48(a1)<br>
> + ld t6, 56(a1)<br>
> + lw $0, 160(a1) /* bring the next lines of src, addr 160 */<br>
> + lw $0, 0x32(a0)<br>
> +<br>
> + sd t0, 32(a0)<br>
> + sd t2, 40(a0)<br>
> + sd t4, 48(a0)<br>
> + sd t6, 56(a0)<br>
> +<br>
> + daddiu a0, a0, 64 /* adding 64 to dest */<br>
> sgtu v1, a0, t9<br>
> bne a0, a3, $loop16w<br>
> - addiu a1, a1, 64 /* adding 64 to src */<br>
> + daddiu a1, a1, 64 /* adding 64 to src */<br>
> move a2, t8<br>
><br>
> /* Here we have src and dest word-aligned but less than 64-bytes to go */<br>
><br>
> $chk8w:<br>
> - pref 0, 0x0(a1)<br>
> + lw $0, 0x0(a1)<br>
> andi t8, a2, 0x1f /* is there a 32-byte chunk? */<br>
> /* the t8 is the reminder count past 32-bytes */<br>
> beq a2, t8, $chk1w /* when a2=t8, no 32-byte chunk */<br>
> nop<br>
><br>
> - lw t0, 0(a1)<br>
> - lw t1, 4(a1)<br>
> - lw t2, 8(a1)<br>
> - lw t3, 12(a1)<br>
> - lw t4, 16(a1)<br>
> - lw t5, 20(a1)<br>
> - lw t6, 24(a1)<br>
> - lw t7, 28(a1)<br>
> - addiu a1, a1, 32<br>
> -<br>
> - sw t0, 0(a0)<br>
> - sw t1, 4(a0)<br>
> - sw t2, 8(a0)<br>
> - sw t3, 12(a0)<br>
> - sw t4, 16(a0)<br>
> - sw t5, 20(a0)<br>
> - sw t6, 24(a0)<br>
> - sw t7, 28(a0)<br>
> - addiu a0, a0, 32<br>
> + ld t0, 0(a1)<br>
> + ld t2, 8(a1)<br>
> + ld t4, 16(a1)<br>
> + ld t6, 24(a1)<br>
> + lw $0, 0x0(a0)<br>
> + daddiu a1, a1, 32<br>
> +<br>
> + sd t0, 0(a0)<br>
> + sd t2, 8(a0)<br>
> + sd t4, 16(a0)<br>
> + sd t6, 24(a0)<br>
> + daddiu a0, a0, 32<br>
><br>
> $chk1w:<br>
> andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */<br>
> beq a2, t8, $last8<br>
> subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */<br>
> - addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */<br>
> + daddu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */<br>
><br>
> /* copying in words (4-byte chunks) */<br>
> $wordCopy_loop:<br>
> lw t3, 0(a1) /* the first t3 may be equal t0 ... optimize? */<br>
> - addiu a1, a1, 4<br>
> - addiu a0, a0, 4<br>
> + daddiu a1, a1, 4<br>
> + daddiu a0, a0, 4<br>
> bne a0, a3, $wordCopy_loop<br>
> sw t3, -4(a0)<br>
><br>
> /* For the last (<8) bytes */<br>
> $last8:<br>
> blez a2, leave<br>
> - addu a3, a0, a2 /* a3 is the last dst address */<br>
> + daddu a3, a0, a2 /* a3 is the last dst address */<br>
> $last8loop:<br>
> lb v1, 0(a1)<br>
> - addiu a1, a1, 1<br>
> - addiu a0, a0, 1<br>
> + daddiu a1, a1, 1<br>
> + daddiu a0, a0, 1<br>
> bne a0, a3, $last8loop<br>
> sb v1, -1(a0)<br>
><br>
> @@ -214,15 +194,16 @@ leave: j ra<br>
><br>
> $unaligned:<br>
> /* got here with a3="negu a0" */<br>
> - andi a3, a3, 0x3 /* test if the a0 is word aligned */<br>
> + andi a3, a3, 0x7 /* test if the a0 is word aligned */<br>
> beqz a3, $ua_chk16w<br>
> subu a2, a2, a3 /* bytes left after initial a3 bytes */<br>
><br>
> - LWHI v1, 0(a1)<br>
> - LWLO v1, 3(a1)<br>
> - addu a1, a1, a3 /* a3 may be here 1, 2 or 3 */<br>
> - SWHI v1, 0(a0)<br>
> - addu a0, a0, a3 /* below the dst will be word aligned (NOTE1) */<br>
> + ldl v1, 7(a1)<br>
> + ldr v1, 0(a1)<br>
> + daddu a1, a1, a3 /* a3 may be here 1, 2 or 3 */<br>
> + sdl v1, 7(a0)<br>
> + sdr v1, 0(a0)<br>
> + daddu a0, a0, a3 /* below the dst will be word aligned (NOTE1) */<br>
><br>
> $ua_chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */<br>
> /* t8 is the byte count after 64-byte chunks */<br>
> @@ -230,149 +211,116 @@ $ua_chk16w: andi t8, a2, 0x3f /* any whole 64-byte chunks? */<br>
> /* There will be at most 1 32-byte chunk after it */<br>
> subu a3, a2, t8 /* subtract from a2 the reminder */<br>
> /* Here a3 counts bytes in 16w chunks */<br>
> - addu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */<br>
> + daddu a3, a0, a3 /* Now a3 is the final dst after 64-byte chunks */<br>
><br>
> - addu t0, a0, a2 /* t0 is the "past the end" address */<br>
> + daddu t0, a0, a2 /* t0 is the "past the end" address */<br>
><br>
> subu t9, t0, 160 /* t9 is the "last safe pref 30, 128(a0)" address */<br>
><br>
> - pref 0, 0(a1) /* bring the first line of src, addr 0 */<br>
> - pref 0, 32(a1) /* bring the second line of src, addr 32 */<br>
> - pref 0, 64(a1) /* bring the third line of src, addr 64 */<br>
> - pref 30, 32(a0) /* safe, as we have at least 64 bytes ahead */<br>
> + lw $0, 0(a1) /* bring the first line of src, addr 0 */<br>
> + lw $0, 32(a1) /* bring the second line of src, addr 32 */<br>
> + lw $0, 64(a1) /* bring the third line of src, addr 64 */<br>
> + lw $0, 32(a0) /* safe, as we have at least 64 bytes ahead */<br>
> /* In case the a0 > t9 don't use "pref 30" at all */<br>
> sgtu v1, a0, t9<br>
> bgtz v1, $ua_loop16w /* skip "pref 30, 64(a0)" for too short arrays */<br>
> nop<br>
> /* otherwise, start with using pref30 */<br>
> - pref 30, 64(a0)<br>
> + lw $0, 64(a0)<br>
> $ua_loop16w:<br>
> - pref 0, 96(a1)<br>
> - LWHI t0, 0(a1)<br>
> - LWLO t0, 3(a1)<br>
> - LWHI t1, 4(a1)<br>
> + lw $0, 96(a1)<br>
> + ldl t0, 7(a1)<br>
> + ldr t0, 0(a1)<br>
> bgtz v1, $ua_skip_pref30_96<br>
> - LWLO t1, 7(a1)<br>
> - pref 30, 96(a0) /* continue setting up the dest, addr 96 */<br>
> + lw $0, 96(a0) /* continue setting up the dest, addr 96 */<br>
> $ua_skip_pref30_96:<br>
> - LWHI t2, 8(a1)<br>
> - LWLO t2, 11(a1)<br>
> - LWHI t3, 12(a1)<br>
> - LWLO t3, 15(a1)<br>
> - LWHI t4, 16(a1)<br>
> - LWLO t4, 19(a1)<br>
> - LWHI t5, 20(a1)<br>
> - LWLO t5, 23(a1)<br>
> - LWHI t6, 24(a1)<br>
> - LWLO t6, 27(a1)<br>
> - LWHI t7, 28(a1)<br>
> - LWLO t7, 31(a1)<br>
> - pref 0, 128(a1) /* bring the next lines of src, addr 128 */<br>
> -<br>
> - sw t0, 0(a0)<br>
> - sw t1, 4(a0)<br>
> - sw t2, 8(a0)<br>
> - sw t3, 12(a0)<br>
> - sw t4, 16(a0)<br>
> - sw t5, 20(a0)<br>
> - sw t6, 24(a0)<br>
> - sw t7, 28(a0)<br>
> -<br>
> - LWHI t0, 32(a1)<br>
> - LWLO t0, 35(a1)<br>
> - LWHI t1, 36(a1)<br>
> + ldl t2, 15(a1)<br>
> + ldr t2, 8(a1)<br>
> + ldl t4, 23(a1)<br>
> + ldr t4, 16(a1)<br>
> + ldl t6, 31(a1)<br>
> + ldr t6, 24(a1)<br>
> + lw $0, 128(a1) /* bring the next lines of src, addr 128 */<br>
> + lw $0, 0(a0)<br>
> +<br>
> + sd t0, 0(a0)<br>
> + sd t2, 8(a0)<br>
> + sd t4, 16(a0)<br>
> + sd t6, 24(a0)<br>
> +<br>
> + ldl t0, 39(a1)<br>
> + ldr t0, 32(a1)<br>
> bgtz v1, $ua_skip_pref30_128<br>
> - LWLO t1, 39(a1)<br>
> - pref 30, 128(a0) /* continue setting up the dest, addr 128 */<br>
> + lw $0, 128(a0) /* continue setting up the dest, addr 128 */<br>
> $ua_skip_pref30_128:<br>
> - LWHI t2, 40(a1)<br>
> - LWLO t2, 43(a1)<br>
> - LWHI t3, 44(a1)<br>
> - LWLO t3, 47(a1)<br>
> - LWHI t4, 48(a1)<br>
> - LWLO t4, 51(a1)<br>
> - LWHI t5, 52(a1)<br>
> - LWLO t5, 55(a1)<br>
> - LWHI t6, 56(a1)<br>
> - LWLO t6, 59(a1)<br>
> - LWHI t7, 60(a1)<br>
> - LWLO t7, 63(a1)<br>
> - pref 0, 160(a1) /* bring the next lines of src, addr 160 */<br>
> -<br>
> - sw t0, 32(a0)<br>
> - sw t1, 36(a0)<br>
> - sw t2, 40(a0)<br>
> - sw t3, 44(a0)<br>
> - sw t4, 48(a0)<br>
> - sw t5, 52(a0)<br>
> - sw t6, 56(a0)<br>
> - sw t7, 60(a0)<br>
> -<br>
> - addiu a0, a0, 64 /* adding 64 to dest */<br>
> + ldl t2, 47(a1)<br>
> + ldr t2, 40(a1)<br>
> + ldl t4, 55(a1)<br>
> + ldr t4, 48(a1)<br>
> + ldl t6, 63(a1)<br>
> + ldr t6, 56(a1)<br>
> + lw $0, 32(a0)<br>
> + lw $0, 160(a1) /* bring the next lines of src, addr 160 */<br>
> +<br>
> + sd t0, 32(a0)<br>
> + sd t2, 40(a0)<br>
> + sd t4, 48(a0)<br>
> + sd t6, 56(a0)<br>
> +<br>
> + daddiu a0, a0, 64 /* adding 64 to dest */<br>
> sgtu v1, a0, t9<br>
> bne a0, a3, $ua_loop16w<br>
> - addiu a1, a1, 64 /* adding 64 to src */<br>
> + daddiu a1, a1, 64 /* adding 64 to src */<br>
> move a2, t8<br>
><br>
> /* Here we have src and dest word-aligned but less than 64-bytes to go */<br>
><br>
> $ua_chk8w:<br>
> - pref 0, 0x0(a1)<br>
> + lw $0, 0x0(a1)<br>
> andi t8, a2, 0x1f /* is there a 32-byte chunk? */<br>
> /* the t8 is the reminder count */<br>
> beq a2, t8, $ua_chk1w /* when a2=t8, no 32-byte chunk */<br>
><br>
> - LWHI t0, 0(a1)<br>
> - LWLO t0, 3(a1)<br>
> - LWHI t1, 4(a1)<br>
> - LWLO t1, 7(a1)<br>
> - LWHI t2, 8(a1)<br>
> - LWLO t2, 11(a1)<br>
> - LWHI t3, 12(a1)<br>
> - LWLO t3, 15(a1)<br>
> - LWHI t4, 16(a1)<br>
> - LWLO t4, 19(a1)<br>
> - LWHI t5, 20(a1)<br>
> - LWLO t5, 23(a1)<br>
> - LWHI t6, 24(a1)<br>
> - LWLO t6, 27(a1)<br>
> - LWHI t7, 28(a1)<br>
> - LWLO t7, 31(a1)<br>
> - addiu a1, a1, 32<br>
> -<br>
> - sw t0, 0(a0)<br>
> - sw t1, 4(a0)<br>
> - sw t2, 8(a0)<br>
> - sw t3, 12(a0)<br>
> - sw t4, 16(a0)<br>
> - sw t5, 20(a0)<br>
> - sw t6, 24(a0)<br>
> - sw t7, 28(a0)<br>
> - addiu a0, a0, 32<br>
> + ldl t0, 7(a1)<br>
> + ldr t0, 0(a1)<br>
> + ldl t2, 15(a1)<br>
> + ldr t2, 8(a1)<br>
> + ldl t4, 23(a1)<br>
> + ldr t4, 16(a1)<br>
> + ldl t6, 31(a1)<br>
> + ldr t6, 24(a1)<br>
> + lw $0, 0x0(a0)<br>
> + daddiu a1, a1, 32<br>
> +<br>
> + sd t0, 0(a0)<br>
> + sd t2, 8(a0)<br>
> + sd t4, 16(a0)<br>
> + sd t6, 24(a0)<br>
> + daddiu a0, a0, 32<br>
><br>
> $ua_chk1w:<br>
> andi a2, t8, 0x3 /* now a2 is the reminder past 1w chunks */<br>
> beq a2, t8, $ua_smallCopy<br>
> subu a3, t8, a2 /* a3 is count of bytes in 1w chunks */<br>
> - addu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */<br>
> + daddu a3, a0, a3 /* now a3 is the dst address past the 1w chunks */<br>
><br>
> /* copying in words (4-byte chunks) */<br>
> $ua_wordCopy_loop:<br>
> LWHI v1, 0(a1)<br>
> LWLO v1, 3(a1)<br>
> - addiu a1, a1, 4<br>
> - addiu a0, a0, 4 /* note: dst=a0 is word aligned here, see NOTE1 */<br>
> + daddiu a1, a1, 4<br>
> + daddiu a0, a0, 4 /* note: dst=a0 is word aligned here, see NOTE1 */<br>
> bne a0, a3, $ua_wordCopy_loop<br>
> sw v1, -4(a0)<br>
><br>
> /* Now less than 4 bytes (value in a2) left to copy */<br>
> $ua_smallCopy:<br>
> beqz a2, leave<br>
> - addu a3, a0, a2 /* a3 is the last dst address */<br>
> + daddu a3, a0, a2 /* a3 is the last dst address */<br>
> $ua_smallCopy_loop:<br>
> lb v1, 0(a1)<br>
> - addiu a1, a1, 1<br>
> - addiu a0, a0, 1<br>
> + daddiu a1, a1, 1<br>
> + daddiu a0, a0, 1<br>
> bne a0, a3, $ua_smallCopy_loop<br>
> sb v1, -1(a0)<br>
><br>
> diff --git a/pixman/pixman-mmx.c b/pixman/pixman-mmx.c<br>
> index dec3974..edbf16b 100644<br>
> --- a/pixman/pixman-mmx.c<br>
> +++ b/pixman/pixman-mmx.c<br>
> @@ -59,6 +59,71 @@ _mm_empty (void)<br>
> }<br>
> #endif<br>
><br>
> +#define COMBINE_A_OUT 1<br>
> +#define COMBINE_A_IN 2<br>
> +#define COMBINE_B_OUT 4<br>
> +#define COMBINE_B_IN 8<br>
> +<br>
> +#define COMBINE_CLEAR 0<br>
> +#define COMBINE_A (COMBINE_A_OUT | COMBINE_A_IN)<br>
> +#define COMBINE_B (COMBINE_B_OUT | COMBINE_B_IN)<br>
> +#define COMBINE_A_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN)<br>
> +#define COMBINE_B_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN)<br>
> +#define COMBINE_A_ATOP (COMBINE_B_OUT | COMBINE_A_IN)<br>
> +#define COMBINE_B_ATOP (COMBINE_A_OUT | COMBINE_B_IN)<br>
> +#define COMBINE_XOR (COMBINE_A_OUT | COMBINE_B_OUT)<br>
> +<br>
> +/* no SIMD instructions for div, so leave it alone<br>
> + * portion covered by a but not b<br>
> + * min (1, (1-b) / a)<br>
> + */<br>
> +static uint8_t<br>
> +combine_disjoint_out_part (uint8_t a, uint8_t b)<br>
> +{<br>
> +<br>
> + b = ~b;<br>
> + if (b >= a)<br>
> + return MASK;<br>
> + return DIV_UN8 (b, a);<br>
> +}<br>
> +<br>
> +/* portion covered by both a and b<br>
> + * max (1-(1-b)/a, 0)<br>
> + */<br>
> +static uint8_t<br>
> +combine_disjoint_in_part (uint8_t a, uint8_t b)<br>
> +{<br>
> +<br>
> + b = ~b;<br>
> + if (b >= a)<br>
> + return 0;<br>
> + return ~DIV_UN8(b, a);<br>
> +}<br>
> +<br>
> +/* portion covered by a but not b<br>
> + * max (1-b/a ,0)<br>
> + * */<br>
> +static uint8_t<br>
> +combine_conjoint_out_part (uint8_t a, uint8_t b)<br>
> +{<br>
> +<br>
> + if (b >= a)<br>
> + return 0x00;<br>
> + return ~DIV_UN8(b, a);<br>
> +}<br>
> +<br>
> +/* portion covered by both a and b<br>
> + * min (1, b/a)<br>
> + */<br>
> +static uint8_t<br>
> +combine_conjoint_in_part (uint8_t a, uint8_t b)<br>
> +{<br>
> +<br>
> + if (b >= a)<br>
> + return MASK;<br>
> + return DIV_UN8 (b, a);<br>
> +}<br>
> +<br>
> #ifdef USE_X86_MMX<br>
> # if (defined(__SUNPRO_C) || defined(_MSC_VER) || defined(_WIN64))<br>
> # include <xmmintrin.h><br>
> @@ -78,7 +143,8 @@ _mm_movemask_pi8 (__m64 __A)<br>
><br>
> return ret;<br>
> }<br>
> -<br>
> +#define __OPTIMIZE__<br>
> +#ifdef __OPTIMIZE__<br>
> extern __inline __m64 __attribute__((__gnu_inline__, __always_inline__, __artificial__))<br>
> _mm_mulhi_pu16 (__m64 __A, __m64 __B)<br>
> {<br>
> @@ -88,7 +154,7 @@ _mm_mulhi_pu16 (__m64 __A, __m64 __B)<br>
> );<br>
> return __A;<br>
> }<br>
> -<br>
> +#else<br>
> # define _mm_shuffle_pi16(A, N) \<br>
> ({ \<br>
> __m64 ret; \<br>
> @@ -102,7 +168,7 @@ _mm_mulhi_pu16 (__m64 __A, __m64 __B)<br>
> })<br>
> # endif<br>
> #endif<br>
> -<br>
> +#endif<br>
> #ifndef _MSC_VER<br>
> #define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \<br>
> (((fp3) << 6) | ((fp2) << 4) | ((fp1) << 2) | (fp0))<br>
> @@ -710,6 +776,34 @@ combine (const uint32_t *src, const uint32_t *mask)<br>
> return vsrc;<br>
> }<br>
><br>
> +static force_inline void<br>
> +mmx_combine_mask_ca(const uint32_t *src, const uint32_t *mask, __m64 *s64, __m64 *m64)<br>
> +{<br>
> + __m64 res, tmp;<br>
> +<br>
> + if(!(*mask))<br>
> + {<br>
> + *s64 = 0;<br>
> + *m64 = 0;<br>
> + return;<br>
> + }<br>
> +<br>
> + *s64 = load8888(src);<br>
> +<br>
> + if (*mask == ~0)<br>
> + {<br>
> + *m64 = expand_alpha(*s64);<br>
> + return;<br>
> + }<br>
> +<br>
> + *m64 = load8888(mask);<br>
> +<br>
> + res = pix_multiply(*s64, *m64);<br>
> + tmp = expand_alpha(*s64);<br>
> + *s64 = res;<br>
> + *m64 = pix_multiply(*m64, tmp);<br>
> +}<br>
> +<br>
> static force_inline __m64<br>
> core_combine_over_u_pixel_mmx (__m64 vsrc, __m64 vdst)<br>
> {<br>
> @@ -729,6 +823,39 @@ core_combine_over_u_pixel_mmx (__m64 vsrc, __m64 vdst)<br>
> }<br>
><br>
> static void<br>
> +mmx_combine_disjoint_over_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + uint32_t *end = dest + width;<br>
> + uint32_t s32;<br>
> + uint64_t sa64;<br>
> + __m64 s64, d64;<br>
> +<br>
> + while (dest < end)<br>
> + {<br>
> + s64 = combine (src, mask);<br>
> +<br>
> + if (s64)<br>
> + {<br>
> + store8888(&s32, s64);<br>
> + sa64 = combine_disjoint_out_part (*dest >> A_SHIFT, s32 >> A_SHIFT);<br>
> + d64 = pix_add (pix_multiply (load8888 (dest),expand_alpha_rev ((*(__m64*)&sa64))), s64);<br>
> + store8888 (dest, d64);<br>
> + }<br>
> +<br>
> + ++dest;<br>
> + ++src;<br>
> + if (mask)<br>
> + ++mask;<br>
> +<br>
> + }<br>
> +}<br>
> +<br>
> +static void<br>
> mmx_combine_over_u (pixman_implementation_t *imp,<br>
> pixman_op_t op,<br>
> uint32_t * dest,<br>
> @@ -1062,7 +1189,294 @@ mmx_combine_saturate_u (pixman_implementation_t *imp,<br>
> }<br>
> _mm_empty ();<br>
> }<br>
> +/* In functions such as ‘combine_conjoint_gerneral_u’, there are multiple branchs,determined by the parameter 'combine'.<br>
> + * and this value will not change during functions operations,so it is not necessary to judge each value in the origin<br>
> + * code. Can be judged at function entrance,and set the corresponding function pointer,can be called directly later.<br>
> + */<br>
> +#define DEF_FUNC_ZERO_MASK(type, zm, suffix, res) \<br>
> + static type inline combine_joint_ ##zm## _ ##suffix( type sa, type da, type io_flag) \<br>
> + { \<br>
> + return res; \<br>
> + }<br>
> +<br>
> +/* 'conjoint' is same code structure as 'disjoint',the funtion name is different,set this macro to generate the corresponding<br>
> + * function.The order of parameter is different,which is determined by 'io_flag',with '0' for 'in_part' and '1' for 'out_part'.<br>
> + */<br>
> +#define DEF_FUNC_COMBINE_JOINT_U(cd, io) \<br>
> + static uint8_t inline combine_ ##cd## joint_ ##io## _part_u(uint8_t sa, uint8_t da, uint8_t io_flag) \<br>
> + { \<br>
> + uint8_t parm[2]; \<br>
> + parm[0] = sa * (io_flag ^ 0x1) + da * (io_flag ^ 0x0); \<br>
> + parm[1] = sa * (io_flag ^ 0x0) + da * (io_flag ^ 0x1); \<br>
> + return combine_ ##cd## joint_ ##io## _part (parm[0], parm[1]); \<br>
> + }<br>
> +/* Sets the macro for the array of function pointers, storing the correct handler at the function entrance */<br>
> +#define DEF_COMB_FUNC_ARR(cd,SUFFIX,suffix) \<br>
> + COMBINE_JOINT_FUNC_##SUFFIX combine_ ##cd## joint_ ##suffix[4] ={ \<br>
> + combine_joint_zero_ ##suffix, \<br>
> + combine_ ##cd## joint_out_part_ ##suffix, \<br>
> + combine_ ##cd## joint_in_part_ ##suffix, \<br>
> + combine_joint_mask_ ##suffix \<br>
> + };<br>
> +<br>
> +typedef uint8_t (*COMBINE_JOINT_FUNC_U)(uint8_t a, uint8_t b, uint8_t io_flag);<br>
> +<br>
> +DEF_FUNC_ZERO_MASK(uint8_t,zero,u, 0x0)<br>
> +DEF_FUNC_ZERO_MASK(uint8_t,mask,u, ~0x0)<br>
> +<br>
> +DEF_FUNC_COMBINE_JOINT_U(dis, in);<br>
> +DEF_FUNC_COMBINE_JOINT_U(dis, out);<br>
> +DEF_COMB_FUNC_ARR(dis,U,u)<br>
> +<br>
> +DEF_FUNC_COMBINE_JOINT_U(con, in);<br>
> +DEF_FUNC_COMBINE_JOINT_U(con, out);<br>
> +DEF_COMB_FUNC_ARR(con, U, u)<br>
> +/* Set an underlying function,'conjoint' and 'disjoint' related functions can be called. */<br>
> +static void<br>
> +mmx_combine_joint_general_u (uint32_t * dest,<br>
> + const uint32_t *src,<br>
> + const uint32_t *mask,<br>
> + int width,<br>
> + uint8_t comb,<br>
> + COMBINE_JOINT_FUNC_U *cjf)<br>
> +{<br>
> + COMBINE_JOINT_FUNC_U combine_joint_u[2];<br>
> + combine_joint_u[0] = cjf[comb & COMBINE_A]; /* in_part */<br>
> + combine_joint_u[1] = cjf[(comb & COMBINE_B)>>2]; /* out_par */<br>
> +<br>
> + uint32_t *end = dest + width;<br>
> + while (dest < end)<br>
> + {<br>
> + __m64 s64 = combine (src, mask);<br>
> + __m64 d64,sa64,da64;<br>
> + uint8_t sa, da;<br>
> + uint32_t tmp;<br>
> + uint64_t Fa, Fb;<br>
> +<br>
> + /* Because these function contain division instructions,<br>
> + * multimedia instruction are not used to optimize them.<br>
> + */<br>
> + store8888(&tmp, s64);<br>
> + sa = tmp >> A_SHIFT;<br>
> + da = *dest >> A_SHIFT;<br>
> +<br>
> + Fa = combine_joint_u[0](sa, da, 0);<br>
> + Fb = combine_joint_u[1](sa, da, 1);<br>
> +<br>
> + d64 = load8888(dest);<br>
> + sa64 = expand_alpha_rev (*(__m64*)&Fa);<br>
> + da64 = expand_alpha_rev (*(__m64*)&Fb);<br>
> +<br>
> + d64 = pix_add_mul (s64, sa64, d64, da64);<br>
> +<br>
> + store8888 (dest, d64);<br>
> +<br>
> + ++dest;<br>
> + ++src;<br>
> + if (mask)<br>
> + ++mask;<br>
> + }<br>
> +}<br>
> +<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_general_u (uint32_t * dest,<br>
> + const uint32_t *src,<br>
> + const uint32_t *mask,<br>
> + int width,<br>
> + uint8_t comb)<br>
> +{<br>
> + mmx_combine_joint_general_u (dest, src, mask, width, comb, combine_disjoint_u);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_in_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_in_reverse_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_out_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_out_reverse_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_atop_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_atop_reverse_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_disjoint_xor_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR);<br>
> +}<br>
> +<br>
> +/* Conjoint */<br>
> +static void<br>
> +mmx_combine_conjoint_general_u(uint32_t * dest,<br>
> + const uint32_t *src,<br>
> + const uint32_t *mask,<br>
> + int width,<br>
> + uint8_t comb)<br>
> +{<br>
> + mmx_combine_joint_general_u (dest, src, mask, width, comb, combine_conjoint_u);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_over_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_over_reverse_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_in_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_in_reverse_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_out_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_out_reverse_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_atop_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_atop_reverse_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP);<br>
> +}<br>
> +<br>
> +static void<br>
> +mmx_combine_conjoint_xor_u (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + mmx_combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR);<br>
> +}<br>
><br>
> +/* Component alpha combiners */<br>
> static void<br>
> mmx_combine_src_ca (pixman_implementation_t *imp,<br>
> pixman_op_t op,<br>
> @@ -1089,6 +1503,410 @@ mmx_combine_src_ca (pixman_implementation_t *imp,<br>
> }<br>
><br>
> static void<br>
> +mmx_combine_saturate_ca (pixman_implementation_t *imp,<br>
> + pixman_op_t op,<br>
> + uint32_t * dest,<br>
> + const uint32_t * src,<br>
> + const uint32_t * mask,<br>
> + int width)<br>
> +{<br>
> + uint32_t *end = dest + width;<br>
> + while (dest < end)<br>
> + {<br>
> + uint16_t sa, sr, sg, sb;<br>
> + uint32_t sa32, m32;<br>
> + __m64 m64, s64, d64, sa64, da64, cmpf, res;<br>
> +<br>
> + mmx_combine_mask_ca (src, mask, &s64, &m64);<br>
> +<br>
> + d64 = load8888 (dest);<br>
> + da64 = expand_alpha (negate(d64));<br>
> + cmpf = _mm_cmpgt_pi16 (m64, da64);<br>
> + if (cmpf)<br>
> + {<br>
> + store8888 (&m32, m64);<br>
> + sa = (m32 >> (A_SHIFT));<br>
> + sr = (m32 >> (R_SHIFT)) & MASK;<br>
> + sg = (m32 >> (G_SHIFT)) & MASK;<br>
> + sb = m32 & MASK;<br>
> + sa32 = (~(*dest) >> A_SHIFT) & MASK;<br>
> +<br>
> + sa = (sa) ? sa : 0x1;<br>
> + sr = (sr) ? sr : 0x1;<br>
> + sg = (sg) ? sg : 0x1;<br>
> + sb = (sb) ? sb : 0x1;<br>
> +<br>
> + sa32 = ((sa32 << G_SHIFT) / sb & MASK) |<br>
> + ((((sa32 << G_SHIFT) / sg) & MASK) << G_SHIFT) |<br>
> + ((((sa32 << G_SHIFT) / sr) & MASK) << R_SHIFT) |<br>
> + ((((sa32 << G_SHIFT) / sa) & MASK) << A_SHIFT);<br>
> + sa64 = load8888 (&sa32);<br>
> + da64 = MC (4x00ff);<br>
> + res = pix_multiply (s64, sa64);<br>
> + s64 = _mm_or_si64 (_mm_and_si64 (res, cmpf), _mm_and_si64 (s64, negate (cmpf)));<br>
> + res = pix_multiply (d64, da64);<br>
> + d64 = _mm_or_si64 (_mm_and_si64 (res, cmpf), _mm_and_si64 (d64, negate (cmpf)));<br>
> + }<br>
> + res = _mm_adds_pu8 (s64, d64);<br>
> + store8888 (dest, res);<br>
> +<br>
> + ++dest;<br>
> + ++src;<br>
> + if (mask)<br>
> + ++mask;<br>
> + }<br>
> +}<br>
> +<br>
> +#define DEF_FUNC_COMBINE_JOINT_CA(cd, io) \<br>
> + static uint32_t inline combine_ ##cd## joint_ ##io## _part_ca(uint32_t sa, uint32_t da, uint32_t io_flag) \<br>
> + { \<br>
> + uint8_t da8 = da >> A_SHIFT; \<br>
> + uint32_t m, n, o, p, res; \<br>
> + uint8_t i, parm[2][4], shift=0; \<br>
> + for (i=0; i<4; i++) \<br>
> + { \<br>
> + parm[0][i] = (uint8_t)(sa>>shift) * (io_flag ^ 0x1) + da8 * (io_flag ^ 0x0); \<br>
> + parm[1][i] = (uint8_t)(sa>>shift) * (io_flag ^ 0x0) + da8 * (io_flag ^ 0x1); \<br>
> + shift += G_SHIFT; \<br>
> + } \<br>
> + m = (uint32_t)combine_ ##cd## joint_ ##io## _part (parm[0][0], parm[1][0]); \<br>
> + n = (uint32_t)combine_ ##cd## joint_ ##io## _part (parm[0][1], parm[1][1]) << G_SHIFT; \<br>
> + o = (uint32_t)combine_ ##cd## joint_ ##io## _part (parm[0][2], parm[1][2]) << R_SHIFT; \<br>
> + p = (uint32_t)combine_ ##cd## joint_ ##io## _part (parm[0][3], parm[1][3]) << A_SHIFT; \<br>
> + res = m | n | o | p; \<br>
> + return res; \<br>
> + }<br>
> +<br>
> +typedef uint32_t (*COMBINE_JOINT_FUNC_CA)(uint32_t sa, uint32_t da, uint32_t io_flag);<br>
> +<br>
> +DEF_FUNC_ZERO_MASK(uint32_t, zero, ca, 0x0)<br>
> +DEF_FUNC_ZERO_MASK(uint32_t, mask, ca, ~0x0)<br>
> +<br>
> +DEF_FUNC_COMBINE_JOINT_CA(dis, in);<br>
> +DEF_FUNC_COMBINE_JOINT_CA(dis, out);<br>
> +DEF_COMB_FUNC_ARR(dis, CA, ca)<br>
> +<br>
> +DEF_FUNC_COMBINE_JOINT_CA(con, in);<br>
> +DEF_FUNC_COMBINE_JOINT_CA(con, out);<br>
> +DEF_COMB_FUNC_ARR(con, CA, ca)<br>
> +<br>
> +static void<br>
> +mmx_combine_joint_general_ca (uint32_t * dest,<br>
> + const uint32_t *src,<br>
> + const uint32_t *mask,<br>
> + int width,<br>
> + uint8_t comb,<br>
> + COMBINE_JOINT_FUNC_CA *cjf)<br>
> +{<br>
> + COMBINE_JOINT_FUNC_CA combine_joint_ca[2];<br>
> + combine_joint_ca[0] = cjf[comb & COMBINE_A];<br>
> + combine_joint_ca[1] = cjf[(comb & COMBINE_B)>>2];<br>
> +<br>
> + uint32_t *end = dest + width;<br>
> + while (dest < end)<br>
> + {<br>
> + __m64 m64, s64, sa64, da64, d64;<br>
> + </blockquote></div>
</blockquote></div>