[cairo] [PATCH] Added MIPS32R2 and MIPS DSP ASE optimized functions
Georgi Beloev
gb at beloev.net
Thu Sep 9 08:30:28 PDT 2010
From 118b1f5596f72be7fed85ba408ff2961b3308038 Mon Sep 17 00:00:00 2001
From: Georgi Beloev <gb at beloev.net>
Date: Wed, 8 Sep 2010 17:34:22 -0700
Subject: [PATCH] Added MIPS32R2 and MIPS DSP ASE optimized functions.
The following functions were implemented for MIPS32R2:
- pixman_fill32()
- fast_composite_over_n_8_8888()
The following functions were implemented for MIPS DSP ASE:
- combine_over_u()
- fast_composite_over_n_8_8888()
Additionally, MIPS DSP ASE uses the MIPS32R2 pixman_fill32() function.
Use configure commands similar to the ones below to select the target
processor and, correspondingly, the target instruction set:
- MIPS32R2: configure CFLAGS='-march=24kc -O2'
- MIPS DSP ASE: configure CFLAGS='-march=24kec -O2'
---
configure.ac | 63 +++++++++++++
pixman/Makefile.am | 22 +++++
pixman/pixman-cpu.c | 24 +++++
pixman/pixman-mips-dspase1-asm.S | 189 ++++++++++++++++++++++++++++++++++++++
pixman/pixman-mips-dspase1.c | 110 ++++++++++++++++++++++
pixman/pixman-mips32r2-asm.S | 180 ++++++++++++++++++++++++++++++++++++
pixman/pixman-mips32r2.c | 115 +++++++++++++++++++++++
pixman/pixman-private.h | 11 ++
8 files changed, 714 insertions(+), 0 deletions(-)
create mode 100644 pixman/pixman-mips-dspase1-asm.S
create mode 100644 pixman/pixman-mips-dspase1.c
create mode 100644 pixman/pixman-mips32r2-asm.S
create mode 100644 pixman/pixman-mips32r2.c
diff --git a/configure.ac b/configure.ac
index dbff2a6..ce32843 100644
--- a/configure.ac
+++ b/configure.ac
@@ -562,6 +562,69 @@ fi
AM_CONDITIONAL(USE_GCC_INLINE_ASM, test $have_gcc_inline_asm = yes)
+dnl ==========================================================================
+dnl Check if the compiler supports MIPS32R2 instructions
+
+AC_MSG_CHECKING(whether to use MIPS32R2 instructions)
+AC_COMPILE_IFELSE([[
+void test()
+{
+ asm("ext \$v0,\$a0,8,8");
+}
+]], have_mips32r2=yes, have_mips32r2=no)
+
+AC_ARG_ENABLE(mips32r2,
+ [AC_HELP_STRING([--disable-mips32r2],
+ [disable MIPS32R2 fast paths])],
+ [enable_mips32r2=$enableval], [enable_mips32r2=auto])
+
+if test $enable_mips32r2 = no ; then
+ have_mips32r2=disabled
+fi
+
+if test $have_mips32r2 = yes ; then
+ AC_DEFINE(USE_MIPS32R2, 1, [use MIPS32R2 optimizations])
+fi
+
+AM_CONDITIONAL(USE_MIPS32R2, test $have_mips32r2 = yes)
+
+AC_MSG_RESULT($have_mips32r2)
+if test $enable_mips32r2 = yes && test $have_mips32r2 = no ; then
+ AC_MSG_ERROR([MIPS32R2 not detected])
+fi
+
+
+dnl ==========================================================================
+dnl Check if the compiler supports MIPS DSP ASE Rev 1 instructions
+
+AC_MSG_CHECKING(whether to use MIPS DSP ASE Rev 1 instructions)
+AC_COMPILE_IFELSE([[
+void test()
+{
+ asm("addu.qb \$v0,\$a0,\$a1");
+}
+]], have_mips_dspase1=yes, have_mips_dspase1=no)
+
+AC_ARG_ENABLE(mips-dspase1,
+ [AC_HELP_STRING([--disable-mips-dspase1],
+ [disable MIPS DSP ASE Rev 1 fast paths])],
+ [enable_mips_dspase1=$enableval], [enable_mips_dspase1=auto])
+
+if test $enable_mips_dspase1 = no ; then
+ have_mips_dspase1=disabled
+fi
+
+if test $have_mips_dspase1 = yes ; then
+ AC_DEFINE(USE_MIPS_DSPASE1, 1, [use MIPS DSP ASE Rev 1 optimizations])
+fi
+
+AM_CONDITIONAL(USE_MIPS_DSPASE1, test $have_mips_dspase1 = yes)
+
+AC_MSG_RESULT($have_mips_dspase1)
+if test $enable_mips_dspase1 = yes && test $have_mips_dspase1 = no ; then
+ AC_MSG_ERROR([MIPS DSP ASE Rev 1 not detected])
+fi
+
dnl ==============================================
dnl Timers
diff --git a/pixman/Makefile.am b/pixman/Makefile.am
index a9de19f..0863211 100644
--- a/pixman/Makefile.am
+++ b/pixman/Makefile.am
@@ -122,5 +122,27 @@ libpixman_1_la_LIBADD += libpixman-arm-neon.la
ASM_CFLAGS_arm_neon=
endif
+# MIPS32R2
+if USE_MIPS32R2
+noinst_LTLIBRARIES += libpixman-mips32r2.la
+libpixman_mips32r2_la_SOURCES = \
+ pixman-mips32r2.c \
+ pixman-mips32r2-asm.S
+libpixman_mips32r2_la_CFLAGS = $(DEP_CFLAGS)
+libpixman_mips32r2_la_LIBADD = $(DEP_LIBS)
+libpixman_1_la_LIBADD += libpixman-mips32r2.la
+endif
+
+# MIPS DSP ASE Rev 1
+if USE_MIPS_DSPASE1
+noinst_LTLIBRARIES += libpixman-mips-dspase1.la
+libpixman_mips_dspase1_la_SOURCES = \
+ pixman-mips-dspase1.c \
+ pixman-mips-dspase1-asm.S
+libpixman_mips_dspase1_la_CFLAGS = $(DEP_CFLAGS)
+libpixman_mips_dspase1_la_LIBADD = $(DEP_LIBS)
+libpixman_1_la_LIBADD += libpixman-mips-dspase1.la
+endif
+
.c.s : $(libpixmaninclude_HEADERS) $(BUILT_SOURCES)
$(CC) $(CFLAGS) $(ASM_CFLAGS_$(@:pixman-%.s=%)) $(ASM_CFLAGS_$(@:pixman-arm-%.s=arm_%)) -DHAVE_CONFIG_H -I$(srcdir) -I$(builddir) -I$(top_builddir) -S -o $@ $<
diff --git a/pixman/pixman-cpu.c b/pixman/pixman-cpu.c
index e4fb1e4..d8628c6 100644
--- a/pixman/pixman-cpu.c
+++ b/pixman/pixman-cpu.c
@@ -568,6 +568,17 @@ pixman_have_sse2 (void)
#endif /* __amd64__ */
#endif
+#ifdef USE_MIPS32R2
+// note: no runtime check for MIPS32R2 support
+#define pixman_have_mips32r2() TRUE
+#endif
+
+#ifdef USE_MIPS_DSPASE1
+// note: no runtime check for MIPS DSP ASE Rev 1 support
+#define pixman_have_mips_dspase1() TRUE
+#endif
+
+
pixman_implementation_t *
_pixman_choose_implementation (void)
{
@@ -593,6 +604,19 @@ _pixman_choose_implementation (void)
return _pixman_implementation_create_vmx ();
#endif
+#ifdef USE_MIPS32R2
+ pixman_implementation_t *imp = NULL;
+ if (pixman_have_mips32r2 ())
+ imp = _pixman_implementation_create_mips32r2 (imp);
+
+#ifdef USE_MIPS_DSPASE1
+ if (pixman_have_mips_dspase1 ())
+ imp = _pixman_implementation_create_mips_dspase1 (imp);
+#endif // USE_MIPS_DSPASE1
+
+ return imp;
+#endif // USE_MIPS32R2
+
return _pixman_implementation_create_fast_path ();
}
diff --git a/pixman/pixman-mips-dspase1-asm.S b/pixman/pixman-mips-dspase1-asm.S
new file mode 100644
index 0000000..b96fe83
--- /dev/null
+++ b/pixman/pixman-mips-dspase1-asm.S
@@ -0,0 +1,189 @@
+
+ .text
+ .set noreorder
+ .set nomacro
+
+
+// void
+// mips_dspase1_combine_over_u_nomask(uint32_t *dest, const uint32_t *src,
+// const uint32_t *mask, int width)
+
+ .global mips_dspase1_combine_over_u_nomask
+ .ent mips_dspase1_combine_over_u_nomask
+
+// note: this version to be used only when mask = NULL
+
+mips_dspase1_combine_over_u_nomask:
+ beqz $a3, 1f
+ subu $v0, $a1, $a0 // diff = src - dest (for LWX)
+
+ sll $a3, $a3, 2 // width <<= 2
+ addu $a3, $a0, $a3 // dest_end = dest + width
+
+ lw $t0, 0($a0) // dest
+ lwx $t1, $v0($a0) // src (dest + diff)
+
+ li $t9, 0x00800080
+
+0:
+ not $t2, $t1 // ~src
+ srl $t2, $t2, 24 // ALPHA_8(~src)
+ ins $t2, $t2, 16, 8 // 0:a:0:a; equivalent to replv.ph
+
+ muleu_s.ph.qbl $t3, $t0, $t2
+ muleu_s.ph.qbr $t4, $t0, $t2
+
+ lw $t0, 4($a0) // dest[1] for next loop iteration
+ addiu $a0, $a0, 4 // dest++
+
+ addu $t3, $t3, $t9 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t9 // can't overflow; rev2: addu_s.ph
+ preceu.ph.qbla $t5, $t3 // rev2: shrl.ph
+ preceu.ph.qbla $t6, $t4 // rev2: shrl.ph
+ addu $t3, $t3, $t5 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t6 // can't overflow; rev2: addu_s.ph
+
+ precrq.qb.ph $t3, $t3, $t4
+ addu_s.qb $t3, $t3, $t1
+
+ lwx $t1, $v0($a0) // src (dest + diff) for next loop iteration
+
+ bne $a0, $a3, 0b
+ sw $t3, -4($a0) // dest
+
+1:
+ jr $ra
+ nop
+
+ .end mips_dspase1_combine_over_u_nomask
+
+
+// void
+// mips_dspase1_combine_over_u_mask(uint32_t *dest, const uint32_t *src,
+// const uint32_t *mask, int width)
+
+ .global mips_dspase1_combine_over_u_mask
+ .ent mips_dspase1_combine_over_u_mask
+
+// note: this version to be used only when mask != NULL
+
+mips_dspase1_combine_over_u_mask:
+ beqz $a3, 1f
+ subu $v0, $a1, $a0 // sdiff = src - dest (for LWX)
+
+ subu $v1, $a2, $a0 // mdiff = mask - dest (for LWX)
+
+ sll $a3, $a3, 2 // width <<= 2
+ addu $a3, $a0, $a3 // dest_end = dest + width
+
+ li $t9, 0x00800080
+
+0:
+ lwx $t8, $v1($a0) // mask (dest + mdiff)
+ lwx $t1, $v0($a0) // src (dest + sdiff)
+
+ srl $t8, $t8, 24 // mask >>= A_SHIFT
+ ins $t8, $t8, 16, 8 // 0:m:0:m; equivalent to replv.ph
+
+ muleu_s.ph.qbl $t3, $t1, $t8
+ muleu_s.ph.qbr $t4, $t1, $t8
+
+ lw $t0, 0($a0) // dest
+
+ addu $t3, $t3, $t9 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t9 // can't overflow; rev2: addu_s.ph
+ preceu.ph.qbla $t5, $t3 // rev2: shrl.ph
+ preceu.ph.qbla $t6, $t4 // rev2: shrl.ph
+ addu $t3, $t3, $t5 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t6 // can't overflow; rev2: addu_s.ph
+ precrq.qb.ph $t1, $t3, $t4
+
+ not $t2, $t1 // ~src
+ srl $t2, $t2, 24 // ALPHA_8(~src)
+ ins $t2, $t2, 16, 8 // 0:a:0:a; equivalent to replv.ph
+
+ muleu_s.ph.qbl $t3, $t0, $t2
+ muleu_s.ph.qbr $t4, $t0, $t2
+
+ addiu $a0, $a0, 4 // dest++
+
+ addu $t3, $t3, $t9 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t9 // can't overflow; rev2: addu_s.ph
+ preceu.ph.qbla $t5, $t3 // rev2: shrl.ph
+ preceu.ph.qbla $t6, $t4 // rev2: shrl.ph
+ addu $t3, $t3, $t5 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t6 // can't overflow; rev2: addu_s.ph
+ precrq.qb.ph $t3, $t3, $t4
+ addu_s.qb $t3, $t3, $t1
+
+ bne $a0, $a3, 0b
+ sw $t3, -4($a0) // dest
+
+1:
+ jr $ra
+ nop
+
+ .end mips_dspase1_combine_over_u_mask
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// void
+// mips_dspase1_composite_over_n_8_8888_inner(uint32_t *dest, const uint32_t src,
+// const uint8_t *mask, int width)
+
+ .global mips_dspase1_composite_over_n_8_8888_inner
+ .ent mips_dspase1_composite_over_n_8_8888_inner
+
+mips_dspase1_composite_over_n_8_8888_inner:
+ beqz $a3, 1f
+ sll $a3, $a3, 2 // width <<= 2
+
+ addu $a3, $a0, $a3 // dest_end = dest + width
+
+ li $t9, 0x00800080
+
+0:
+ lbu $t8, 0($a2) // mask
+ lw $t0, 0($a0) // dest
+ ins $t8, $t8, 16, 8 // 0:m:0:m; equivalent to replv.ph
+
+ muleu_s.ph.qbl $t3, $a1, $t8
+ muleu_s.ph.qbr $t4, $a1, $t8
+
+ addiu $a0, $a0, 4 // dest++
+ addiu $a2, $a2, 1 // mask++
+
+ addu $t3, $t3, $t9 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t9 // can't overflow; rev2: addu_s.ph
+ preceu.ph.qbla $t5, $t3 // rev2: shrl.ph
+ preceu.ph.qbla $t6, $t4 // rev2: shrl.ph
+ addu $t3, $t3, $t5 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t6 // can't overflow; rev2: addu_s.ph
+ precrq.qb.ph $t1, $t3, $t4 // in(src,m)
+
+ not $t2, $t1 // ~in(src,m)
+ srl $t2, $t2, 24
+ ins $t2, $t2, 16, 8 // 0:a:0:a; equivalent to replv.ph
+
+ muleu_s.ph.qbl $t3, $t0, $t2
+ muleu_s.ph.qbr $t4, $t0, $t2
+
+ addu $t3, $t3, $t9 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t9 // can't overflow; rev2: addu_s.ph
+ preceu.ph.qbla $t5, $t3 // rev2: shrl.ph
+ preceu.ph.qbla $t6, $t4 // rev2: shrl.ph
+ addu $t3, $t3, $t5 // can't overflow; rev2: addu_s.ph
+ addu $t4, $t4, $t6 // can't overflow; rev2: addu_s.ph
+ precrq.qb.ph $t3, $t3, $t4
+ addu_s.qb $t3, $t3, $t1 // over(in(src,m),dest)
+
+ bne $a0, $a3, 0b
+ sw $t3, -4($a0) // dest
+
+1:
+ jr $ra
+ nop
+
+ .end mips_dspase1_composite_over_n_8_8888_inner
+
diff --git a/pixman/pixman-mips-dspase1.c b/pixman/pixman-mips-dspase1.c
new file mode 100644
index 0000000..13e0ad9
--- /dev/null
+++ b/pixman/pixman-mips-dspase1.c
@@ -0,0 +1,110 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pixman-private.h"
+
+
+// assembly-language functions
+
+void
+mips_dspase1_combine_over_u_nomask(uint32_t *dest, const uint32_t *src,
+ const uint32_t *mask, int width);
+
+void
+mips_dspase1_combine_over_u_mask(uint32_t *dest, const uint32_t *src,
+ const uint32_t *mask, int width);
+
+void
+mips_dspase1_composite_over_n_8_8888_inner(uint32_t *dest, uint32_t src,
+ const uint8_t *mask, int width);
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+static void
+mips_dspase1_combine_over_u(pixman_implementation_t *imp,
+ pixman_op_t op,
+ uint32_t * dest,
+ const uint32_t * src,
+ const uint32_t * mask,
+ int width)
+{
+ if (mask)
+ {
+// _pixman_implementation_combine_32(imp->delegate, op, dest, src, mask, width);
+ mips_dspase1_combine_over_u_mask(dest, src, mask, width);
+ }
+ else
+ {
+// _pixman_implementation_combine_32(imp->delegate, op, dest, src, mask, width);
+ mips_dspase1_combine_over_u_nomask(dest, src, mask, width);
+ }
+}
+
+
+static void
+mips_dspase1_fast_composite_over_n_8_8888(pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint32_t *dst_line, *dst;
+ uint8_t *mask_line, *mask;
+ int dst_stride, mask_stride;
+
+ src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+
+ mips_dspase1_composite_over_n_8_8888_inner(dst, src, mask, width);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+static const pixman_fast_path_t mips_dspase1_fast_paths[] =
+{
+ PIXMAN_STD_FAST_PATH(OVER, solid, a8, a8r8g8b8, mips_dspase1_fast_composite_over_n_8_8888),
+ { PIXMAN_OP_NONE }
+};
+
+
+pixman_implementation_t *
+_pixman_implementation_create_mips_dspase1 (pixman_implementation_t *delegate)
+{
+ if (delegate == NULL)
+ delegate = _pixman_implementation_create_fast_path ();
+
+ pixman_implementation_t *imp =
+ _pixman_implementation_create (delegate, mips_dspase1_fast_paths);
+
+ imp->combine_32[PIXMAN_OP_OVER] = mips_dspase1_combine_over_u;
+
+ return imp;
+}
diff --git a/pixman/pixman-mips32r2-asm.S b/pixman/pixman-mips32r2-asm.S
new file mode 100644
index 0000000..e5b4a6c
--- /dev/null
+++ b/pixman/pixman-mips32r2-asm.S
@@ -0,0 +1,180 @@
+
+ .text
+ .set noreorder
+ .set nomacro
+
+
+// pixman_bool_t
+// mips32r2_pixman_fill32(uint32_t *bits, int stride, int x, int y,
+// int width, int height, uint32_t xor)
+
+ .global mips32r2_pixman_fill32
+ .ent mips32r2_pixman_fill32
+
+mips32r2_pixman_fill32:
+ mul $a3, $a1, $a3
+ addu $a3, $a3, $a2
+ sll $a3, $a3, 2
+ addu $a0, $a0, $a3 // bits = bits + y * stride + x
+
+ lw $a2, 16($sp) // width
+ lw $a3, 20($sp) // height
+ lw $v0, 24($sp) // xor
+
+ li $t0, ~7
+ beqz $a3, 5f // exit if height = 0
+ and $t0, $a2, $t0 // width8 = width & ~7
+
+ sll $a1, $a1, 2 // stride <<= 2
+ sll $t0, $t0, 2 // width8 <<= 2
+ sll $a2, $a2, 2 // width <<= 2
+
+0:
+ move $t1, $a0 // b = bits
+ addu $t2, $t1, $t0 // b + width8
+
+ beq $t1, $t2, 2f // skip unrolled loop if not enough samples
+ addu $t3, $t1, $a2 // b + width
+
+1:
+ sw $v0, 0($t1)
+ sw $v0, 4($t1)
+ sw $v0, 8($t1)
+ sw $v0,12($t1)
+ sw $v0,16($t1)
+ sw $v0,20($t1)
+ sw $v0,24($t1)
+
+ addiu $t1, $t1, 32 // b += 8
+ bne $t1, $t2, 1b // b = (bits + width8)?
+ sw $v0, -4($t1)
+
+2:
+ beq $t1, $t3, 4f // skip single-sample loop if all work done
+ addiu $a3, $a3, -1 // height--
+
+3:
+ addiu $t1, $t1, 4
+ bne $t1, $t3, 3b // b = (bits + width)?
+ sw $v0, -4($t1)
+
+4:
+ bnez $a3, 0b
+ addu $a0, $a0, $a1 // bits += stride
+
+5:
+ jr $ra
+ li $v0, 1
+
+ .end mips32r2_pixman_fill32
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+// void
+// mips32r2_composite_over_n_8_8888_inner(uint32_t *dest, const uint32_t src,
+// const uint8_t *mask, int width)
+
+ .global mips32r2_composite_over_n_8_8888_inner
+ .ent mips32r2_composite_over_n_8_8888_inner
+
+mips32r2_composite_over_n_8_8888_inner:
+ beqz $a3, 1f
+ sll $a3, $a3, 2 // width <<= 2
+
+ addu $a3, $a0, $a3 // dest_end = dest + width
+
+ li $t7, 0x01000100
+ li $t8, 0x00FF00FF // RB_MASK
+ li $t9, 0x00800080
+
+0:
+ lbu $t2, 0($a2) // mask
+
+ // in()
+
+ and $t5, $a1, $t8
+ mul $t3, $t5, $t2
+
+ lw $t0, 0($a0) // dest
+ addiu $a2, $a2, 1 // mask++
+
+ srl $t6, $a1, 8
+ and $t6, $t6, $t8
+ mul $t4, $t6, $t2
+
+ addu $t3, $t3, $t9
+ srl $t5, $t3, 8
+ and $t5, $t5, $t8
+ addu $t3, $t3, $t5
+ srl $t3, $t3, 8
+ and $t3, $t3, $t8
+
+ addu $t4, $t4, $t9
+ srl $t6, $t4, 8
+ and $t6, $t6, $t8
+ addu $t4, $t4, $t6
+ srl $t4, $t4, 8
+ and $t4, $t4, $t8
+
+ sll $t4, $t4, 8
+ or $t1, $t3, $t4
+
+
+ not $t2, $t1 // ~in()
+ srl $t2, $t2, 24
+
+ // over(): UN8_rb_MUL_UN8() and UN8_rb_ADD_UN8_rb()
+
+ and $t5, $t0, $t8
+ mul $t3, $t5, $t2
+
+ addiu $a0, $a0, 4 // dest++
+
+ srl $t6, $t0, 8
+ and $t6, $t6, $t8
+ mul $t4, $t6, $t2
+
+ addu $t3, $t3, $t9
+ srl $t5, $t3, 8
+ and $t5, $t5, $t8
+ addu $t3, $t3, $t5
+ srl $t3, $t3, 8
+ and $t3, $t3, $t8
+
+ and $t5, $t1, $t8
+ addu $t3, $t3, $t5
+ srl $t5, $t3, 8
+ and $t5, $t5, $t8
+ subu $t5, $t7, $t5
+ or $t3, $t3, $t5
+ and $t3, $t3, $t8
+
+ addu $t4, $t4, $t9
+ srl $t6, $t4, 8
+ and $t6, $t6, $t8
+ addu $t4, $t4, $t6
+ srl $t4, $t4, 8
+ and $t4, $t4, $t8
+
+ srl $t6, $t1, 8
+ and $t6, $t6, $t8
+ addu $t4, $t4, $t6
+ srl $t6, $t4, 8
+ and $t6, $t6, $t8
+ subu $t6, $t7, $t6
+ or $t4, $t4, $t6
+ and $t4, $t4, $t8
+
+ sll $t4, $t4, 8
+ or $t3, $t3, $t4
+
+ bne $a0, $a3, 0b
+ sw $t3, -4($a0) // dest
+
+1:
+ jr $ra
+ nop
+
+ .end mips32r2_composite_over_n_8_8888_inner
+
diff --git a/pixman/pixman-mips32r2.c b/pixman/pixman-mips32r2.c
new file mode 100644
index 0000000..70cfdd7
--- /dev/null
+++ b/pixman/pixman-mips32r2.c
@@ -0,0 +1,115 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pixman-private.h"
+
+
+// assembly-language functions
+
+pixman_bool_t
+mips32r2_pixman_fill32(uint32_t *bits, int stride, int x, int y,
+ int width, int height, uint32_t xor);
+
+void
+mips32r2_composite_over_n_8_8888_inner(uint32_t *dest, uint32_t src,
+ const uint8_t *mask, int width);
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+static pixman_bool_t
+mips32r2_fill(pixman_implementation_t *imp,
+ uint32_t * bits,
+ int stride,
+ int bpp,
+ int x,
+ int y,
+ int width,
+ int height,
+ uint32_t xor)
+{
+ pixman_bool_t b;
+
+ switch (bpp)
+ {
+ case 32:
+// b = _pixman_implementation_fill(imp->delegate, bits, stride, bpp, x, y, width, height, xor);
+ b = mips32r2_pixman_fill32(bits, stride, x, y, width, height, xor);
+ break;
+
+ default:
+ b = _pixman_implementation_fill(imp->delegate, bits, stride, bpp,
+ x, y, width, height, xor);
+ break;
+ }
+
+ return b;
+}
+
+
+static void
+mips32r2_fast_composite_over_n_8_8888(pixman_implementation_t *imp,
+ pixman_op_t op,
+ pixman_image_t * src_image,
+ pixman_image_t * mask_image,
+ pixman_image_t * dst_image,
+ int32_t src_x,
+ int32_t src_y,
+ int32_t mask_x,
+ int32_t mask_y,
+ int32_t dest_x,
+ int32_t dest_y,
+ int32_t width,
+ int32_t height)
+{
+ uint32_t src, srca;
+ uint32_t *dst_line, *dst;
+ uint8_t *mask_line, *mask;
+ int dst_stride, mask_stride;
+
+ src = _pixman_image_get_solid (src_image, dst_image->bits.format);
+
+ srca = src >> 24;
+ if (src == 0)
+ return;
+
+ PIXMAN_IMAGE_GET_LINE (dst_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
+ PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
+
+ while (height--)
+ {
+ dst = dst_line;
+ dst_line += dst_stride;
+ mask = mask_line;
+ mask_line += mask_stride;
+
+ mips32r2_composite_over_n_8_8888_inner(dst, src, mask, width);
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+
+static const pixman_fast_path_t mips32r2_fast_paths[] =
+{
+ PIXMAN_STD_FAST_PATH(OVER, solid, a8, a8r8g8b8, mips32r2_fast_composite_over_n_8_8888),
+ { PIXMAN_OP_NONE }
+};
+
+
+pixman_implementation_t *
+_pixman_implementation_create_mips32r2 (pixman_implementation_t *delegate)
+{
+ if (delegate == NULL)
+ delegate = _pixman_implementation_create_fast_path ();
+
+ pixman_implementation_t *imp =
+ _pixman_implementation_create (delegate, mips32r2_fast_paths);
+
+ imp->fill = mips32r2_fill;
+
+ return imp;
+}
diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index dedea0b..d52f063 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -527,6 +527,17 @@ pixman_implementation_t *
_pixman_implementation_create_vmx (void);
#endif
+#ifdef USE_MIPS32R2
+pixman_implementation_t *
+_pixman_implementation_create_mips32r2 (pixman_implementation_t *delegate);
+#endif
+
+#ifdef USE_MIPS_DSPASE1
+pixman_implementation_t *
+_pixman_implementation_create_mips_dspase1 (pixman_implementation_t *delegate);
+#endif
+
+
pixman_implementation_t *
_pixman_choose_implementation (void);
--
1.7.1
More information about the cairo
mailing list