public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: Vector permutation support for x86
@ 2009-12-02 20:04 Uros Bizjak
  2009-12-02 20:10 ` Sebastian Pop
  2009-12-02 21:22 ` Sebastian Pop
  0 siblings, 2 replies; 45+ messages in thread
From: Uros Bizjak @ 2009-12-02 20:04 UTC (permalink / raw)
  To: GCC Patches; +Cc: Sebastian Pop, Richard Henderson

Hello!

+	  (match_operand:SSEMODEF4 1 "register_operand" "%x,x")
+	  (match_operand:SSEMODEF4 2 "nonimmediate_operand" "x,xm"))
+	 (match_operand:SSEMODEF4 3 "nonimmediate_operand" "xm,x")))]


You can use only "x,m" in the operand 2, all-registers alternative is 
already matched in alternative 0.

Uros.

^ permalink raw reply	[flat|nested] 45+ messages in thread
* Re: Vector permutation support for x86
@ 2009-11-27 10:17 Uros Bizjak
  2009-11-27 16:02 ` Richard Henderson
  0 siblings, 1 reply; 45+ messages in thread
From: Uros Bizjak @ 2009-11-27 10:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Henderson

Hello!

>>    I'm not sure when these were introduced; I probably would have made
>>    some objection at the time if I had noticed. However, I'll grant you
>>    that it'll be easy to notice if someone breaks this idiom. I don't
>>    agree that it's necessary, but since I can't prove it isn't I suppose
>>    I can revert the change to the define_expand for v16qi.


> I've committed the following, though I'm still not convinced.

> I think one could argue that this misses more cse opportunities
> than it finds.  Consider for instance:

>  x = a * b;
>  y = c * b;


> for mulv16qi, the expansion produces two sets of

>  sse2_punpckhbw (tmp, b, b)
>  sse2_punpcklbw (tmp, b, b)

which could be cse'd...

I have tried with the following testcase and attached patch that
changes all define_insn_and_split mult sequences to expanders.

--cut here--
char a[256], b[256], c[256], x[256], y[256];

void bar(void)
{
  int i;

  for (i=0; i<256; ++i)
    {
      x[i] = a[i] * b[i];
      y[i] = c[i] * b[i];
    }
}
--cut here--

The difference was:

> grep unpck vect-p.s | wc -l
20
> grep unpck vect.s | wc -l
22

Where vect-p.s was created with expanders. The full sequence had 45 vs 48 insns.

The same test with ints/longs showed no noticable differences.

With longs and -mxop, I get substantial differences. With splitter:

	xorl	%eax, %eax
.L2:
	vmovdqa	b(%rax), %xmm0
	vpshufd	$177, %xmm0, %xmm2
	vmovdqa	a(%rax), %xmm1
	vpmulld	%xmm1, %xmm2, %xmm2
	vphadddq	%xmm2, %xmm2
	vpsllq	$32, %xmm2, %xmm2
	vpmacsdql	%xmm2, %xmm1, %xmm0, %xmm1
	vmovdqa	%xmm1, x(%rax)
	vmovdqa	c(%rax), %xmm1
	vpshufd	$177, %xmm1, %xmm2
	vpmulld	%xmm0, %xmm2, %xmm2
	vphadddq	%xmm2, %xmm2
	vpsllq	$32, %xmm2, %xmm2
	vpmacsdql	%xmm2, %xmm0, %xmm1, %xmm0
	vmovdqa	%xmm0, y(%rax)
	addq	$16, %rax
	cmpq	$2048, %rax
	jne	.L2
	rep
	ret

and with expander:

	vpxor	%xmm3, %xmm3, %xmm3
	xorl	%eax, %eax
	vmovdqa	%xmm3, %xmm2
.L2:
	vmovdqa	b(%rax), %xmm0
	vpmacsdql	%xmm3, a(%rax), %xmm0, %xmm1
	vpmacsdql	%xmm2, c(%rax), %xmm0, %xmm0
	vmovdqa	%xmm1, x(%rax)
	vmovdqa	%xmm0, y(%rax)
	addq	$16, %rax
	cmpq	$2048, %rax
	jne	.L2
	rep
	ret

I will investigate this last issue a bit more.

Uros.

^ permalink raw reply	[flat|nested] 45+ messages in thread
* Re: Vector permutation support for x86
@ 2009-11-26  9:14 Uros Bizjak
  2009-11-26 19:18 ` Richard Henderson
  0 siblings, 1 reply; 45+ messages in thread
From: Uros Bizjak @ 2009-11-26  9:14 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Henderson

Hello!

> -(define_insn_and_split "mulv16qi3"
> +(define_expand "mulv16qi3"
>    [(set (match_operand:V16QI 0 "register_operand" "")
>  	(mult:V16QI (match_operand:V16QI 1 "register_operand" "")
>  		    (match_operand:V16QI 2 "register_operand" "")))]
> -  "TARGET_SSE2
> -   && can_create_pseudo_p ()"
> -  "#"
> -  "&& 1"
> -  [(const_int 0)]
> +  "TARGET_SSE2"

	(mulv16qi3, vec_pack_trunc_v8hi, vec_pack_trunc_v4si,
	vec_pack_trunc_v2di): Use ix86_expand_vec_extract_even_odd.

Please leave this pattern in its "mult" form up to split1 pass, so
combine [and other passes] can process it as a multiplication
operator. Also, please see PR33329 and PR26449 for some troubles in
this area, when these patterns were split early.

(This change is not documented in ChangeLog, it looks like an
unintended change.)

Uros.

^ permalink raw reply	[flat|nested] 45+ messages in thread
* Vector permutation support for x86
@ 2009-11-26  3:55 Richard Henderson
  2009-11-27 23:54 ` H.J. Lu
  2009-11-30 18:36 ` Sebastian Pop
  0 siblings, 2 replies; 45+ messages in thread
From: Richard Henderson @ 2009-11-26  3:55 UTC (permalink / raw)
  To: GCC Patches; +Cc: Sebastian Pop

[-- Attachment #1: Type: text/plain, Size: 860 bytes --]

The following implements the builtin_vec_perm hook so that the 
vectorizer can do its SLP thing.  As noted elsewhere, ISAs before SSSE3 
cannot arbitrarily permute, so this complicates things a bit.  But even 
given SSSE3, the arbitrary two-vector permute costs 3 insns, and so we 
would want to do most of this work to find the 1 and 2 insn special cases.

For the AMD folk: I tried to support the vpperm insn from the XOP ISA, 
but there seems to be some disconnect between trunk binutils and trunk 
gcc wrt vpperm.  This can be seen in the failure of the new test 
"vperm-v4si-2x.c".  I'm looking at the XOP spec labeled "Pub No 43479, 
Rev 3.03, May 2009", and what gcc is emitting looks ok.  But I've 
already been bitten by an out-of-date AVX spec during this adventure, so 
I'd appreciate some double-check.

Tested on an i7 machine (i.e. sse4.2).


r~

[-- Attachment #2: zz --]
[-- Type: text/plain, Size: 2180 bytes --]

	* config/i386/i386-builtin-types.awk (DEF_VECTOR_TYPE): Allow an
	optional 3rd argument to define the mode.
	* config/i386/i386-builtin-types.def (UQI, UHI, USI, UDI): New.
	(V2UDI, V4USI, V8UHI, V16UQI): New.
	(V4SF_FTYPE_V4SF_V4SF_V4SI, V2UDI_FTYPE_V2UDI_V2UDI_V2UDI,
	V4USI_FTYPE_V4USI_V4USI_V4USI, V8UHI_FTYPE_V8UHI_V8UHI_V8UHI,
	V16UQI_FTYPE_V16UQI_V16UQI_V16UQI): New.
	* config/i386/i386-modes.def: Rearrange for double-wide AVX.
	* config/i386/i386-protos.h (ix86_expand_vec_extract_even_odd): New.
	* config/i386/i386.c (IX86_BUILTIN_VEC_PERM_*): New.
	(bdesc_args): Add the builtin definitions to match.
	(ix86_expand_builtin): Expand them.
	(ix86_builtin_vectorization_cost): Rename from
	x86_builtin_vectorization_cost.
	(ix86_vectorize_builtin_vec_perm, struct expand_vec_perm_d,
	doublesize_vector_mode, expand_vselect, expand_vselect_vconcat,
	expand_vec_perm_blend, expand_vec_perm_vpermil,
	expand_vec_perm_pshufb, expand_vec_perm_1,
	expand_vec_perm_pshuflw_pshufhw, expand_vec_perm_palignr,
	expand_vec_perm_interleave2, expand_vec_perm_pshufb2,
	expand_vec_perm_even_odd_1, expand_vec_perm_even_odd,
	ix86_expand_vec_perm_builtin_1, extract_vec_perm_cst,
	ix86_expand_vec_perm_builtin, ix86_vectorize_builtin_vec_perm_ok,
	ix86_expand_vec_extract_even_odd, TARGET_VECTORIZE_BUILTIN_VEC_PERM,
	TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK): New.
	* sse.md (SSEMODE_EO): New.
	(vec_extract_even<mode>): Use SSEMODE_EO and
	ix86_expand_vec_extract_even_odd.
	(vec_extract_odd<mode>): Likewise.
	(mulv16qi3, vec_pack_trunc_v8hi, vec_pack_trunc_v4si,
	vec_pack_trunc_v2di): Use ix86_expand_vec_extract_even_odd.

testsuite/
	* gcc.dg/vect/slp-21.c: Succeed with vect_extract_even_odd too.

	* lib/target-supports.exp
	(check_effective_target_vect_extract_even_odd): Add x86.

	* gcc.target/i386/isa-check.h: New.
	* gcc.target/i386/vperm-2-2.inc, gcc.target/i386/vperm-4-1.inc,
	gcc.target/i386/vperm-4-2.inc, gcc.target/i386/vperm-v2df.c,
	gcc.target/i386/vperm-v2di.c, gcc.target/i386/vperm-v4sf-1.c,
	gcc.target/i386/vperm-v4sf-2.c, gcc.target/i386/vperm-v4si-1.c,
	gcc.target/i386/vperm-v4si-2.c, gcc.target/i386/vperm-v4si-2x.c,
	gcc.target/i386/vperm.pl: New files.

[-- Attachment #3: z --]
[-- Type: text/plain, Size: 156430 bytes --]

diff --git a/gcc/config/i386/i386-builtin-types.awk b/gcc/config/i386/i386-builtin-types.awk
index 0c54458..7b016f4 100644
--- a/gcc/config/i386/i386-builtin-types.awk
+++ b/gcc/config/i386/i386-builtin-types.awk
@@ -69,11 +69,12 @@ $1 == "DEF_PRIMITIVE_TYPE" {
 }
 
 $1 == "DEF_VECTOR_TYPE" {
-    if (NF == 4) {
+    if (NF == 4 || NF == 5) {
 	check_type($3)
 	type_hash[$2] = 1
-	vect_mode[vect_defs] = $2
+	vect_name[vect_defs] = $2
 	vect_base[vect_defs] = $3
+	vect_mode[vect_defs] = (NF == 5 ? $4 : $2)
 	vect_defs++
     } else
 	do_error("DEF_VECTOR_TYPE expected 2 arguments")
@@ -152,8 +153,8 @@ END {
 	print "  IX86_BT_" prim_name[i] ","
     print "  IX86_BT_LAST_PRIM = IX86_BT_" prim_name[i-1] ","
     for (i = 0; i < vect_defs; ++i)
-	print "  IX86_BT_" vect_mode[i] ","
-    print "  IX86_BT_LAST_VECT = IX86_BT_" vect_mode[i-1] ","
+	print "  IX86_BT_" vect_name[i] ","
+    print "  IX86_BT_LAST_VECT = IX86_BT_" vect_name[i-1] ","
     for (i = 0; i < ptr_defs; ++i)
 	print "  IX86_BT_" ptr_name[i] ","
     print "  IX86_BT_LAST_PTR = IX86_BT_" ptr_name[i-1] ","
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 3f0b20b..9f45a13 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -10,12 +10,12 @@
 #   At present, that's all that's required; revisit if it turns out
 #   that we need more than that.
 #
-# DEF_VECTOR_TYPE (ENUM, TYPE)
+# DEF_VECTOR_TYPE (ENUM, TYPE [, MODE])
 #
-#  This describes a vector type.  ENUM doubles as both the identifier
-#  to define in the enumeration as well as the mode of the vector; TYPE is
-#  the enumeral for the inner type which should of course name a type of
-#  the proper inner mode.
+#  This describes a vector type.  ENUM is an identifier as above.
+#  TYPE is the enumeral for the inner type which should of course
+#  name a type of the proper inner mode.  If present, MODE is the
+#  machine mode, else the machine mode should be the same as ENUM.
 #
 # DEF_POINTER_TYPE (ENUM, TYPE [, CONST])
 #
@@ -40,10 +40,22 @@
 DEF_PRIMITIVE_TYPE (VOID, void_type_node)
 DEF_PRIMITIVE_TYPE (CHAR, char_type_node)
 DEF_PRIMITIVE_TYPE (UCHAR, unsigned_char_type_node)
-DEF_PRIMITIVE_TYPE (QI, intQI_type_node)
+# ??? Logically this should be intQI_type_node, but that maps to "signed char"
+# which is a different type than "char" even if "char" is signed.  This must
+# match the usage in emmintrin.h and changing this would change name mangling
+# and so is not advisable.
+DEF_PRIMITIVE_TYPE (QI, char_type_node)
 DEF_PRIMITIVE_TYPE (HI, intHI_type_node)
 DEF_PRIMITIVE_TYPE (SI, intSI_type_node)
+# ??? Logically this should be intDI_type_node, but that maps to "long"
+# with 64-bit, and that's not how the emmintrin.h is written.  Again, 
+# changing this would change name mangling.
 DEF_PRIMITIVE_TYPE (DI, long_long_integer_type_node)
+DEF_PRIMITIVE_TYPE (UQI, unsigned_intQI_type_node)
+DEF_PRIMITIVE_TYPE (UHI, unsigned_intHI_type_node)
+DEF_PRIMITIVE_TYPE (USI, unsigned_intSI_type_node)
+DEF_PRIMITIVE_TYPE (UDI, long_long_unsigned_type_node)
+# ??? Some of the types below should use the mode types above.
 DEF_PRIMITIVE_TYPE (USHORT, short_unsigned_type_node)
 DEF_PRIMITIVE_TYPE (INT, integer_type_node)
 DEF_PRIMITIVE_TYPE (UINT, unsigned_type_node)
@@ -59,23 +71,33 @@ DEF_PRIMITIVE_TYPE (DOUBLE, double_type_node)
 DEF_PRIMITIVE_TYPE (FLOAT80, float80_type_node)
 DEF_PRIMITIVE_TYPE (FLOAT128, float128_type_node)
 
-DEF_VECTOR_TYPE (V16HI, HI)
-DEF_VECTOR_TYPE (V16QI, CHAR)
-DEF_VECTOR_TYPE (V1DI, DI)
-DEF_VECTOR_TYPE (V2DF, DOUBLE)
-DEF_VECTOR_TYPE (V2DI, DI)
+# MMX vectors
 DEF_VECTOR_TYPE (V2SF, FLOAT)
+DEF_VECTOR_TYPE (V1DI, DI)
 DEF_VECTOR_TYPE (V2SI, SI)
-DEF_VECTOR_TYPE (V32QI, CHAR)
-DEF_VECTOR_TYPE (V4DF, DOUBLE)
-DEF_VECTOR_TYPE (V4DI, DI)
 DEF_VECTOR_TYPE (V4HI, HI)
+DEF_VECTOR_TYPE (V8QI, QI)
+
+# SSE vectors
+DEF_VECTOR_TYPE (V2DF, DOUBLE)
 DEF_VECTOR_TYPE (V4SF, FLOAT)
+DEF_VECTOR_TYPE (V2DI, DI)
 DEF_VECTOR_TYPE (V4SI, SI)
 DEF_VECTOR_TYPE (V8HI, HI)
-DEF_VECTOR_TYPE (V8QI, CHAR)
+DEF_VECTOR_TYPE (V16QI, QI)
+DEF_VECTOR_TYPE (V2UDI, UDI, V2DI)
+DEF_VECTOR_TYPE (V4USI, USI, V4SI)
+DEF_VECTOR_TYPE (V8UHI, UHI, V8HI)
+DEF_VECTOR_TYPE (V16UQI, UQI, V16QI)
+
+# AVX vectors
+DEF_VECTOR_TYPE (V4DF, DOUBLE)
 DEF_VECTOR_TYPE (V8SF, FLOAT)
+DEF_VECTOR_TYPE (V4DI, DI)
 DEF_VECTOR_TYPE (V8SI, SI)
+DEF_VECTOR_TYPE (V16HI, HI)
+DEF_VECTOR_TYPE (V32QI, QI)
+
 
 DEF_POINTER_TYPE (PCCHAR, CHAR, CONST)
 DEF_POINTER_TYPE (PCDOUBLE, DOUBLE, CONST)
@@ -323,6 +345,12 @@ DEF_FUNCTION_TYPE (VOID, UINT64, UINT, UINT)
 DEF_FUNCTION_TYPE (VOID, USHORT, UINT, USHORT)
 DEF_FUNCTION_TYPE (VOID, V16QI, V16QI, PCHAR)
 DEF_FUNCTION_TYPE (VOID, V8QI, V8QI, PCHAR)
+DEF_FUNCTION_TYPE (V2DF, V2DF, V2DF, V2DI)
+DEF_FUNCTION_TYPE (V4SF, V4SF, V4SF, V4SI)
+DEF_FUNCTION_TYPE (V2UDI, V2UDI, V2UDI, V2UDI)
+DEF_FUNCTION_TYPE (V4USI, V4USI, V4USI, V4USI)
+DEF_FUNCTION_TYPE (V8UHI, V8UHI, V8UHI, V8UHI)
+DEF_FUNCTION_TYPE (V16UQI, V16UQI, V16UQI, V16UQI)
 
 DEF_FUNCTION_TYPE (V2DI, V2DI, V2DI, UINT, UINT)
 DEF_FUNCTION_TYPE (V4HI, HI, HI, HI, HI)
diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def
index 9c94802..f2e06ee 100644
--- a/gcc/config/i386/i386-modes.def
+++ b/gcc/config/i386/i386-modes.def
@@ -69,22 +69,20 @@ CC_MODE (CCZ);
 CC_MODE (CCFP);
 CC_MODE (CCFPU);
 
-/* Vector modes.  */
-VECTOR_MODES (INT, 4);        /*            V4QI V2HI */
-VECTOR_MODES (INT, 8);        /*       V8QI V4HI V2SI */
-VECTOR_MODES (INT, 16);       /* V16QI V8HI V4SI V2DI */
-VECTOR_MODES (INT, 32);       /* V32QI V16HI V8SI V4DI */
-VECTOR_MODES (FLOAT, 8);      /*            V4HF V2SF */
-VECTOR_MODES (FLOAT, 16);     /*       V8HF V4SF V2DF */
-VECTOR_MODES (FLOAT, 32);     /*      V16HF V8SF V4DF */
-VECTOR_MODE (INT, DI, 1);     /*                 V1DI */
-VECTOR_MODE (INT, SI, 1);     /*                 V1SI */
-VECTOR_MODE (INT, QI, 2);     /*                 V2QI */
-VECTOR_MODE (INT, DI, 8);     /*                 V8DI */
-VECTOR_MODE (INT, HI, 32);    /*                V32HI */
-VECTOR_MODE (INT, QI, 64);    /*                V64QI */
-VECTOR_MODE (FLOAT, DF, 8);   /*                 V8DF */
-VECTOR_MODE (FLOAT, SF, 16);  /*                V16SF */
+/* Vector modes.  Note that VEC_CONCAT patterns require vector
+   sizes twice as big as implemented in hardware.  */
+VECTOR_MODES (INT, 4);        /*              V4QI V2HI */
+VECTOR_MODES (INT, 8);        /*         V8QI V4HI V2SI */
+VECTOR_MODES (INT, 16);       /*   V16QI V8HI V4SI V2DI */
+VECTOR_MODES (INT, 32);       /*  V32QI V16HI V8SI V4DI */
+VECTOR_MODES (INT, 64);       /* V64QI V32HI V16SI V8DI */
+VECTOR_MODES (FLOAT, 8);      /*              V4HF V2SF */
+VECTOR_MODES (FLOAT, 16);     /*         V8HF V4SF V2DF */
+VECTOR_MODES (FLOAT, 32);     /*        V16HF V8SF V4DF */
+VECTOR_MODES (FLOAT, 64);     /*       V32HF V16SF V8DF */
+VECTOR_MODE (INT, DI, 1);     /*                   V1DI */
+VECTOR_MODE (INT, SI, 1);     /*                   V1SI */
+VECTOR_MODE (INT, QI, 2);     /*                   V2QI */
 
 INT_MODE (OI, 32);
 
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index d36b269..88acc1f 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -219,6 +219,8 @@ extern void ix86_expand_reduc_v4sf (rtx (*)(rtx, rtx, rtx), rtx, rtx);
 extern bool ix86_fma4_valid_op_p (rtx [], rtx, int, bool, int, bool);
 extern void ix86_expand_fma4_multiple_memory (rtx [], int, enum machine_mode);
 
+extern void ix86_expand_vec_extract_even_odd (rtx, rtx, rtx, unsigned);
+
 /* In i386-c.c  */
 extern void ix86_target_macros (void);
 extern void ix86_register_pragmas (void);
@@ -277,4 +279,3 @@ extern int asm_preferred_eh_data_format (int, int);
 #ifdef HAVE_ATTR_cpu
 extern enum attr_cpu ix86_schedule;
 #endif
-
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f1bb9ec..4d5e8a3 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -54,7 +54,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "cselib.h"
 
-static int x86_builtin_vectorization_cost (bool);
 static rtx legitimize_dllimport_symbol (rtx, bool);
 
 #ifndef CHECK_STACK_LIMIT
@@ -1885,6 +1884,7 @@ static void ix86_compute_frame_layout (struct ix86_frame *);
 static bool ix86_expand_vector_init_one_nonzero (bool, enum machine_mode,
 						 rtx, rtx, int);
 static void ix86_add_new_builtins (int);
+static rtx ix86_expand_vec_perm_builtin (tree);
 
 enum ix86_function_specific_strings
 {
@@ -21037,6 +21037,17 @@ enum ix86_builtins
 
   IX86_BUILTIN_CVTUDQ2PS,
 
+  IX86_BUILTIN_VEC_PERM_V2DF,
+  IX86_BUILTIN_VEC_PERM_V4SF,
+  IX86_BUILTIN_VEC_PERM_V2DI,
+  IX86_BUILTIN_VEC_PERM_V4SI,
+  IX86_BUILTIN_VEC_PERM_V8HI,
+  IX86_BUILTIN_VEC_PERM_V16QI,
+  IX86_BUILTIN_VEC_PERM_V2DI_U,
+  IX86_BUILTIN_VEC_PERM_V4SI_U,
+  IX86_BUILTIN_VEC_PERM_V8HI_U,
+  IX86_BUILTIN_VEC_PERM_V16QI_U,
+
   /* FMA4 and XOP instructions.  */
   IX86_BUILTIN_VFMADDSS,
   IX86_BUILTIN_VFMADDSD,
@@ -21710,6 +21721,17 @@ static const struct builtin_description bdesc_args[] =
   /* SSE2 */
   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_shufpd, "__builtin_ia32_shufpd", IX86_BUILTIN_SHUFPD, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_INT },
 
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v2df", IX86_BUILTIN_VEC_PERM_V2DF, UNKNOWN, (int) V2DF_FTYPE_V2DF_V2DF_V2DI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v4sf", IX86_BUILTIN_VEC_PERM_V4SF, UNKNOWN, (int) V4SF_FTYPE_V4SF_V4SF_V4SI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v2di", IX86_BUILTIN_VEC_PERM_V2DI, UNKNOWN, (int) V2DI_FTYPE_V2DI_V2DI_V2DI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v4si", IX86_BUILTIN_VEC_PERM_V4SI, UNKNOWN, (int) V4SI_FTYPE_V4SI_V4SI_V4SI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v8hi", IX86_BUILTIN_VEC_PERM_V8HI, UNKNOWN, (int) V8HI_FTYPE_V8HI_V8HI_V8HI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v16qi", IX86_BUILTIN_VEC_PERM_V16QI, UNKNOWN, (int) V16QI_FTYPE_V16QI_V16QI_V16QI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v2di_u", IX86_BUILTIN_VEC_PERM_V2DI_U, UNKNOWN, (int) V2UDI_FTYPE_V2UDI_V2UDI_V2UDI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v4si_u", IX86_BUILTIN_VEC_PERM_V4SI_U, UNKNOWN, (int) V4USI_FTYPE_V4USI_V4USI_V4USI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v8hi_u", IX86_BUILTIN_VEC_PERM_V8HI_U, UNKNOWN, (int) V8UHI_FTYPE_V8UHI_V8UHI_V8UHI },
+  { OPTION_MASK_ISA_SSE2, CODE_FOR_nothing, "__builtin_ia32_vec_perm_v16qi_u", IX86_BUILTIN_VEC_PERM_V16QI_U, UNKNOWN, (int) V16UQI_FTYPE_V16UQI_V16UQI_V16UQI },
+
   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_movmskpd, "__builtin_ia32_movmskpd", IX86_BUILTIN_MOVMSKPD, UNKNOWN, (int) INT_FTYPE_V2DF  },
   { OPTION_MASK_ISA_SSE2, CODE_FOR_sse2_pmovmskb, "__builtin_ia32_pmovmskb128", IX86_BUILTIN_PMOVMSKB128, UNKNOWN, (int) INT_FTYPE_V16QI },
   { OPTION_MASK_ISA_SSE2, CODE_FOR_sqrtv2df2, "__builtin_ia32_sqrtpd", IX86_BUILTIN_SQRTPD, UNKNOWN, (int) V2DF_FTYPE_V2DF },
@@ -24119,6 +24141,18 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
     case IX86_BUILTIN_VEC_SET_V16QI:
       return ix86_expand_vec_set_builtin (exp);
 
+    case IX86_BUILTIN_VEC_PERM_V2DF:
+    case IX86_BUILTIN_VEC_PERM_V4SF:
+    case IX86_BUILTIN_VEC_PERM_V2DI:
+    case IX86_BUILTIN_VEC_PERM_V4SI:
+    case IX86_BUILTIN_VEC_PERM_V8HI:
+    case IX86_BUILTIN_VEC_PERM_V16QI:
+    case IX86_BUILTIN_VEC_PERM_V2DI_U:
+    case IX86_BUILTIN_VEC_PERM_V4SI_U:
+    case IX86_BUILTIN_VEC_PERM_V8HI_U:
+    case IX86_BUILTIN_VEC_PERM_V16QI_U:
+      return ix86_expand_vec_perm_builtin (exp);
+
     case IX86_BUILTIN_INFQ:
     case IX86_BUILTIN_HUGE_VALQ:
       {
@@ -28904,7 +28938,7 @@ static const struct attribute_spec ix86_attribute_table[] =
 
 /* Implement targetm.vectorize.builtin_vectorization_cost.  */
 static int
-x86_builtin_vectorization_cost (bool runtime_test)
+ix86_builtin_vectorization_cost (bool runtime_test)
 {
   /* If the branch of the runtime test is taken - i.e. - the vectorized
      version is skipped - this incurs a misprediction cost (because the
@@ -28926,6 +28960,1091 @@ x86_builtin_vectorization_cost (bool runtime_test)
     return 0;
 }
 
+/* Implement targetm.vectorize.builtin_vec_perm.  */
+
+static tree
+ix86_vectorize_builtin_vec_perm (tree vec_type, tree *mask_type)
+{
+  tree itype = TREE_TYPE (vec_type);
+  bool u = TYPE_UNSIGNED (itype);
+  enum ix86_builtins fcode;
+
+  if (!TARGET_SSE2)
+    return NULL_TREE;
+
+  switch (TYPE_MODE (vec_type))
+    {
+    case V2DFmode:
+      itype = ix86_get_builtin_type (IX86_BT_DI);
+      fcode = IX86_BUILTIN_VEC_PERM_V2DF;
+      break;
+    case V4SFmode:
+      itype = ix86_get_builtin_type (IX86_BT_SI);
+      fcode = IX86_BUILTIN_VEC_PERM_V4SF;
+      break;
+    case V2DImode:
+      fcode = u ? IX86_BUILTIN_VEC_PERM_V2DI_U : IX86_BUILTIN_VEC_PERM_V2DI;
+      break;
+    case V4SImode:
+      fcode = u ? IX86_BUILTIN_VEC_PERM_V4SI_U : IX86_BUILTIN_VEC_PERM_V4SI;
+      break;
+    case V8HImode:
+      fcode = u ? IX86_BUILTIN_VEC_PERM_V8HI_U : IX86_BUILTIN_VEC_PERM_V8HI;
+      break;
+    case V16QImode:
+      fcode = u ? IX86_BUILTIN_VEC_PERM_V16QI_U : IX86_BUILTIN_VEC_PERM_V16QI;
+      break;
+    default:
+      return NULL_TREE;
+    }
+
+  *mask_type = itype;
+  return ix86_builtins[(int) fcode];
+}
+
+/* AVX does not support 32-byte integer vector operations,
+   thus the longest vector we are faced with is V16QImode.  */
+#define MAX_VECT_LEN	16
+
+struct expand_vec_perm_d
+{
+  rtx target, op0, op1;
+  unsigned char perm[MAX_VECT_LEN];
+  enum machine_mode vmode;
+  unsigned char nelt;
+  bool testing_p;
+};
+
+/* Return a vector mode with twice as many elements as VMODE.  */
+/* ??? Consider moving this to a table generated by genmodes.c.  */
+
+static enum machine_mode
+doublesize_vector_mode (enum machine_mode vmode)
+{
+  switch (vmode)
+    {
+    case V2SFmode:	return V4SFmode;
+    case V1DImode:	return V2DImode;
+    case V2SImode:	return V4SImode;
+    case V4HImode:	return V8HImode;
+    case V8QImode:	return V16QImode;
+
+    case V2DFmode:	return V4DFmode;
+    case V4SFmode:	return V8SFmode;
+    case V2DImode:	return V4DImode;
+    case V4SImode:	return V8SImode;
+    case V8HImode:	return V16HImode;
+    case V16QImode:	return V32QImode;
+
+    case V4DFmode:	return V8DFmode;
+    case V8SFmode:	return V16SFmode;
+    case V4DImode:	return V8DImode;
+    case V8SImode:	return V16SImode;
+    case V16HImode:	return V32HImode;
+    case V32QImode:	return V64QImode;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Construct (set target (vec_select op0 (parallel perm))) and
+   return true if that's a valid instruction in the active ISA.  */
+
+static bool
+expand_vselect (rtx target, rtx op0, const unsigned char *perm, unsigned nelt)
+{
+  rtx rperm[MAX_VECT_LEN], x;
+  unsigned i;
+
+  for (i = 0; i < nelt; ++i)
+    rperm[i] = GEN_INT (perm[i]);
+
+  x = gen_rtx_PARALLEL (VOIDmode, gen_rtvec_v (nelt, rperm));
+  x = gen_rtx_VEC_SELECT (GET_MODE (target), op0, x);
+  x = gen_rtx_SET (VOIDmode, target, x);
+
+  x = emit_insn (x);
+  if (recog_memoized (x) < 0)
+    {
+      remove_insn (x);
+      return false;
+    }
+  return true;
+}
+
+/* Similar, but generate a vec_concat from op0 and op1 as well.  */
+
+static bool
+expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
+			const unsigned char *perm, unsigned nelt)
+{
+  enum machine_mode v2mode;
+  rtx x;
+
+  v2mode = doublesize_vector_mode (GET_MODE (op0));
+  x = gen_rtx_VEC_CONCAT (v2mode, op0, op1);
+  return expand_vselect (target, x, perm, nelt);
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Try to implement D
+   in terms of blendp[sd] / pblendw / pblendvb.  */
+
+static bool
+expand_vec_perm_blend (struct expand_vec_perm_d *d)
+{
+  enum machine_mode vmode = d->vmode;
+  unsigned i, mask, nelt = d->nelt;
+  rtx target, op0, op1, x;
+
+  if (!TARGET_SSE4_1 || d->op0 == d->op1)
+    return false;
+  if (!(GET_MODE_SIZE (vmode) == 16 || vmode == V4DFmode || vmode == V8SFmode))
+    return false;
+
+  /* This is a blend, not a permute.  Elements must stay in their
+     respective lanes.  */
+  for (i = 0; i < nelt; ++i)
+    {
+      unsigned e = d->perm[i];
+      if (!(e == i || e == i + nelt))
+	return false;
+    }
+
+  if (d->testing_p)
+    return true;
+
+  /* ??? Without SSE4.1, we could implement this with and/andn/or.  This
+     decision should be extracted elsewhere, so that we only try that
+     sequence once all budget==3 options have been tried.  */
+
+  /* For bytes, see if bytes move in pairs so we can use pblendw with
+     an immediate argument, rather than pblendvb with a vector argument.  */
+  if (vmode == V16QImode)
+    {
+      bool pblendw_ok = true;
+      for (i = 0; i < 16 && pblendw_ok; i += 2)
+	pblendw_ok = (d->perm[i] + 1 == d->perm[i + 1]);
+
+      if (!pblendw_ok)
+	{
+	  rtx rperm[16], vperm;
+
+	  for (i = 0; i < nelt; ++i)
+	    rperm[i] = (d->perm[i] < nelt ? const0_rtx : constm1_rtx);
+
+	  vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm));
+	  vperm = force_reg (V16QImode, vperm);
+
+	  emit_insn (gen_sse4_1_pblendvb (d->target, d->op0, d->op1, vperm));
+	  return true;
+	}
+    }
+
+  target = d->target;
+  op0 = d->op0;
+  op1 = d->op1;
+  mask = 0;
+
+  switch (vmode)
+    {
+    case V4DFmode:
+    case V8SFmode:
+    case V2DFmode:
+    case V4SFmode:
+    case V8HImode:
+      for (i = 0; i < nelt; ++i)
+	mask |= (d->perm[i] >= nelt) << i;
+      break;
+
+    case V2DImode:
+      for (i = 0; i < 2; ++i)
+	mask |= (d->perm[i] >= 2 ? 15 : 0) << (i * 4);
+      goto do_subreg;
+
+    case V4SImode:
+      for (i = 0; i < 4; ++i)
+	mask |= (d->perm[i] >= 4 ? 3 : 0) << (i * 2);
+      goto do_subreg;
+
+    case V16QImode:
+      for (i = 0; i < 8; ++i)
+	mask |= (d->perm[i * 2] >= 16) << i;
+
+    do_subreg:
+      vmode = V8HImode;
+      target = gen_lowpart (vmode, target);
+      op0 = gen_lowpart (vmode, target);
+      op1 = gen_lowpart (vmode, target);
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  /* This matches five different patterns with the different modes.  */
+  x = gen_rtx_VEC_MERGE (vmode, op0, op1, GEN_INT (mask));
+  x = gen_rtx_SET (VOIDmode, target, x);
+  emit_insn (x);
+
+  return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Try to implement D
+   in terms of the variable form of vpermilps.
+
+   Note that we will have already failed the immediate input vpermilps,
+   which requires that the high and low part shuffle be identical; the
+   variable form doesn't require that.  */
+
+static bool
+expand_vec_perm_vpermil (struct expand_vec_perm_d *d)
+{
+  rtx rperm[8], vperm;
+  unsigned i;
+
+  if (!TARGET_AVX || d->vmode != V8SFmode || d->op0 != d->op1)
+    return false;
+
+  /* We can only permute within the 128-bit lane.  */
+  for (i = 0; i < 8; ++i)
+    {
+      unsigned e = d->perm[i];
+      if (i < 4 ? e >= 4 : e < 4)
+	return false;
+    }
+
+  if (d->testing_p)
+    return true;
+
+  for (i = 0; i < 8; ++i)
+    {
+      unsigned e = d->perm[i];
+
+      /* Within each 128-bit lane, the elements of op0 are numbered
+	 from 0 and the elements of op1 are numbered from 4.  */
+      if (e >= 8 + 4)
+	e -= 8;
+      else if (e >= 4)
+	e -= 4;
+
+      rperm[i] = GEN_INT (e);
+    }
+
+  vperm = gen_rtx_CONST_VECTOR (V8SImode, gen_rtvec_v (8, rperm));
+  vperm = force_reg (V8SImode, vperm);
+  emit_insn (gen_avx_vpermilvarv8sf3 (d->target, d->op0, vperm));
+
+  return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Try to implement D
+   in terms of pshufb or vpperm.  */
+
+static bool
+expand_vec_perm_pshufb (struct expand_vec_perm_d *d)
+{
+  unsigned i, nelt, eltsz;
+  rtx rperm[16], vperm, target, op0, op1;
+
+  if (!(d->op0 == d->op1 ? TARGET_SSSE3 : TARGET_XOP))
+    return false;
+  if (GET_MODE_SIZE (d->vmode) != 16)
+    return false;
+
+  if (d->testing_p)
+    return true;
+
+  nelt = d->nelt;
+  eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+
+  for (i = 0; i < nelt; ++i)
+    {
+      unsigned j, e = d->perm[i];
+      for (j = 0; j < eltsz; ++j)
+	rperm[i * eltsz + j] = GEN_INT (e * eltsz + j);
+    }
+
+  vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm));
+  vperm = force_reg (V16QImode, vperm);
+
+  target = gen_lowpart (V16QImode, d->target);
+  op0 = gen_lowpart (V16QImode, d->op0);
+  if (d->op0 == d->op1)
+    emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, vperm));
+  else
+    {
+      op1 = gen_lowpart (V16QImode, d->op1);
+      emit_insn (gen_xop_pperm (target, op0, op1, vperm));
+    }
+
+  return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Try to instantiate D
+   in a single instruction.  */
+
+static bool
+expand_vec_perm_1 (struct expand_vec_perm_d *d)
+{
+  unsigned i, nelt = d->nelt;
+  unsigned char perm2[MAX_VECT_LEN];
+
+  /* Check plain VEC_SELECT first, because AVX has instructions that could
+     match both SEL and SEL+CONCAT, but the plain SEL will allow a memory
+     input where SEL+CONCAT may not.  */
+  if (d->op0 == d->op1)
+    {
+      if (expand_vselect (d->target, d->op0, d->perm, nelt))
+	return true;
+
+      /* There are plenty of patterns in sse.md that are written for
+	 SEL+CONCAT and are not replicated for a single op.  Perhaps
+	 that should be changed, to avoid the nastiness here.  */
+
+      /* Recognize interleave style patterns, which means incrementing
+	 every other permutation operand.  */
+      for (i = 0; i < nelt; i += 2)
+	{
+	  perm2[i] = d->perm[i];
+	  perm2[i+1] = d->perm[i+1] + nelt;
+	}
+      if (expand_vselect_vconcat (d->target, d->op0, d->op0, perm2, nelt))
+	return true;
+
+      /* Recognize shufps, which means adding {0, 0, nelt, nelt}.  */
+      if (nelt >= 4)
+	{
+	  memcpy (perm2, d->perm, nelt);
+	  for (i = 2; i < nelt; i += 4)
+	    {
+	      perm2[i+0] += nelt;
+	      perm2[i+1] += nelt;
+	    }
+
+	  if (expand_vselect_vconcat (d->target, d->op0, d->op0, perm2, nelt))
+	    return true;
+	}
+    }
+
+  /* Finally, try the fully general two operand permute.  */
+  if (expand_vselect_vconcat (d->target, d->op0, d->op1, d->perm, nelt))
+    return true;
+
+  /* Recognize interleave style patterns with reversed operands.  */
+  if (d->op0 != d->op1)
+    {
+      for (i = 0; i < nelt; ++i)
+	{
+	  unsigned e = d->perm[i];
+	  if (e >= nelt)
+	    e -= nelt;
+	  else
+	    e += nelt;
+	  perm2[i] = e;
+	}
+
+      if (expand_vselect_vconcat (d->target, d->op1, d->op0, perm2, nelt))
+	return true;
+    }
+
+  /* Try the SSE4.1 blend variable merge instructions.  */
+  if (expand_vec_perm_blend (d))
+    return true;
+
+  /* Try one of the AVX vpermil variable permutations.  */
+  if (expand_vec_perm_vpermil (d))
+    return true;
+
+  /* Try the SSSE3 pshufb or XOP vpperm variable permutation.  */
+  if (expand_vec_perm_pshufb (d))
+    return true;
+
+  return false;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Try to implement D
+   in terms of a pair of pshuflw + pshufhw instructions.  */
+
+static bool
+expand_vec_perm_pshuflw_pshufhw (struct expand_vec_perm_d *d)
+{
+  unsigned char perm2[MAX_VECT_LEN];
+  unsigned i;
+  bool ok;
+
+  if (d->vmode != V8HImode || d->op0 != d->op1)
+    return false;
+
+  /* The two permutations only operate in 64-bit lanes.  */
+  for (i = 0; i < 4; ++i)
+    if (d->perm[i] >= 4)
+      return false;
+  for (i = 4; i < 8; ++i)
+    if (d->perm[i] < 4)
+      return false;
+
+  if (d->testing_p)
+    return true;
+
+  /* Emit the pshuflw.  */
+  memcpy (perm2, d->perm, 4);
+  for (i = 4; i < 8; ++i)
+    perm2[i] = i;
+  ok = expand_vselect (d->target, d->op0, perm2, 8);
+  gcc_assert (ok);
+
+  /* Emit the pshufhw.  */
+  memcpy (perm2 + 4, d->perm + 4, 4);
+  for (i = 0; i < 4; ++i)
+    perm2[i] = i;
+  ok = expand_vselect (d->target, d->target, perm2, 8);
+  gcc_assert (ok);
+
+  return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Try to simplify
+   the permutation using the SSSE3 palignr instruction.  This succeeds
+   when all of the elements in PERM fit within one vector and we merely
+   need to shift them down so that a single vector permutation has a
+   chance to succeed.  */
+
+static bool
+expand_vec_perm_palignr (struct expand_vec_perm_d *d)
+{
+  unsigned i, nelt = d->nelt;
+  unsigned min, max;
+  bool in_order, ok;
+  rtx shift;
+
+  /* Even with AVX, palignr only operates on 128-bit vectors.  */
+  if (!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16)
+    return false;
+
+  min = nelt, max = 0;
+  for (i = 0; i < nelt; ++i)
+    {
+      unsigned e = d->perm[i];
+      if (e < min)
+	min = e;
+      if (e > max)
+	max = e;
+    }
+  if (min == 0 || max - min >= nelt)
+    return false;
+
+  /* Given that we have SSSE3, we know we'll be able to implement the
+     single operand permutation after the palignr with pshufb.  */
+  if (d->testing_p)
+    return true;
+
+  shift = GEN_INT (min * GET_MODE_BITSIZE (GET_MODE_INNER (d->vmode)));
+  emit_insn (gen_ssse3_palignrti (gen_lowpart (TImode, d->target),
+				  gen_lowpart (TImode, d->op1),
+				  gen_lowpart (TImode, d->op0), shift));
+
+  d->op0 = d->op1 = d->target;
+
+  in_order = true;
+  for (i = 0; i < nelt; ++i)
+    {
+      unsigned e = d->perm[i] - min;
+      if (e != i)
+	in_order = false;
+      d->perm[i] = e;
+    }
+
+  /* Test for the degenerate case where the alignment by itself
+     produces the desired permutation.  */
+  if (in_order)
+    return true;
+
+  ok = expand_vec_perm_1 (d);
+  gcc_assert (ok);
+
+  return ok;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Try to simplify
+   a two vector permutation into a single vector permutation by using
+   an interleave operation to merge the vectors.  */
+
+static bool
+expand_vec_perm_interleave2 (struct expand_vec_perm_d *d)
+{
+  struct expand_vec_perm_d dremap, dfinal;
+  unsigned i, nelt = d->nelt, nelt2 = nelt / 2;
+  unsigned contents, h1, h2, h3, h4;
+  unsigned char remap[2 * MAX_VECT_LEN];
+  rtx seq;
+  bool ok;
+
+  if (d->op0 == d->op1)
+    return false;
+
+  /* The 256-bit unpck[lh]p[sd] instructions only operate within the 128-bit
+     lanes.  We can use similar techniques with the vperm2f128 instruction,
+     but it requires slightly different logic.  */
+  if (GET_MODE_SIZE (d->vmode) != 16)
+    return false;
+
+  /* Examine from whence the elements come.  */
+  contents = 0;
+  for (i = 0; i < nelt; ++i)
+    contents |= 1u << d->perm[i];
+
+  /* Split the two input vectors into 4 halves.  */
+  h1 = (1u << nelt2) - 1;
+  h2 = h1 << nelt2;
+  h3 = h2 << nelt2;
+  h4 = h3 << nelt2;
+
+  memset (remap, 0xff, sizeof (remap));
+  dremap = *d;
+
+  /* If the elements from the low halves use interleave low, and similarly
+     for interleave high.  If the elements are from mis-matched halves, we
+     can use shufps for V4SF/V4SI or do a DImode shuffle.  */
+  if ((contents & (h1 | h3)) == contents)
+    {
+      for (i = 0; i < nelt2; ++i)
+	{
+	  remap[i] = i * 2;
+	  remap[i + nelt] = i * 2 + 1;
+	  dremap.perm[i * 2] = i;
+	  dremap.perm[i * 2 + 1] = i + nelt;
+	}
+    }
+  else if ((contents & (h2 | h4)) == contents)
+    {
+      for (i = 0; i < nelt2; ++i)
+	{
+	  remap[i + nelt2] = i * 2;
+	  remap[i + nelt + nelt2] = i * 2 + 1;
+	  dremap.perm[i * 2] = i + nelt2;
+	  dremap.perm[i * 2 + 1] = i + nelt + nelt2;
+	}
+    }
+  else if ((contents & (h1 | h4)) == contents)
+    {
+      for (i = 0; i < nelt2; ++i)
+	{
+	  remap[i] = i;
+	  remap[i + nelt + nelt2] = i + nelt2;
+	  dremap.perm[i] = i;
+	  dremap.perm[i + nelt2] = i + nelt + nelt2;
+	}
+      if (nelt != 4)
+	{
+	  dremap.vmode = V2DImode;
+	  dremap.nelt = 2;
+	  dremap.perm[0] = 0;
+	  dremap.perm[1] = 3;
+	}
+    }
+  else if ((contents & (h2 | h3)) == contents)
+    {
+      for (i = 0; i < nelt2; ++i)
+	{
+	  remap[i + nelt2] = i;
+	  remap[i + nelt] = i + nelt2;
+	  dremap.perm[i] = i + nelt2;
+	  dremap.perm[i + nelt2] = i + nelt;
+	}
+      if (nelt != 4)
+	{
+	  dremap.vmode = V2DImode;
+	  dremap.nelt = 2;
+	  dremap.perm[0] = 1;
+	  dremap.perm[1] = 2;
+	}
+    }
+  else
+    return false;
+
+  /* Use the remapping array set up above to move the elements from their
+     swizzled locations into their final destinations.  */
+  dfinal = *d;
+  for (i = 0; i < nelt; ++i)
+    {
+      unsigned e = remap[d->perm[i]];
+      gcc_assert (e < nelt);
+      dfinal.perm[i] = e;
+    }
+  dfinal.op0 = gen_reg_rtx (dfinal.vmode);
+  dfinal.op1 = dfinal.op0;
+  dremap.target = dfinal.op0;
+
+  /* Test if the final remap can be done with a single insn.  For V4SFmode or
+     V4SImode this *will* succeed.  For V8HImode or V16QImode it may not.  */
+  start_sequence ();
+  ok = expand_vec_perm_1 (&dfinal);
+  seq = get_insns ();
+  end_sequence ();
+
+  if (!ok)
+    return false;
+
+  if (dremap.vmode != dfinal.vmode)
+    {
+      dremap.target = gen_lowpart (dremap.vmode, dremap.target);
+      dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0);
+      dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1);
+    }
+
+  ok = expand_vec_perm_1 (&dremap);
+  gcc_assert (ok);
+
+  emit_insn (seq);
+  return true;
+}
+
+/* A subroutine of expand_vec_perm_even_odd_1.  Implement the double-word
+   permutation with two pshufb insns and an ior.  We should have already
+   failed all two instruction sequences.  */
+
+static bool
+expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d)
+{
+  rtx rperm[2][16], vperm, l, h, op, m128;
+  unsigned int i, nelt, eltsz;
+
+  if (!TARGET_SSSE3)
+    return false;
+
+  nelt = d->nelt;
+  eltsz = GET_MODE_SIZE (GET_MODE_INNER (d->vmode));
+  
+  /* Generate two permutation masks.  If the required element is within
+     the given vector it is shuffled into the proper lane.  If the required
+     element is in the other vector, force a zero into the lane by setting
+     bit 7 in the permutation mask.  */
+  m128 = GEN_INT (-128);
+  for (i = 0; i < nelt; ++i)
+    {
+      unsigned j, e = d->perm[i];
+      unsigned which = (e >= nelt);
+      if (e >= nelt)
+	e -= nelt;
+
+      for (j = 0; j < eltsz; ++j)
+	{
+	  rperm[which][i*eltsz + j] = GEN_INT (e*eltsz + j);
+	  rperm[1-which][i*eltsz + j] = m128;
+	}
+    }
+
+  vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[0]));
+  vperm = force_reg (V16QImode, vperm);
+
+  l = gen_reg_rtx (V16QImode);
+  op = gen_lowpart (V16QImode, d->op0);
+  emit_insn (gen_ssse3_pshufbv16qi3 (l, op, vperm));
+
+  vperm = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, rperm[1]));
+  vperm = force_reg (V16QImode, vperm);
+
+  h = gen_reg_rtx (V16QImode);
+  op = gen_lowpart (V16QImode, d->op1);
+  emit_insn (gen_ssse3_pshufbv16qi3 (h, op, vperm));
+
+  op = gen_lowpart (V16QImode, d->target);
+  emit_insn (gen_iorv16qi3 (op, l, h));
+
+  return true;
+}
+
+/* A subroutine of ix86_expand_vec_perm_builtin_1.  Pattern match
+   extract-even and extract-odd permutations.  */
+
+static bool
+expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd)
+{
+  rtx t1, t2, t3, t4;
+
+  switch (d->vmode)
+    {
+    case V4DFmode:
+      t1 = gen_reg_rtx (V4DFmode);
+      t2 = gen_reg_rtx (V4DFmode);
+
+      /* Shuffle the lanes around into { 0 1 4 5 } and { 2 3 6 7 }.  */
+      emit_insn (gen_avx_vperm2f128v4df3 (t1, d->op0, d->op1, GEN_INT (0x20)));
+      emit_insn (gen_avx_vperm2f128v4df3 (t2, d->op0, d->op1, GEN_INT (0x31)));
+
+      /* Now an unpck[lh]pd will produce the result required.  */
+      if (odd)
+	t3 = gen_avx_unpckhpd256 (d->target, t1, t2);
+      else
+	t3 = gen_avx_unpcklpd256 (d->target, t1, t2);
+      emit_insn (t3);
+      break;
+
+    case V8SFmode:
+      {
+	static const unsigned char perm1[8] = { 0, 2, 1, 3, 5, 6, 5, 7 };
+	static const unsigned char perme[8] = { 0, 1,  8,  9, 4, 5, 12, 13 };
+	static const unsigned char permo[8] = { 2, 3, 10, 11, 6, 7, 14, 15 };
+
+	t1 = gen_reg_rtx (V8SFmode);
+	t2 = gen_reg_rtx (V8SFmode);
+	t3 = gen_reg_rtx (V8SFmode);
+	t4 = gen_reg_rtx (V8SFmode);
+
+	/* Shuffle within the 128-bit lanes to produce:
+	   { 0 2 1 3 4 6 5 7 } and { 8 a 9 b c e d f }.  */
+	expand_vselect (t1, d->op0, perm1, 8);
+	expand_vselect (t2, d->op1, perm1, 8);
+
+	/* Shuffle the lanes around to produce:
+	   { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }.  */
+	emit_insn (gen_avx_vperm2f128v8sf3 (t3, t1, t2, GEN_INT (0x20)));
+	emit_insn (gen_avx_vperm2f128v8sf3 (t4, t1, t2, GEN_INT (0x31)));
+
+	/* Now a vpermil2p will produce the result required.  */
+	/* ??? The vpermil2p requires a vector constant.  Another option
+	   is a unpck[lh]ps to merge the two vectors to produce
+	   { 0 4 2 6 8 c a e } or { 1 5 3 7 9 d b f }.  Then use another
+	   vpermilps to get the elements into the final order.  */
+	d->op0 = t3;
+	d->op1 = t4;
+	memcpy (d->perm, odd ? permo: perme, 8);
+	expand_vec_perm_vpermil (d);
+      }
+      break;
+
+    case V2DFmode:
+    case V4SFmode:
+    case V2DImode:
+    case V4SImode:
+      /* These are always directly implementable by expand_vec_perm_1.  */
+      gcc_unreachable ();
+
+    case V8HImode:
+      if (TARGET_SSSE3)
+	return expand_vec_perm_pshufb2 (d);
+      else
+	{
+	  /* We need 2*log2(N)-1 operations to achieve odd/even
+	     with interleave. */
+	  t1 = gen_reg_rtx (V8HImode);
+	  t2 = gen_reg_rtx (V8HImode);
+	  emit_insn (gen_sse2_punpckhwd (t1, d->op0, d->op1));
+	  emit_insn (gen_sse2_punpcklwd (d->target, d->op0, d->op1));
+	  emit_insn (gen_sse2_punpckhwd (t2, d->target, t1));
+	  emit_insn (gen_sse2_punpcklwd (d->target, d->target, t1));
+	  if (odd)
+	    emit_insn (gen_sse2_punpckhwd (d->target, d->target, t2));
+	  else
+	    emit_insn (gen_sse2_punpcklwd (d->target, d->target, t2));
+	}
+      break;
+
+    case V16QImode:
+      if (TARGET_SSSE3)
+	return expand_vec_perm_pshufb2 (d);
+      else
+	{
+	  t1 = gen_reg_rtx (V16QImode);
+	  t2 = gen_reg_rtx (V16QImode);
+	  t3 = gen_reg_rtx (V16QImode);
+	  emit_insn (gen_sse2_punpckhbw (t1, d->op0, d->op1));
+	  emit_insn (gen_sse2_punpcklbw (d->target, d->op0, d->op1));
+	  emit_insn (gen_sse2_punpckhbw (t2, d->target, t1));
+	  emit_insn (gen_sse2_punpcklbw (d->target, d->target, t1));
+	  emit_insn (gen_sse2_punpckhbw (t3, d->target, t2));
+	  emit_insn (gen_sse2_punpcklbw (d->target, d->target, t2));
+	  if (odd)
+	    emit_insn (gen_sse2_punpckhbw (d->target, d->target, t3));
+	  else
+	    emit_insn (gen_sse2_punpcklbw (d->target, d->target, t3));
+	}
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  return true;
+}
+
+static bool
+expand_vec_perm_even_odd (struct expand_vec_perm_d *d)
+{
+  unsigned i, odd, nelt = d->nelt;
+
+  odd = d->perm[0];
+  if (odd != 0 && odd != 1)
+    return false;
+
+  for (i = 1; i < nelt; ++i)
+    if (d->perm[i] != 2 * i + odd)
+      return false;
+
+  return expand_vec_perm_even_odd_1 (d, odd);
+}
+
+/* The guts of ix86_expand_vec_perm_builtin, also used by the ok hook.
+   With all of the interface bits taken care of, perform the expansion
+   in D and return true on success.  */
+
+static bool
+ix86_expand_vec_perm_builtin_1 (struct expand_vec_perm_d *d)
+{
+  /* First things first -- check if the instruction is implementable
+     with a single instruction.  */
+  if (expand_vec_perm_1 (d))
+    return true;
+
+  /* Try sequences of two instructions.  */
+
+  if (expand_vec_perm_pshuflw_pshufhw (d))
+    return true;
+
+  if (expand_vec_perm_palignr (d))
+    return true;
+
+  if (expand_vec_perm_interleave2 (d))
+    return true;
+
+  /* Try sequences of three instructions.  */
+
+  if (expand_vec_perm_pshufb2 (d))
+    return true;
+
+  /* ??? Look for narrow permutations whose element orderings would
+     allow the promition to a wider mode.  */
+
+  /* ??? Look for sequences of interleave or a wider permute that place
+     the data into the correct lanes for a half-vector shuffle like
+     pshuf[lh]w or vpermilps.  */
+
+  /* ??? Look for sequences of interleave that produce the desired results.
+     The combinatorics of punpck[lh] get pretty ugly... */
+
+  if (expand_vec_perm_even_odd (d))
+    return true;
+
+  /* ??? Pattern match broadcast.  */
+
+  return false;
+}
+
+/* Extract the values from the vector CST into the permutation array in D.
+   Return 0 on error, 1 if all values from the permutation come from the
+   first vector, 2 if all values from the second vector, and 3 otherwise.  */
+
+static int
+extract_vec_perm_cst (struct expand_vec_perm_d *d, tree cst)
+{
+  tree list = TREE_VECTOR_CST_ELTS (cst);
+  unsigned i, nelt = d->nelt;
+  int ret = 0;
+
+  for (i = 0; i < nelt; ++i, list = TREE_CHAIN (list))
+    {
+      unsigned HOST_WIDE_INT e;
+
+      if (!host_integerp (TREE_VALUE (list), 1))
+	return 0;
+      e = tree_low_cst (TREE_VALUE (list), 1);
+      if (e >= 2 * nelt)
+	return 0;
+
+      ret |= (e < nelt ? 1 : 2);
+      d->perm[i] = e;
+    }
+  gcc_assert (list == NULL);
+
+  /* For all elements from second vector, fold the elements to first.  */
+  if (ret == 2)
+    for (i = 0; i < nelt; ++i)
+      d->perm[i] -= nelt;
+
+  return ret;
+}
+
+static rtx
+ix86_expand_vec_perm_builtin (tree exp)
+{
+  struct expand_vec_perm_d d;
+  tree arg0, arg1, arg2;
+
+  arg0 = CALL_EXPR_ARG (exp, 0);
+  arg1 = CALL_EXPR_ARG (exp, 1);
+  arg2 = CALL_EXPR_ARG (exp, 2);
+
+  d.vmode = TYPE_MODE (TREE_TYPE (arg0));
+  d.nelt = GET_MODE_NUNITS (d.vmode);
+  d.testing_p = false;
+  gcc_assert (VECTOR_MODE_P (d.vmode));
+
+  if (TREE_CODE (arg2) != VECTOR_CST)
+    {
+      error_at (EXPR_LOCATION (exp),
+		"vector permutation requires vector constant");
+      goto exit_error;
+    }
+
+  switch (extract_vec_perm_cst (&d, arg2))
+    {
+    default:
+      gcc_unreachable();
+
+    case 0:
+      error_at (EXPR_LOCATION (exp), "invalid vector permutation constant");
+      goto exit_error;
+
+    case 3:
+      if (!operand_equal_p (arg0, arg1, 0))
+	{
+	  d.op0 = expand_expr (arg0, NULL_RTX, d.vmode, EXPAND_NORMAL);
+	  d.op0 = force_reg (d.vmode, d.op0);
+	  d.op1 = expand_expr (arg1, NULL_RTX, d.vmode, EXPAND_NORMAL);
+	  d.op1 = force_reg (d.vmode, d.op1);
+	  break;
+	}
+
+      /* The elements of PERM do not suggest that only the first operand
+	 is used, but both operands are identical.  Allow easier matching
+	 of the permutation by folding the permutation into the single
+	 input vector.  */
+      {
+	unsigned i, nelt = d.nelt;
+	for (i = 0; i < nelt; ++i)
+	  if (d.perm[i] >= nelt)
+	    d.perm[i] -= nelt;
+      }
+      /* FALLTHRU */
+
+    case 1:
+      d.op0 = expand_expr (arg0, NULL_RTX, d.vmode, EXPAND_NORMAL);
+      d.op0 = force_reg (d.vmode, d.op0);
+      d.op1 = d.op0;
+      break;
+
+    case 2:
+      d.op0 = expand_expr (arg1, NULL_RTX, d.vmode, EXPAND_NORMAL);
+      d.op0 = force_reg (d.vmode, d.op0);
+      d.op1 = d.op0;
+      break;
+    }
+ 
+  d.target = gen_reg_rtx (d.vmode);
+  if (ix86_expand_vec_perm_builtin_1 (&d))
+    return d.target;
+
+  /* For compiler generated permutations, we should never got here, because
+     the compiler should also be checking the ok hook.  But since this is a
+     builtin the user has access too, so don't abort.  */
+  switch (d.nelt)
+    {
+    case 2:
+      sorry ("vector permutation (%d %d)", d.perm[0], d.perm[1]);
+      break;
+    case 4:
+      sorry ("vector permutation (%d %d %d %d)",
+	     d.perm[0], d.perm[1], d.perm[2], d.perm[3]);
+      break;
+    case 8:
+      sorry ("vector permutation (%d %d %d %d %d %d %d %d)",
+	     d.perm[0], d.perm[1], d.perm[2], d.perm[3],
+	     d.perm[4], d.perm[5], d.perm[6], d.perm[7]);
+      break;
+    case 16:
+      sorry ("vector permutation "
+	     "(%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d)",
+	     d.perm[0], d.perm[1], d.perm[2], d.perm[3],
+	     d.perm[4], d.perm[5], d.perm[6], d.perm[7],
+	     d.perm[8], d.perm[9], d.perm[10], d.perm[11],
+	     d.perm[12], d.perm[13], d.perm[14], d.perm[15]);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+ exit_error:
+  return CONST0_RTX (d.vmode);
+}
+
+/* Implement targetm.vectorize.builtin_vec_perm_ok.  */
+
+static bool
+ix86_vectorize_builtin_vec_perm_ok (tree vec_type, tree mask)
+{
+  struct expand_vec_perm_d d;
+  int vec_mask;
+  bool ret, one_vec;
+
+  d.vmode = TYPE_MODE (vec_type);
+  d.nelt = GET_MODE_NUNITS (d.vmode);
+  d.testing_p = true;
+
+  /* Given sufficient ISA support we can just return true here
+     for selected vector modes.  */
+  if (GET_MODE_SIZE (d.vmode) == 16)
+    {
+      /* All implementable with a single vpperm insn.  */
+      if (TARGET_XOP)
+	return true;
+      /* All implementable with 2 pshufb + 1 ior.  */
+      if (TARGET_SSSE3)
+	return true;
+      /* All implementable with shufpd or unpck[lh]pd.  */
+      if (d.nelt == 2)
+	return true;
+    }
+
+  vec_mask = extract_vec_perm_cst (&d, mask);
+
+  /* This hook is cannot be called in response to something that the
+     user does (unlike the builtin expander) so we shouldn't ever see
+     an error generated from the extract.  */
+  gcc_assert (vec_mask > 0 && vec_mask <= 3);
+  one_vec = (vec_mask != 3);
+  
+  /* Implementable with shufps or pshufd.  */
+  if (one_vec && (d.vmode == V4SFmode || d.vmode == V4SImode))
+    return true;
+
+  /* Otherwise we have to go through the motions and see if we can
+     figure out how to generate the requested permutation.  */
+  d.target = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 1);
+  d.op1 = d.op0 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 2);
+  if (!one_vec)
+    d.op1 = gen_raw_REG (d.vmode, LAST_VIRTUAL_REGISTER + 3);
+
+  start_sequence ();
+  ret = ix86_expand_vec_perm_builtin_1 (&d);
+  end_sequence ();
+
+  return ret;
+}
+
+void
+ix86_expand_vec_extract_even_odd (rtx targ, rtx op0, rtx op1, unsigned odd)
+{
+  struct expand_vec_perm_d d;
+  unsigned i, nelt;
+
+  d.target = targ;
+  d.op0 = op0;
+  d.op1 = op1;
+  d.vmode = GET_MODE (targ);
+  d.nelt = nelt = GET_MODE_NUNITS (d.vmode);
+  d.testing_p = false;
+
+  for (i = 0; i < nelt; ++i)
+    d.perm[i] = i * 2 + odd;
+
+  /* We'll either be able to implement the permutation directly...  */
+  if (expand_vec_perm_1 (&d))
+    return;
+
+  /* ... or we use the special-case patterns.  */
+  expand_vec_perm_even_odd_1 (&d, odd);
+}
+\f
 /* This function returns the calling abi specific va_list type node.
    It returns  the FNDECL specific va_list type.  */
 
@@ -29254,7 +30373,14 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree)
 #define TARGET_SECONDARY_RELOAD ix86_secondary_reload
 
 #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
-#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST x86_builtin_vectorization_cost
+#define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST \
+  ix86_builtin_vectorization_cost
+#undef TARGET_VECTORIZE_BUILTIN_VEC_PERM
+#define TARGET_VECTORIZE_BUILTIN_VEC_PERM \
+  ix86_vectorize_builtin_vec_perm
+#undef TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK
+#define TARGET_VECTORIZE_BUILTIN_VEC_PERM_OK \
+  ix86_vectorize_builtin_vec_perm_ok
 
 #undef TARGET_SET_CURRENT_FUNCTION
 #define TARGET_SET_CURRENT_FUNCTION ix86_set_current_function
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 8661b4a..b4bcc5f 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -71,6 +71,14 @@
 (define_mode_iterator SSEMODE124C8 [V16QI V8HI V4SI
 				    (V2DI "TARGET_SSE4_2")])
 
+;; Modes handled by vec_extract_even/odd pattern.
+(define_mode_iterator SSEMODE_EO
+  [(V4SF "TARGET_SSE")
+   (V2DF "TARGET_SSE2")
+   (V2DI "TARGET_SSE2") (V4SI "TARGET_SSE2")
+   (V8HI "TARGET_SSE2") (V16QI "TARGET_SSE2")
+   (V4DF "TARGET_AVX") (V8SF "TARGET_AVX")])
+
 ;; Mapping from float mode to required SSE level
 (define_mode_attr sse [(SF "sse") (DF "sse2") (V4SF "sse") (V2DF "sse2")])
 
@@ -4693,48 +4701,24 @@
 })
 
 (define_expand "vec_extract_even<mode>"
-  [(set (match_operand:SSEMODE4S 0 "register_operand" "")
-	(vec_select:SSEMODE4S
-	  (vec_concat:<ssedoublesizemode>
-	    (match_operand:SSEMODE4S 1 "register_operand" "")
-	    (match_operand:SSEMODE4S 2 "nonimmediate_operand" ""))
-	  (parallel [(const_int 0)
-		     (const_int 2)
-		     (const_int 4)
-		     (const_int 6)])))]
-  "TARGET_SSE")
-
-(define_expand "vec_extract_odd<mode>"
-  [(set (match_operand:SSEMODE4S 0 "register_operand" "")
-	(vec_select:SSEMODE4S
-	  (vec_concat:<ssedoublesizemode>
-	    (match_operand:SSEMODE4S 1 "register_operand" "")
-	    (match_operand:SSEMODE4S 2 "nonimmediate_operand" ""))
-	  (parallel [(const_int 1)
-		     (const_int 3)
-		     (const_int 5)
-		     (const_int 7)])))]
-  "TARGET_SSE")
-
-(define_expand "vec_extract_even<mode>"
-  [(set (match_operand:SSEMODE2D 0 "register_operand" "")
-	(vec_select:SSEMODE2D
-	  (vec_concat:<ssedoublesizemode>
-	    (match_operand:SSEMODE2D 1 "register_operand" "")
-	    (match_operand:SSEMODE2D 2 "nonimmediate_operand" ""))
-	  (parallel [(const_int 0)
-	  	     (const_int 2)])))]
-  "TARGET_SSE2")
+  [(match_operand:SSEMODE_EO 0 "register_operand" "")
+   (match_operand:SSEMODE_EO 1 "register_operand" "")
+   (match_operand:SSEMODE_EO 2 "register_operand" "")]
+  ""
+{
+  ix86_expand_vec_extract_even_odd (operands[0], operands[1], operands[2], 0);
+  DONE;
+})
 
 (define_expand "vec_extract_odd<mode>"
-  [(set (match_operand:SSEMODE2D 0 "register_operand" "")
-	(vec_select:SSEMODE2D
-	  (vec_concat:<ssedoublesizemode>
-	    (match_operand:SSEMODE2D 1 "register_operand" "")
-	    (match_operand:SSEMODE2D 2 "nonimmediate_operand" ""))
-	  (parallel [(const_int 1)
-	  	     (const_int 3)])))]
-  "TARGET_SSE2")
+  [(match_operand:SSEMODE_EO 0 "register_operand" "")
+   (match_operand:SSEMODE_EO 1 "register_operand" "")
+   (match_operand:SSEMODE_EO 2 "register_operand" "")]
+  ""
+{
+  ix86_expand_vec_extract_even_odd (operands[0], operands[1], operands[2], 1);
+  DONE;
+})
 
 ;; punpcklqdq and punpckhqdq are shorter than shufpd.
 (define_insn "*avx_punpckhqdq"
@@ -5243,20 +5227,16 @@
    (set_attr "prefix_data16" "1")
    (set_attr "mode" "TI")])
 
-(define_insn_and_split "mulv16qi3"
+(define_expand "mulv16qi3"
   [(set (match_operand:V16QI 0 "register_operand" "")
 	(mult:V16QI (match_operand:V16QI 1 "register_operand" "")
 		    (match_operand:V16QI 2 "register_operand" "")))]
-  "TARGET_SSE2
-   && can_create_pseudo_p ()"
-  "#"
-  "&& 1"
-  [(const_int 0)]
+  "TARGET_SSE2"
 {
-  rtx t[12];
+  rtx t[6];
   int i;
 
-  for (i = 0; i < 12; ++i)
+  for (i = 0; i < 6; ++i)
     t[i] = gen_reg_rtx (V16QImode);
 
   /* Unpack data such that we've got a source byte in each low byte of
@@ -5278,15 +5258,8 @@
 			   gen_lowpart (V8HImode, t[2]),
 			   gen_lowpart (V8HImode, t[3])));
 
-  /* Extract the relevant bytes and merge them back together.  */
-  emit_insn (gen_sse2_punpckhbw (t[6], t[5], t[4]));	/* ..AI..BJ..CK..DL */
-  emit_insn (gen_sse2_punpcklbw (t[7], t[5], t[4]));	/* ..EM..FN..GO..HP */
-  emit_insn (gen_sse2_punpckhbw (t[8], t[7], t[6]));	/* ....AEIM....BFJN */
-  emit_insn (gen_sse2_punpcklbw (t[9], t[7], t[6]));	/* ....CGKO....DHLP */
-  emit_insn (gen_sse2_punpckhbw (t[10], t[9], t[8]));	/* ........ACEGIKMO */
-  emit_insn (gen_sse2_punpcklbw (t[11], t[9], t[8]));	/* ........BDFHJLNP */
-
-  emit_insn (gen_sse2_punpcklbw (operands[0], t[11], t[10]));	/* ABCDEFGHIJKLMNOP */
+  /* Extract the even bytes and merge them back together.  */
+  ix86_expand_vec_extract_even_odd (operands[0], t[5], t[4], 0);
   DONE;
 })
 
@@ -6578,96 +6551,39 @@
 ;;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-;; Reduce:
-;;      op1 = abcdefghijklmnop
-;;      op2 = qrstuvwxyz012345
-;;       h1 = aqbrcsdteufvgwhx
-;;       l1 = iyjzk0l1m2n3o4p5
-;;       h2 = aiqybjrzcks0dlt1
-;;       l2 = emu2fnv3gow4hpx5
-;;       h3 = aeimquy2bfjnrvz3
-;;       l3 = cgkosw04dhlptx15
-;;   result = bdfhjlnprtvxz135
 (define_expand "vec_pack_trunc_v8hi"
   [(match_operand:V16QI 0 "register_operand" "")
    (match_operand:V8HI 1 "register_operand" "")
    (match_operand:V8HI 2 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx op1, op2, h1, l1, h2, l2, h3, l3;
-
-  op1 = gen_lowpart (V16QImode, operands[1]);
-  op2 = gen_lowpart (V16QImode, operands[2]);
-  h1 = gen_reg_rtx (V16QImode);
-  l1 = gen_reg_rtx (V16QImode);
-  h2 = gen_reg_rtx (V16QImode);
-  l2 = gen_reg_rtx (V16QImode);
-  h3 = gen_reg_rtx (V16QImode);
-  l3 = gen_reg_rtx (V16QImode);
-
-  emit_insn (gen_vec_interleave_highv16qi (h1, op1, op2));
-  emit_insn (gen_vec_interleave_lowv16qi (l1, op1, op2));
-  emit_insn (gen_vec_interleave_highv16qi (h2, l1, h1));
-  emit_insn (gen_vec_interleave_lowv16qi (l2, l1, h1));
-  emit_insn (gen_vec_interleave_highv16qi (h3, l2, h2));
-  emit_insn (gen_vec_interleave_lowv16qi (l3, l2, h2));
-  emit_insn (gen_vec_interleave_lowv16qi (operands[0], l3, h3));
+  rtx op1 = gen_lowpart (V16QImode, operands[1]);
+  rtx op2 = gen_lowpart (V16QImode, operands[2]);
+  ix86_expand_vec_extract_even_odd (operands[0], op1, op2, 0);
   DONE;
 })
 
-;; Reduce:
-;;      op1 = abcdefgh
-;;      op2 = ijklmnop
-;;       h1 = aibjckdl
-;;       l1 = emfngohp
-;;       h2 = aeimbfjn
-;;       l2 = cgkodhlp
-;;   result = bdfhjlnp
 (define_expand "vec_pack_trunc_v4si"
   [(match_operand:V8HI 0 "register_operand" "")
    (match_operand:V4SI 1 "register_operand" "")
    (match_operand:V4SI 2 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx op1, op2, h1, l1, h2, l2;
-
-  op1 = gen_lowpart (V8HImode, operands[1]);
-  op2 = gen_lowpart (V8HImode, operands[2]);
-  h1 = gen_reg_rtx (V8HImode);
-  l1 = gen_reg_rtx (V8HImode);
-  h2 = gen_reg_rtx (V8HImode);
-  l2 = gen_reg_rtx (V8HImode);
-
-  emit_insn (gen_vec_interleave_highv8hi (h1, op1, op2));
-  emit_insn (gen_vec_interleave_lowv8hi (l1, op1, op2));
-  emit_insn (gen_vec_interleave_highv8hi (h2, l1, h1));
-  emit_insn (gen_vec_interleave_lowv8hi (l2, l1, h1));
-  emit_insn (gen_vec_interleave_lowv8hi (operands[0], l2, h2));
+  rtx op1 = gen_lowpart (V8HImode, operands[1]);
+  rtx op2 = gen_lowpart (V8HImode, operands[2]);
+  ix86_expand_vec_extract_even_odd (operands[0], op1, op2, 0);
   DONE;
 })
 
-;; Reduce:
-;;     op1 = abcd
-;;     op2 = efgh
-;;      h1 = aebf
-;;      l1 = cgdh
-;;  result = bdfh
 (define_expand "vec_pack_trunc_v2di"
   [(match_operand:V4SI 0 "register_operand" "")
    (match_operand:V2DI 1 "register_operand" "")
    (match_operand:V2DI 2 "register_operand" "")]
   "TARGET_SSE2"
 {
-  rtx op1, op2, h1, l1;
-
-  op1 = gen_lowpart (V4SImode, operands[1]);
-  op2 = gen_lowpart (V4SImode, operands[2]);
-  h1 = gen_reg_rtx (V4SImode);
-  l1 = gen_reg_rtx (V4SImode);
-
-  emit_insn (gen_vec_interleave_highv4si (h1, op1, op2));
-  emit_insn (gen_vec_interleave_lowv4si (l1, op1, op2));
-  emit_insn (gen_vec_interleave_lowv4si (operands[0], l1, h1));
+  rtx op1 = gen_lowpart (V4SImode, operands[1]);
+  rtx op2 = gen_lowpart (V4SImode, operands[2]);
+  ix86_expand_vec_extract_even_odd (operands[0], op1, op2, 0);
   DONE;
 })
 
diff --git a/gcc/testsuite/gcc.dg/vect/slp-21.c b/gcc/testsuite/gcc.dg/vect/slp-21.c
index 327045e..182ad49 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-21.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-21.c
@@ -200,8 +200,8 @@ int main (void)
   return 0;
 }
 
-/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect"  { target vect_strided } } } */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect"  { target  { ! { vect_strided } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 4 loops" 1 "vect"  { target { vect_strided || vect_extract_even_odd } } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect"  { target  { ! { vect_strided || vect_extract_even_odd } } } } } */
 /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "vect" { target vect_strided }  } } */
 /* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 0 "vect"  { target { ! { vect_strided } } } } } */
 /* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.target/i386/isa-check.h b/gcc/testsuite/gcc.target/i386/isa-check.h
new file mode 100644
index 0000000..8ddbf4d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/isa-check.h
@@ -0,0 +1,85 @@
+#include "cpuid.h"
+
+extern void exit (int) __attribute__((noreturn));
+
+/* Determine what instruction set we've been compiled for,
+   and detect that we're running with it.  */
+static void __attribute__((constructor))
+check_isa (void)
+{
+  int a, b, c, d;
+  int c1, d1, c1e, d1e;
+
+  c1 = d1 = c1e = d1e = 0;
+
+#ifdef __MMX__
+  d1 |= bit_MMX;
+#endif
+#ifdef __3dNOW__
+  d1e |= bit_3DNOW;
+#endif
+#ifdef __3dNOW_A__
+  d1e |= bit_3DNOWP;
+#endif
+#ifdef __SSE__
+  d1 |= bit_SSE;
+#endif
+#ifdef __SSE2__
+  d1 |= bit_SSE2;
+#endif
+#ifdef __SSE3__
+  c1 |= bit_SSE3;
+#endif
+#ifdef __SSSE3__
+  c1 |= bit_SSSE3;
+#endif
+#ifdef __SSE4_1__
+  c1 |= bit_SSE4_1;
+#endif
+#ifdef __SSE4_2__
+  c1 |= bit_SSE4_2;
+#endif
+#ifdef __AES__
+  c1 |= bit_AES;
+#endif
+#ifdef __PCLMUL__
+  c1 |= bit_PCLMUL;
+#endif
+#ifdef __AVX__
+  c1 |= bit_AVX;
+#endif
+#ifdef __FMA__
+  c1 |= bit_FMA;
+#endif
+#ifdef __SSE4A__
+  c1e |= bit_SSE4a;
+#endif
+#ifdef __FMA4__
+  c1e |= bit_FMA4;
+#endif
+#ifdef __XOP__
+  c1e |= bit_XOP;
+#endif
+#ifdef __LWP__
+  c1e |= bit_LWP;
+#endif
+
+  if (c1 | d1)
+    {
+      if (!__get_cpuid (1, &a, &b, &c, &d))
+	goto fail;
+      if ((c & c1) != c1 || (d & d1) != d1)
+	goto fail;
+    }
+  if (c1e | d1e)
+    {
+      if (!__get_cpuid (0x80000001, &a, &b, &c, &d))
+	goto fail;
+      if ((c & c1e) != c1e || (d & d1e) != d1e)
+	goto fail;
+    }
+  return;
+
+ fail:
+  exit (0);
+}
diff --git a/gcc/testsuite/gcc.target/i386/vperm-2-2.inc b/gcc/testsuite/gcc.target/i386/vperm-2-2.inc
new file mode 100644
index 0000000..ef66f68
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-2-2.inc
@@ -0,0 +1,27 @@
+/* This file auto-generated with ./vperm.pl 2 2.  */
+
+void check0(void)
+{
+  TEST (0, 0)
+  TEST (1, 0)
+  TEST (2, 0)
+  TEST (3, 0)
+  TEST (0, 1)
+  TEST (1, 1)
+  TEST (2, 1)
+  TEST (3, 1)
+  TEST (0, 2)
+  TEST (1, 2)
+  TEST (2, 2)
+  TEST (3, 2)
+  TEST (0, 3)
+  TEST (1, 3)
+  TEST (2, 3)
+  TEST (3, 3)
+}
+
+void check(void)
+{
+  check0 ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/vperm-4-1.inc b/gcc/testsuite/gcc.target/i386/vperm-4-1.inc
new file mode 100644
index 0000000..c04f185
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-4-1.inc
@@ -0,0 +1,272 @@
+/* This file auto-generated with ./vperm.pl 4 1.  */
+
+void check0(void)
+{
+  TEST (0, 0, 0, 0)
+  TEST (1, 0, 0, 0)
+  TEST (2, 0, 0, 0)
+  TEST (3, 0, 0, 0)
+  TEST (0, 1, 0, 0)
+  TEST (1, 1, 0, 0)
+  TEST (2, 1, 0, 0)
+  TEST (3, 1, 0, 0)
+  TEST (0, 2, 0, 0)
+  TEST (1, 2, 0, 0)
+  TEST (2, 2, 0, 0)
+  TEST (3, 2, 0, 0)
+  TEST (0, 3, 0, 0)
+  TEST (1, 3, 0, 0)
+  TEST (2, 3, 0, 0)
+  TEST (3, 3, 0, 0)
+  TEST (0, 0, 1, 0)
+  TEST (1, 0, 1, 0)
+  TEST (2, 0, 1, 0)
+  TEST (3, 0, 1, 0)
+  TEST (0, 1, 1, 0)
+  TEST (1, 1, 1, 0)
+  TEST (2, 1, 1, 0)
+  TEST (3, 1, 1, 0)
+  TEST (0, 2, 1, 0)
+  TEST (1, 2, 1, 0)
+  TEST (2, 2, 1, 0)
+  TEST (3, 2, 1, 0)
+  TEST (0, 3, 1, 0)
+  TEST (1, 3, 1, 0)
+  TEST (2, 3, 1, 0)
+  TEST (3, 3, 1, 0)
+  TEST (0, 0, 2, 0)
+  TEST (1, 0, 2, 0)
+  TEST (2, 0, 2, 0)
+  TEST (3, 0, 2, 0)
+  TEST (0, 1, 2, 0)
+  TEST (1, 1, 2, 0)
+  TEST (2, 1, 2, 0)
+  TEST (3, 1, 2, 0)
+  TEST (0, 2, 2, 0)
+  TEST (1, 2, 2, 0)
+  TEST (2, 2, 2, 0)
+  TEST (3, 2, 2, 0)
+  TEST (0, 3, 2, 0)
+  TEST (1, 3, 2, 0)
+  TEST (2, 3, 2, 0)
+  TEST (3, 3, 2, 0)
+  TEST (0, 0, 3, 0)
+  TEST (1, 0, 3, 0)
+  TEST (2, 0, 3, 0)
+  TEST (3, 0, 3, 0)
+  TEST (0, 1, 3, 0)
+  TEST (1, 1, 3, 0)
+  TEST (2, 1, 3, 0)
+  TEST (3, 1, 3, 0)
+  TEST (0, 2, 3, 0)
+  TEST (1, 2, 3, 0)
+  TEST (2, 2, 3, 0)
+  TEST (3, 2, 3, 0)
+  TEST (0, 3, 3, 0)
+  TEST (1, 3, 3, 0)
+  TEST (2, 3, 3, 0)
+  TEST (3, 3, 3, 0)
+  TEST (0, 0, 0, 1)
+  TEST (1, 0, 0, 1)
+  TEST (2, 0, 0, 1)
+  TEST (3, 0, 0, 1)
+  TEST (0, 1, 0, 1)
+  TEST (1, 1, 0, 1)
+  TEST (2, 1, 0, 1)
+  TEST (3, 1, 0, 1)
+  TEST (0, 2, 0, 1)
+  TEST (1, 2, 0, 1)
+  TEST (2, 2, 0, 1)
+  TEST (3, 2, 0, 1)
+  TEST (0, 3, 0, 1)
+  TEST (1, 3, 0, 1)
+  TEST (2, 3, 0, 1)
+  TEST (3, 3, 0, 1)
+  TEST (0, 0, 1, 1)
+  TEST (1, 0, 1, 1)
+  TEST (2, 0, 1, 1)
+  TEST (3, 0, 1, 1)
+  TEST (0, 1, 1, 1)
+  TEST (1, 1, 1, 1)
+  TEST (2, 1, 1, 1)
+  TEST (3, 1, 1, 1)
+  TEST (0, 2, 1, 1)
+  TEST (1, 2, 1, 1)
+  TEST (2, 2, 1, 1)
+  TEST (3, 2, 1, 1)
+  TEST (0, 3, 1, 1)
+  TEST (1, 3, 1, 1)
+  TEST (2, 3, 1, 1)
+  TEST (3, 3, 1, 1)
+  TEST (0, 0, 2, 1)
+  TEST (1, 0, 2, 1)
+  TEST (2, 0, 2, 1)
+  TEST (3, 0, 2, 1)
+  TEST (0, 1, 2, 1)
+  TEST (1, 1, 2, 1)
+  TEST (2, 1, 2, 1)
+  TEST (3, 1, 2, 1)
+  TEST (0, 2, 2, 1)
+  TEST (1, 2, 2, 1)
+  TEST (2, 2, 2, 1)
+  TEST (3, 2, 2, 1)
+  TEST (0, 3, 2, 1)
+  TEST (1, 3, 2, 1)
+  TEST (2, 3, 2, 1)
+  TEST (3, 3, 2, 1)
+  TEST (0, 0, 3, 1)
+  TEST (1, 0, 3, 1)
+  TEST (2, 0, 3, 1)
+  TEST (3, 0, 3, 1)
+  TEST (0, 1, 3, 1)
+  TEST (1, 1, 3, 1)
+  TEST (2, 1, 3, 1)
+  TEST (3, 1, 3, 1)
+  TEST (0, 2, 3, 1)
+  TEST (1, 2, 3, 1)
+  TEST (2, 2, 3, 1)
+  TEST (3, 2, 3, 1)
+  TEST (0, 3, 3, 1)
+  TEST (1, 3, 3, 1)
+  TEST (2, 3, 3, 1)
+  TEST (3, 3, 3, 1)
+}
+
+void check1(void)
+{
+  TEST (0, 0, 0, 2)
+  TEST (1, 0, 0, 2)
+  TEST (2, 0, 0, 2)
+  TEST (3, 0, 0, 2)
+  TEST (0, 1, 0, 2)
+  TEST (1, 1, 0, 2)
+  TEST (2, 1, 0, 2)
+  TEST (3, 1, 0, 2)
+  TEST (0, 2, 0, 2)
+  TEST (1, 2, 0, 2)
+  TEST (2, 2, 0, 2)
+  TEST (3, 2, 0, 2)
+  TEST (0, 3, 0, 2)
+  TEST (1, 3, 0, 2)
+  TEST (2, 3, 0, 2)
+  TEST (3, 3, 0, 2)
+  TEST (0, 0, 1, 2)
+  TEST (1, 0, 1, 2)
+  TEST (2, 0, 1, 2)
+  TEST (3, 0, 1, 2)
+  TEST (0, 1, 1, 2)
+  TEST (1, 1, 1, 2)
+  TEST (2, 1, 1, 2)
+  TEST (3, 1, 1, 2)
+  TEST (0, 2, 1, 2)
+  TEST (1, 2, 1, 2)
+  TEST (2, 2, 1, 2)
+  TEST (3, 2, 1, 2)
+  TEST (0, 3, 1, 2)
+  TEST (1, 3, 1, 2)
+  TEST (2, 3, 1, 2)
+  TEST (3, 3, 1, 2)
+  TEST (0, 0, 2, 2)
+  TEST (1, 0, 2, 2)
+  TEST (2, 0, 2, 2)
+  TEST (3, 0, 2, 2)
+  TEST (0, 1, 2, 2)
+  TEST (1, 1, 2, 2)
+  TEST (2, 1, 2, 2)
+  TEST (3, 1, 2, 2)
+  TEST (0, 2, 2, 2)
+  TEST (1, 2, 2, 2)
+  TEST (2, 2, 2, 2)
+  TEST (3, 2, 2, 2)
+  TEST (0, 3, 2, 2)
+  TEST (1, 3, 2, 2)
+  TEST (2, 3, 2, 2)
+  TEST (3, 3, 2, 2)
+  TEST (0, 0, 3, 2)
+  TEST (1, 0, 3, 2)
+  TEST (2, 0, 3, 2)
+  TEST (3, 0, 3, 2)
+  TEST (0, 1, 3, 2)
+  TEST (1, 1, 3, 2)
+  TEST (2, 1, 3, 2)
+  TEST (3, 1, 3, 2)
+  TEST (0, 2, 3, 2)
+  TEST (1, 2, 3, 2)
+  TEST (2, 2, 3, 2)
+  TEST (3, 2, 3, 2)
+  TEST (0, 3, 3, 2)
+  TEST (1, 3, 3, 2)
+  TEST (2, 3, 3, 2)
+  TEST (3, 3, 3, 2)
+  TEST (0, 0, 0, 3)
+  TEST (1, 0, 0, 3)
+  TEST (2, 0, 0, 3)
+  TEST (3, 0, 0, 3)
+  TEST (0, 1, 0, 3)
+  TEST (1, 1, 0, 3)
+  TEST (2, 1, 0, 3)
+  TEST (3, 1, 0, 3)
+  TEST (0, 2, 0, 3)
+  TEST (1, 2, 0, 3)
+  TEST (2, 2, 0, 3)
+  TEST (3, 2, 0, 3)
+  TEST (0, 3, 0, 3)
+  TEST (1, 3, 0, 3)
+  TEST (2, 3, 0, 3)
+  TEST (3, 3, 0, 3)
+  TEST (0, 0, 1, 3)
+  TEST (1, 0, 1, 3)
+  TEST (2, 0, 1, 3)
+  TEST (3, 0, 1, 3)
+  TEST (0, 1, 1, 3)
+  TEST (1, 1, 1, 3)
+  TEST (2, 1, 1, 3)
+  TEST (3, 1, 1, 3)
+  TEST (0, 2, 1, 3)
+  TEST (1, 2, 1, 3)
+  TEST (2, 2, 1, 3)
+  TEST (3, 2, 1, 3)
+  TEST (0, 3, 1, 3)
+  TEST (1, 3, 1, 3)
+  TEST (2, 3, 1, 3)
+  TEST (3, 3, 1, 3)
+  TEST (0, 0, 2, 3)
+  TEST (1, 0, 2, 3)
+  TEST (2, 0, 2, 3)
+  TEST (3, 0, 2, 3)
+  TEST (0, 1, 2, 3)
+  TEST (1, 1, 2, 3)
+  TEST (2, 1, 2, 3)
+  TEST (3, 1, 2, 3)
+  TEST (0, 2, 2, 3)
+  TEST (1, 2, 2, 3)
+  TEST (2, 2, 2, 3)
+  TEST (3, 2, 2, 3)
+  TEST (0, 3, 2, 3)
+  TEST (1, 3, 2, 3)
+  TEST (2, 3, 2, 3)
+  TEST (3, 3, 2, 3)
+  TEST (0, 0, 3, 3)
+  TEST (1, 0, 3, 3)
+  TEST (2, 0, 3, 3)
+  TEST (3, 0, 3, 3)
+  TEST (0, 1, 3, 3)
+  TEST (1, 1, 3, 3)
+  TEST (2, 1, 3, 3)
+  TEST (3, 1, 3, 3)
+  TEST (0, 2, 3, 3)
+  TEST (1, 2, 3, 3)
+  TEST (2, 2, 3, 3)
+  TEST (3, 2, 3, 3)
+  TEST (0, 3, 3, 3)
+  TEST (1, 3, 3, 3)
+  TEST (2, 3, 3, 3)
+  TEST (3, 3, 3, 3)
+}
+
+void check(void)
+{
+  check0 ();
+  check1 ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/vperm-4-2.inc b/gcc/testsuite/gcc.target/i386/vperm-4-2.inc
new file mode 100644
index 0000000..2f7baa0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-4-2.inc
@@ -0,0 +1,4262 @@
+/* This file auto-generated with ./vperm.pl 4 2.  */
+
+void check0(void)
+{
+  TEST (0, 0, 0, 0)
+  TEST (1, 0, 0, 0)
+  TEST (2, 0, 0, 0)
+  TEST (3, 0, 0, 0)
+  TEST (4, 0, 0, 0)
+  TEST (5, 0, 0, 0)
+  TEST (6, 0, 0, 0)
+  TEST (7, 0, 0, 0)
+  TEST (0, 1, 0, 0)
+  TEST (1, 1, 0, 0)
+  TEST (2, 1, 0, 0)
+  TEST (3, 1, 0, 0)
+  TEST (4, 1, 0, 0)
+  TEST (5, 1, 0, 0)
+  TEST (6, 1, 0, 0)
+  TEST (7, 1, 0, 0)
+  TEST (0, 2, 0, 0)
+  TEST (1, 2, 0, 0)
+  TEST (2, 2, 0, 0)
+  TEST (3, 2, 0, 0)
+  TEST (4, 2, 0, 0)
+  TEST (5, 2, 0, 0)
+  TEST (6, 2, 0, 0)
+  TEST (7, 2, 0, 0)
+  TEST (0, 3, 0, 0)
+  TEST (1, 3, 0, 0)
+  TEST (2, 3, 0, 0)
+  TEST (3, 3, 0, 0)
+  TEST (4, 3, 0, 0)
+  TEST (5, 3, 0, 0)
+  TEST (6, 3, 0, 0)
+  TEST (7, 3, 0, 0)
+  TEST (0, 4, 0, 0)
+  TEST (1, 4, 0, 0)
+  TEST (2, 4, 0, 0)
+  TEST (3, 4, 0, 0)
+  TEST (4, 4, 0, 0)
+  TEST (5, 4, 0, 0)
+  TEST (6, 4, 0, 0)
+  TEST (7, 4, 0, 0)
+  TEST (0, 5, 0, 0)
+  TEST (1, 5, 0, 0)
+  TEST (2, 5, 0, 0)
+  TEST (3, 5, 0, 0)
+  TEST (4, 5, 0, 0)
+  TEST (5, 5, 0, 0)
+  TEST (6, 5, 0, 0)
+  TEST (7, 5, 0, 0)
+  TEST (0, 6, 0, 0)
+  TEST (1, 6, 0, 0)
+  TEST (2, 6, 0, 0)
+  TEST (3, 6, 0, 0)
+  TEST (4, 6, 0, 0)
+  TEST (5, 6, 0, 0)
+  TEST (6, 6, 0, 0)
+  TEST (7, 6, 0, 0)
+  TEST (0, 7, 0, 0)
+  TEST (1, 7, 0, 0)
+  TEST (2, 7, 0, 0)
+  TEST (3, 7, 0, 0)
+  TEST (4, 7, 0, 0)
+  TEST (5, 7, 0, 0)
+  TEST (6, 7, 0, 0)
+  TEST (7, 7, 0, 0)
+  TEST (0, 0, 1, 0)
+  TEST (1, 0, 1, 0)
+  TEST (2, 0, 1, 0)
+  TEST (3, 0, 1, 0)
+  TEST (4, 0, 1, 0)
+  TEST (5, 0, 1, 0)
+  TEST (6, 0, 1, 0)
+  TEST (7, 0, 1, 0)
+  TEST (0, 1, 1, 0)
+  TEST (1, 1, 1, 0)
+  TEST (2, 1, 1, 0)
+  TEST (3, 1, 1, 0)
+  TEST (4, 1, 1, 0)
+  TEST (5, 1, 1, 0)
+  TEST (6, 1, 1, 0)
+  TEST (7, 1, 1, 0)
+  TEST (0, 2, 1, 0)
+  TEST (1, 2, 1, 0)
+  TEST (2, 2, 1, 0)
+  TEST (3, 2, 1, 0)
+  TEST (4, 2, 1, 0)
+  TEST (5, 2, 1, 0)
+  TEST (6, 2, 1, 0)
+  TEST (7, 2, 1, 0)
+  TEST (0, 3, 1, 0)
+  TEST (1, 3, 1, 0)
+  TEST (2, 3, 1, 0)
+  TEST (3, 3, 1, 0)
+  TEST (4, 3, 1, 0)
+  TEST (5, 3, 1, 0)
+  TEST (6, 3, 1, 0)
+  TEST (7, 3, 1, 0)
+  TEST (0, 4, 1, 0)
+  TEST (1, 4, 1, 0)
+  TEST (2, 4, 1, 0)
+  TEST (3, 4, 1, 0)
+  TEST (4, 4, 1, 0)
+  TEST (5, 4, 1, 0)
+  TEST (6, 4, 1, 0)
+  TEST (7, 4, 1, 0)
+  TEST (0, 5, 1, 0)
+  TEST (1, 5, 1, 0)
+  TEST (2, 5, 1, 0)
+  TEST (3, 5, 1, 0)
+  TEST (4, 5, 1, 0)
+  TEST (5, 5, 1, 0)
+  TEST (6, 5, 1, 0)
+  TEST (7, 5, 1, 0)
+  TEST (0, 6, 1, 0)
+  TEST (1, 6, 1, 0)
+  TEST (2, 6, 1, 0)
+  TEST (3, 6, 1, 0)
+  TEST (4, 6, 1, 0)
+  TEST (5, 6, 1, 0)
+  TEST (6, 6, 1, 0)
+  TEST (7, 6, 1, 0)
+  TEST (0, 7, 1, 0)
+  TEST (1, 7, 1, 0)
+  TEST (2, 7, 1, 0)
+  TEST (3, 7, 1, 0)
+  TEST (4, 7, 1, 0)
+  TEST (5, 7, 1, 0)
+  TEST (6, 7, 1, 0)
+  TEST (7, 7, 1, 0)
+}
+
+void check1(void)
+{
+  TEST (0, 0, 2, 0)
+  TEST (1, 0, 2, 0)
+  TEST (2, 0, 2, 0)
+  TEST (3, 0, 2, 0)
+  TEST (4, 0, 2, 0)
+  TEST (5, 0, 2, 0)
+  TEST (6, 0, 2, 0)
+  TEST (7, 0, 2, 0)
+  TEST (0, 1, 2, 0)
+  TEST (1, 1, 2, 0)
+  TEST (2, 1, 2, 0)
+  TEST (3, 1, 2, 0)
+  TEST (4, 1, 2, 0)
+  TEST (5, 1, 2, 0)
+  TEST (6, 1, 2, 0)
+  TEST (7, 1, 2, 0)
+  TEST (0, 2, 2, 0)
+  TEST (1, 2, 2, 0)
+  TEST (2, 2, 2, 0)
+  TEST (3, 2, 2, 0)
+  TEST (4, 2, 2, 0)
+  TEST (5, 2, 2, 0)
+  TEST (6, 2, 2, 0)
+  TEST (7, 2, 2, 0)
+  TEST (0, 3, 2, 0)
+  TEST (1, 3, 2, 0)
+  TEST (2, 3, 2, 0)
+  TEST (3, 3, 2, 0)
+  TEST (4, 3, 2, 0)
+  TEST (5, 3, 2, 0)
+  TEST (6, 3, 2, 0)
+  TEST (7, 3, 2, 0)
+  TEST (0, 4, 2, 0)
+  TEST (1, 4, 2, 0)
+  TEST (2, 4, 2, 0)
+  TEST (3, 4, 2, 0)
+  TEST (4, 4, 2, 0)
+  TEST (5, 4, 2, 0)
+  TEST (6, 4, 2, 0)
+  TEST (7, 4, 2, 0)
+  TEST (0, 5, 2, 0)
+  TEST (1, 5, 2, 0)
+  TEST (2, 5, 2, 0)
+  TEST (3, 5, 2, 0)
+  TEST (4, 5, 2, 0)
+  TEST (5, 5, 2, 0)
+  TEST (6, 5, 2, 0)
+  TEST (7, 5, 2, 0)
+  TEST (0, 6, 2, 0)
+  TEST (1, 6, 2, 0)
+  TEST (2, 6, 2, 0)
+  TEST (3, 6, 2, 0)
+  TEST (4, 6, 2, 0)
+  TEST (5, 6, 2, 0)
+  TEST (6, 6, 2, 0)
+  TEST (7, 6, 2, 0)
+  TEST (0, 7, 2, 0)
+  TEST (1, 7, 2, 0)
+  TEST (2, 7, 2, 0)
+  TEST (3, 7, 2, 0)
+  TEST (4, 7, 2, 0)
+  TEST (5, 7, 2, 0)
+  TEST (6, 7, 2, 0)
+  TEST (7, 7, 2, 0)
+  TEST (0, 0, 3, 0)
+  TEST (1, 0, 3, 0)
+  TEST (2, 0, 3, 0)
+  TEST (3, 0, 3, 0)
+  TEST (4, 0, 3, 0)
+  TEST (5, 0, 3, 0)
+  TEST (6, 0, 3, 0)
+  TEST (7, 0, 3, 0)
+  TEST (0, 1, 3, 0)
+  TEST (1, 1, 3, 0)
+  TEST (2, 1, 3, 0)
+  TEST (3, 1, 3, 0)
+  TEST (4, 1, 3, 0)
+  TEST (5, 1, 3, 0)
+  TEST (6, 1, 3, 0)
+  TEST (7, 1, 3, 0)
+  TEST (0, 2, 3, 0)
+  TEST (1, 2, 3, 0)
+  TEST (2, 2, 3, 0)
+  TEST (3, 2, 3, 0)
+  TEST (4, 2, 3, 0)
+  TEST (5, 2, 3, 0)
+  TEST (6, 2, 3, 0)
+  TEST (7, 2, 3, 0)
+  TEST (0, 3, 3, 0)
+  TEST (1, 3, 3, 0)
+  TEST (2, 3, 3, 0)
+  TEST (3, 3, 3, 0)
+  TEST (4, 3, 3, 0)
+  TEST (5, 3, 3, 0)
+  TEST (6, 3, 3, 0)
+  TEST (7, 3, 3, 0)
+  TEST (0, 4, 3, 0)
+  TEST (1, 4, 3, 0)
+  TEST (2, 4, 3, 0)
+  TEST (3, 4, 3, 0)
+  TEST (4, 4, 3, 0)
+  TEST (5, 4, 3, 0)
+  TEST (6, 4, 3, 0)
+  TEST (7, 4, 3, 0)
+  TEST (0, 5, 3, 0)
+  TEST (1, 5, 3, 0)
+  TEST (2, 5, 3, 0)
+  TEST (3, 5, 3, 0)
+  TEST (4, 5, 3, 0)
+  TEST (5, 5, 3, 0)
+  TEST (6, 5, 3, 0)
+  TEST (7, 5, 3, 0)
+  TEST (0, 6, 3, 0)
+  TEST (1, 6, 3, 0)
+  TEST (2, 6, 3, 0)
+  TEST (3, 6, 3, 0)
+  TEST (4, 6, 3, 0)
+  TEST (5, 6, 3, 0)
+  TEST (6, 6, 3, 0)
+  TEST (7, 6, 3, 0)
+  TEST (0, 7, 3, 0)
+  TEST (1, 7, 3, 0)
+  TEST (2, 7, 3, 0)
+  TEST (3, 7, 3, 0)
+  TEST (4, 7, 3, 0)
+  TEST (5, 7, 3, 0)
+  TEST (6, 7, 3, 0)
+  TEST (7, 7, 3, 0)
+}
+
+void check2(void)
+{
+  TEST (0, 0, 4, 0)
+  TEST (1, 0, 4, 0)
+  TEST (2, 0, 4, 0)
+  TEST (3, 0, 4, 0)
+  TEST (4, 0, 4, 0)
+  TEST (5, 0, 4, 0)
+  TEST (6, 0, 4, 0)
+  TEST (7, 0, 4, 0)
+  TEST (0, 1, 4, 0)
+  TEST (1, 1, 4, 0)
+  TEST (2, 1, 4, 0)
+  TEST (3, 1, 4, 0)
+  TEST (4, 1, 4, 0)
+  TEST (5, 1, 4, 0)
+  TEST (6, 1, 4, 0)
+  TEST (7, 1, 4, 0)
+  TEST (0, 2, 4, 0)
+  TEST (1, 2, 4, 0)
+  TEST (2, 2, 4, 0)
+  TEST (3, 2, 4, 0)
+  TEST (4, 2, 4, 0)
+  TEST (5, 2, 4, 0)
+  TEST (6, 2, 4, 0)
+  TEST (7, 2, 4, 0)
+  TEST (0, 3, 4, 0)
+  TEST (1, 3, 4, 0)
+  TEST (2, 3, 4, 0)
+  TEST (3, 3, 4, 0)
+  TEST (4, 3, 4, 0)
+  TEST (5, 3, 4, 0)
+  TEST (6, 3, 4, 0)
+  TEST (7, 3, 4, 0)
+  TEST (0, 4, 4, 0)
+  TEST (1, 4, 4, 0)
+  TEST (2, 4, 4, 0)
+  TEST (3, 4, 4, 0)
+  TEST (4, 4, 4, 0)
+  TEST (5, 4, 4, 0)
+  TEST (6, 4, 4, 0)
+  TEST (7, 4, 4, 0)
+  TEST (0, 5, 4, 0)
+  TEST (1, 5, 4, 0)
+  TEST (2, 5, 4, 0)
+  TEST (3, 5, 4, 0)
+  TEST (4, 5, 4, 0)
+  TEST (5, 5, 4, 0)
+  TEST (6, 5, 4, 0)
+  TEST (7, 5, 4, 0)
+  TEST (0, 6, 4, 0)
+  TEST (1, 6, 4, 0)
+  TEST (2, 6, 4, 0)
+  TEST (3, 6, 4, 0)
+  TEST (4, 6, 4, 0)
+  TEST (5, 6, 4, 0)
+  TEST (6, 6, 4, 0)
+  TEST (7, 6, 4, 0)
+  TEST (0, 7, 4, 0)
+  TEST (1, 7, 4, 0)
+  TEST (2, 7, 4, 0)
+  TEST (3, 7, 4, 0)
+  TEST (4, 7, 4, 0)
+  TEST (5, 7, 4, 0)
+  TEST (6, 7, 4, 0)
+  TEST (7, 7, 4, 0)
+  TEST (0, 0, 5, 0)
+  TEST (1, 0, 5, 0)
+  TEST (2, 0, 5, 0)
+  TEST (3, 0, 5, 0)
+  TEST (4, 0, 5, 0)
+  TEST (5, 0, 5, 0)
+  TEST (6, 0, 5, 0)
+  TEST (7, 0, 5, 0)
+  TEST (0, 1, 5, 0)
+  TEST (1, 1, 5, 0)
+  TEST (2, 1, 5, 0)
+  TEST (3, 1, 5, 0)
+  TEST (4, 1, 5, 0)
+  TEST (5, 1, 5, 0)
+  TEST (6, 1, 5, 0)
+  TEST (7, 1, 5, 0)
+  TEST (0, 2, 5, 0)
+  TEST (1, 2, 5, 0)
+  TEST (2, 2, 5, 0)
+  TEST (3, 2, 5, 0)
+  TEST (4, 2, 5, 0)
+  TEST (5, 2, 5, 0)
+  TEST (6, 2, 5, 0)
+  TEST (7, 2, 5, 0)
+  TEST (0, 3, 5, 0)
+  TEST (1, 3, 5, 0)
+  TEST (2, 3, 5, 0)
+  TEST (3, 3, 5, 0)
+  TEST (4, 3, 5, 0)
+  TEST (5, 3, 5, 0)
+  TEST (6, 3, 5, 0)
+  TEST (7, 3, 5, 0)
+  TEST (0, 4, 5, 0)
+  TEST (1, 4, 5, 0)
+  TEST (2, 4, 5, 0)
+  TEST (3, 4, 5, 0)
+  TEST (4, 4, 5, 0)
+  TEST (5, 4, 5, 0)
+  TEST (6, 4, 5, 0)
+  TEST (7, 4, 5, 0)
+  TEST (0, 5, 5, 0)
+  TEST (1, 5, 5, 0)
+  TEST (2, 5, 5, 0)
+  TEST (3, 5, 5, 0)
+  TEST (4, 5, 5, 0)
+  TEST (5, 5, 5, 0)
+  TEST (6, 5, 5, 0)
+  TEST (7, 5, 5, 0)
+  TEST (0, 6, 5, 0)
+  TEST (1, 6, 5, 0)
+  TEST (2, 6, 5, 0)
+  TEST (3, 6, 5, 0)
+  TEST (4, 6, 5, 0)
+  TEST (5, 6, 5, 0)
+  TEST (6, 6, 5, 0)
+  TEST (7, 6, 5, 0)
+  TEST (0, 7, 5, 0)
+  TEST (1, 7, 5, 0)
+  TEST (2, 7, 5, 0)
+  TEST (3, 7, 5, 0)
+  TEST (4, 7, 5, 0)
+  TEST (5, 7, 5, 0)
+  TEST (6, 7, 5, 0)
+  TEST (7, 7, 5, 0)
+}
+
+void check3(void)
+{
+  TEST (0, 0, 6, 0)
+  TEST (1, 0, 6, 0)
+  TEST (2, 0, 6, 0)
+  TEST (3, 0, 6, 0)
+  TEST (4, 0, 6, 0)
+  TEST (5, 0, 6, 0)
+  TEST (6, 0, 6, 0)
+  TEST (7, 0, 6, 0)
+  TEST (0, 1, 6, 0)
+  TEST (1, 1, 6, 0)
+  TEST (2, 1, 6, 0)
+  TEST (3, 1, 6, 0)
+  TEST (4, 1, 6, 0)
+  TEST (5, 1, 6, 0)
+  TEST (6, 1, 6, 0)
+  TEST (7, 1, 6, 0)
+  TEST (0, 2, 6, 0)
+  TEST (1, 2, 6, 0)
+  TEST (2, 2, 6, 0)
+  TEST (3, 2, 6, 0)
+  TEST (4, 2, 6, 0)
+  TEST (5, 2, 6, 0)
+  TEST (6, 2, 6, 0)
+  TEST (7, 2, 6, 0)
+  TEST (0, 3, 6, 0)
+  TEST (1, 3, 6, 0)
+  TEST (2, 3, 6, 0)
+  TEST (3, 3, 6, 0)
+  TEST (4, 3, 6, 0)
+  TEST (5, 3, 6, 0)
+  TEST (6, 3, 6, 0)
+  TEST (7, 3, 6, 0)
+  TEST (0, 4, 6, 0)
+  TEST (1, 4, 6, 0)
+  TEST (2, 4, 6, 0)
+  TEST (3, 4, 6, 0)
+  TEST (4, 4, 6, 0)
+  TEST (5, 4, 6, 0)
+  TEST (6, 4, 6, 0)
+  TEST (7, 4, 6, 0)
+  TEST (0, 5, 6, 0)
+  TEST (1, 5, 6, 0)
+  TEST (2, 5, 6, 0)
+  TEST (3, 5, 6, 0)
+  TEST (4, 5, 6, 0)
+  TEST (5, 5, 6, 0)
+  TEST (6, 5, 6, 0)
+  TEST (7, 5, 6, 0)
+  TEST (0, 6, 6, 0)
+  TEST (1, 6, 6, 0)
+  TEST (2, 6, 6, 0)
+  TEST (3, 6, 6, 0)
+  TEST (4, 6, 6, 0)
+  TEST (5, 6, 6, 0)
+  TEST (6, 6, 6, 0)
+  TEST (7, 6, 6, 0)
+  TEST (0, 7, 6, 0)
+  TEST (1, 7, 6, 0)
+  TEST (2, 7, 6, 0)
+  TEST (3, 7, 6, 0)
+  TEST (4, 7, 6, 0)
+  TEST (5, 7, 6, 0)
+  TEST (6, 7, 6, 0)
+  TEST (7, 7, 6, 0)
+  TEST (0, 0, 7, 0)
+  TEST (1, 0, 7, 0)
+  TEST (2, 0, 7, 0)
+  TEST (3, 0, 7, 0)
+  TEST (4, 0, 7, 0)
+  TEST (5, 0, 7, 0)
+  TEST (6, 0, 7, 0)
+  TEST (7, 0, 7, 0)
+  TEST (0, 1, 7, 0)
+  TEST (1, 1, 7, 0)
+  TEST (2, 1, 7, 0)
+  TEST (3, 1, 7, 0)
+  TEST (4, 1, 7, 0)
+  TEST (5, 1, 7, 0)
+  TEST (6, 1, 7, 0)
+  TEST (7, 1, 7, 0)
+  TEST (0, 2, 7, 0)
+  TEST (1, 2, 7, 0)
+  TEST (2, 2, 7, 0)
+  TEST (3, 2, 7, 0)
+  TEST (4, 2, 7, 0)
+  TEST (5, 2, 7, 0)
+  TEST (6, 2, 7, 0)
+  TEST (7, 2, 7, 0)
+  TEST (0, 3, 7, 0)
+  TEST (1, 3, 7, 0)
+  TEST (2, 3, 7, 0)
+  TEST (3, 3, 7, 0)
+  TEST (4, 3, 7, 0)
+  TEST (5, 3, 7, 0)
+  TEST (6, 3, 7, 0)
+  TEST (7, 3, 7, 0)
+  TEST (0, 4, 7, 0)
+  TEST (1, 4, 7, 0)
+  TEST (2, 4, 7, 0)
+  TEST (3, 4, 7, 0)
+  TEST (4, 4, 7, 0)
+  TEST (5, 4, 7, 0)
+  TEST (6, 4, 7, 0)
+  TEST (7, 4, 7, 0)
+  TEST (0, 5, 7, 0)
+  TEST (1, 5, 7, 0)
+  TEST (2, 5, 7, 0)
+  TEST (3, 5, 7, 0)
+  TEST (4, 5, 7, 0)
+  TEST (5, 5, 7, 0)
+  TEST (6, 5, 7, 0)
+  TEST (7, 5, 7, 0)
+  TEST (0, 6, 7, 0)
+  TEST (1, 6, 7, 0)
+  TEST (2, 6, 7, 0)
+  TEST (3, 6, 7, 0)
+  TEST (4, 6, 7, 0)
+  TEST (5, 6, 7, 0)
+  TEST (6, 6, 7, 0)
+  TEST (7, 6, 7, 0)
+  TEST (0, 7, 7, 0)
+  TEST (1, 7, 7, 0)
+  TEST (2, 7, 7, 0)
+  TEST (3, 7, 7, 0)
+  TEST (4, 7, 7, 0)
+  TEST (5, 7, 7, 0)
+  TEST (6, 7, 7, 0)
+  TEST (7, 7, 7, 0)
+}
+
+void check4(void)
+{
+  TEST (0, 0, 0, 1)
+  TEST (1, 0, 0, 1)
+  TEST (2, 0, 0, 1)
+  TEST (3, 0, 0, 1)
+  TEST (4, 0, 0, 1)
+  TEST (5, 0, 0, 1)
+  TEST (6, 0, 0, 1)
+  TEST (7, 0, 0, 1)
+  TEST (0, 1, 0, 1)
+  TEST (1, 1, 0, 1)
+  TEST (2, 1, 0, 1)
+  TEST (3, 1, 0, 1)
+  TEST (4, 1, 0, 1)
+  TEST (5, 1, 0, 1)
+  TEST (6, 1, 0, 1)
+  TEST (7, 1, 0, 1)
+  TEST (0, 2, 0, 1)
+  TEST (1, 2, 0, 1)
+  TEST (2, 2, 0, 1)
+  TEST (3, 2, 0, 1)
+  TEST (4, 2, 0, 1)
+  TEST (5, 2, 0, 1)
+  TEST (6, 2, 0, 1)
+  TEST (7, 2, 0, 1)
+  TEST (0, 3, 0, 1)
+  TEST (1, 3, 0, 1)
+  TEST (2, 3, 0, 1)
+  TEST (3, 3, 0, 1)
+  TEST (4, 3, 0, 1)
+  TEST (5, 3, 0, 1)
+  TEST (6, 3, 0, 1)
+  TEST (7, 3, 0, 1)
+  TEST (0, 4, 0, 1)
+  TEST (1, 4, 0, 1)
+  TEST (2, 4, 0, 1)
+  TEST (3, 4, 0, 1)
+  TEST (4, 4, 0, 1)
+  TEST (5, 4, 0, 1)
+  TEST (6, 4, 0, 1)
+  TEST (7, 4, 0, 1)
+  TEST (0, 5, 0, 1)
+  TEST (1, 5, 0, 1)
+  TEST (2, 5, 0, 1)
+  TEST (3, 5, 0, 1)
+  TEST (4, 5, 0, 1)
+  TEST (5, 5, 0, 1)
+  TEST (6, 5, 0, 1)
+  TEST (7, 5, 0, 1)
+  TEST (0, 6, 0, 1)
+  TEST (1, 6, 0, 1)
+  TEST (2, 6, 0, 1)
+  TEST (3, 6, 0, 1)
+  TEST (4, 6, 0, 1)
+  TEST (5, 6, 0, 1)
+  TEST (6, 6, 0, 1)
+  TEST (7, 6, 0, 1)
+  TEST (0, 7, 0, 1)
+  TEST (1, 7, 0, 1)
+  TEST (2, 7, 0, 1)
+  TEST (3, 7, 0, 1)
+  TEST (4, 7, 0, 1)
+  TEST (5, 7, 0, 1)
+  TEST (6, 7, 0, 1)
+  TEST (7, 7, 0, 1)
+  TEST (0, 0, 1, 1)
+  TEST (1, 0, 1, 1)
+  TEST (2, 0, 1, 1)
+  TEST (3, 0, 1, 1)
+  TEST (4, 0, 1, 1)
+  TEST (5, 0, 1, 1)
+  TEST (6, 0, 1, 1)
+  TEST (7, 0, 1, 1)
+  TEST (0, 1, 1, 1)
+  TEST (1, 1, 1, 1)
+  TEST (2, 1, 1, 1)
+  TEST (3, 1, 1, 1)
+  TEST (4, 1, 1, 1)
+  TEST (5, 1, 1, 1)
+  TEST (6, 1, 1, 1)
+  TEST (7, 1, 1, 1)
+  TEST (0, 2, 1, 1)
+  TEST (1, 2, 1, 1)
+  TEST (2, 2, 1, 1)
+  TEST (3, 2, 1, 1)
+  TEST (4, 2, 1, 1)
+  TEST (5, 2, 1, 1)
+  TEST (6, 2, 1, 1)
+  TEST (7, 2, 1, 1)
+  TEST (0, 3, 1, 1)
+  TEST (1, 3, 1, 1)
+  TEST (2, 3, 1, 1)
+  TEST (3, 3, 1, 1)
+  TEST (4, 3, 1, 1)
+  TEST (5, 3, 1, 1)
+  TEST (6, 3, 1, 1)
+  TEST (7, 3, 1, 1)
+  TEST (0, 4, 1, 1)
+  TEST (1, 4, 1, 1)
+  TEST (2, 4, 1, 1)
+  TEST (3, 4, 1, 1)
+  TEST (4, 4, 1, 1)
+  TEST (5, 4, 1, 1)
+  TEST (6, 4, 1, 1)
+  TEST (7, 4, 1, 1)
+  TEST (0, 5, 1, 1)
+  TEST (1, 5, 1, 1)
+  TEST (2, 5, 1, 1)
+  TEST (3, 5, 1, 1)
+  TEST (4, 5, 1, 1)
+  TEST (5, 5, 1, 1)
+  TEST (6, 5, 1, 1)
+  TEST (7, 5, 1, 1)
+  TEST (0, 6, 1, 1)
+  TEST (1, 6, 1, 1)
+  TEST (2, 6, 1, 1)
+  TEST (3, 6, 1, 1)
+  TEST (4, 6, 1, 1)
+  TEST (5, 6, 1, 1)
+  TEST (6, 6, 1, 1)
+  TEST (7, 6, 1, 1)
+  TEST (0, 7, 1, 1)
+  TEST (1, 7, 1, 1)
+  TEST (2, 7, 1, 1)
+  TEST (3, 7, 1, 1)
+  TEST (4, 7, 1, 1)
+  TEST (5, 7, 1, 1)
+  TEST (6, 7, 1, 1)
+  TEST (7, 7, 1, 1)
+}
+
+void check5(void)
+{
+  TEST (0, 0, 2, 1)
+  TEST (1, 0, 2, 1)
+  TEST (2, 0, 2, 1)
+  TEST (3, 0, 2, 1)
+  TEST (4, 0, 2, 1)
+  TEST (5, 0, 2, 1)
+  TEST (6, 0, 2, 1)
+  TEST (7, 0, 2, 1)
+  TEST (0, 1, 2, 1)
+  TEST (1, 1, 2, 1)
+  TEST (2, 1, 2, 1)
+  TEST (3, 1, 2, 1)
+  TEST (4, 1, 2, 1)
+  TEST (5, 1, 2, 1)
+  TEST (6, 1, 2, 1)
+  TEST (7, 1, 2, 1)
+  TEST (0, 2, 2, 1)
+  TEST (1, 2, 2, 1)
+  TEST (2, 2, 2, 1)
+  TEST (3, 2, 2, 1)
+  TEST (4, 2, 2, 1)
+  TEST (5, 2, 2, 1)
+  TEST (6, 2, 2, 1)
+  TEST (7, 2, 2, 1)
+  TEST (0, 3, 2, 1)
+  TEST (1, 3, 2, 1)
+  TEST (2, 3, 2, 1)
+  TEST (3, 3, 2, 1)
+  TEST (4, 3, 2, 1)
+  TEST (5, 3, 2, 1)
+  TEST (6, 3, 2, 1)
+  TEST (7, 3, 2, 1)
+  TEST (0, 4, 2, 1)
+  TEST (1, 4, 2, 1)
+  TEST (2, 4, 2, 1)
+  TEST (3, 4, 2, 1)
+  TEST (4, 4, 2, 1)
+  TEST (5, 4, 2, 1)
+  TEST (6, 4, 2, 1)
+  TEST (7, 4, 2, 1)
+  TEST (0, 5, 2, 1)
+  TEST (1, 5, 2, 1)
+  TEST (2, 5, 2, 1)
+  TEST (3, 5, 2, 1)
+  TEST (4, 5, 2, 1)
+  TEST (5, 5, 2, 1)
+  TEST (6, 5, 2, 1)
+  TEST (7, 5, 2, 1)
+  TEST (0, 6, 2, 1)
+  TEST (1, 6, 2, 1)
+  TEST (2, 6, 2, 1)
+  TEST (3, 6, 2, 1)
+  TEST (4, 6, 2, 1)
+  TEST (5, 6, 2, 1)
+  TEST (6, 6, 2, 1)
+  TEST (7, 6, 2, 1)
+  TEST (0, 7, 2, 1)
+  TEST (1, 7, 2, 1)
+  TEST (2, 7, 2, 1)
+  TEST (3, 7, 2, 1)
+  TEST (4, 7, 2, 1)
+  TEST (5, 7, 2, 1)
+  TEST (6, 7, 2, 1)
+  TEST (7, 7, 2, 1)
+  TEST (0, 0, 3, 1)
+  TEST (1, 0, 3, 1)
+  TEST (2, 0, 3, 1)
+  TEST (3, 0, 3, 1)
+  TEST (4, 0, 3, 1)
+  TEST (5, 0, 3, 1)
+  TEST (6, 0, 3, 1)
+  TEST (7, 0, 3, 1)
+  TEST (0, 1, 3, 1)
+  TEST (1, 1, 3, 1)
+  TEST (2, 1, 3, 1)
+  TEST (3, 1, 3, 1)
+  TEST (4, 1, 3, 1)
+  TEST (5, 1, 3, 1)
+  TEST (6, 1, 3, 1)
+  TEST (7, 1, 3, 1)
+  TEST (0, 2, 3, 1)
+  TEST (1, 2, 3, 1)
+  TEST (2, 2, 3, 1)
+  TEST (3, 2, 3, 1)
+  TEST (4, 2, 3, 1)
+  TEST (5, 2, 3, 1)
+  TEST (6, 2, 3, 1)
+  TEST (7, 2, 3, 1)
+  TEST (0, 3, 3, 1)
+  TEST (1, 3, 3, 1)
+  TEST (2, 3, 3, 1)
+  TEST (3, 3, 3, 1)
+  TEST (4, 3, 3, 1)
+  TEST (5, 3, 3, 1)
+  TEST (6, 3, 3, 1)
+  TEST (7, 3, 3, 1)
+  TEST (0, 4, 3, 1)
+  TEST (1, 4, 3, 1)
+  TEST (2, 4, 3, 1)
+  TEST (3, 4, 3, 1)
+  TEST (4, 4, 3, 1)
+  TEST (5, 4, 3, 1)
+  TEST (6, 4, 3, 1)
+  TEST (7, 4, 3, 1)
+  TEST (0, 5, 3, 1)
+  TEST (1, 5, 3, 1)
+  TEST (2, 5, 3, 1)
+  TEST (3, 5, 3, 1)
+  TEST (4, 5, 3, 1)
+  TEST (5, 5, 3, 1)
+  TEST (6, 5, 3, 1)
+  TEST (7, 5, 3, 1)
+  TEST (0, 6, 3, 1)
+  TEST (1, 6, 3, 1)
+  TEST (2, 6, 3, 1)
+  TEST (3, 6, 3, 1)
+  TEST (4, 6, 3, 1)
+  TEST (5, 6, 3, 1)
+  TEST (6, 6, 3, 1)
+  TEST (7, 6, 3, 1)
+  TEST (0, 7, 3, 1)
+  TEST (1, 7, 3, 1)
+  TEST (2, 7, 3, 1)
+  TEST (3, 7, 3, 1)
+  TEST (4, 7, 3, 1)
+  TEST (5, 7, 3, 1)
+  TEST (6, 7, 3, 1)
+  TEST (7, 7, 3, 1)
+}
+
+void check6(void)
+{
+  TEST (0, 0, 4, 1)
+  TEST (1, 0, 4, 1)
+  TEST (2, 0, 4, 1)
+  TEST (3, 0, 4, 1)
+  TEST (4, 0, 4, 1)
+  TEST (5, 0, 4, 1)
+  TEST (6, 0, 4, 1)
+  TEST (7, 0, 4, 1)
+  TEST (0, 1, 4, 1)
+  TEST (1, 1, 4, 1)
+  TEST (2, 1, 4, 1)
+  TEST (3, 1, 4, 1)
+  TEST (4, 1, 4, 1)
+  TEST (5, 1, 4, 1)
+  TEST (6, 1, 4, 1)
+  TEST (7, 1, 4, 1)
+  TEST (0, 2, 4, 1)
+  TEST (1, 2, 4, 1)
+  TEST (2, 2, 4, 1)
+  TEST (3, 2, 4, 1)
+  TEST (4, 2, 4, 1)
+  TEST (5, 2, 4, 1)
+  TEST (6, 2, 4, 1)
+  TEST (7, 2, 4, 1)
+  TEST (0, 3, 4, 1)
+  TEST (1, 3, 4, 1)
+  TEST (2, 3, 4, 1)
+  TEST (3, 3, 4, 1)
+  TEST (4, 3, 4, 1)
+  TEST (5, 3, 4, 1)
+  TEST (6, 3, 4, 1)
+  TEST (7, 3, 4, 1)
+  TEST (0, 4, 4, 1)
+  TEST (1, 4, 4, 1)
+  TEST (2, 4, 4, 1)
+  TEST (3, 4, 4, 1)
+  TEST (4, 4, 4, 1)
+  TEST (5, 4, 4, 1)
+  TEST (6, 4, 4, 1)
+  TEST (7, 4, 4, 1)
+  TEST (0, 5, 4, 1)
+  TEST (1, 5, 4, 1)
+  TEST (2, 5, 4, 1)
+  TEST (3, 5, 4, 1)
+  TEST (4, 5, 4, 1)
+  TEST (5, 5, 4, 1)
+  TEST (6, 5, 4, 1)
+  TEST (7, 5, 4, 1)
+  TEST (0, 6, 4, 1)
+  TEST (1, 6, 4, 1)
+  TEST (2, 6, 4, 1)
+  TEST (3, 6, 4, 1)
+  TEST (4, 6, 4, 1)
+  TEST (5, 6, 4, 1)
+  TEST (6, 6, 4, 1)
+  TEST (7, 6, 4, 1)
+  TEST (0, 7, 4, 1)
+  TEST (1, 7, 4, 1)
+  TEST (2, 7, 4, 1)
+  TEST (3, 7, 4, 1)
+  TEST (4, 7, 4, 1)
+  TEST (5, 7, 4, 1)
+  TEST (6, 7, 4, 1)
+  TEST (7, 7, 4, 1)
+  TEST (0, 0, 5, 1)
+  TEST (1, 0, 5, 1)
+  TEST (2, 0, 5, 1)
+  TEST (3, 0, 5, 1)
+  TEST (4, 0, 5, 1)
+  TEST (5, 0, 5, 1)
+  TEST (6, 0, 5, 1)
+  TEST (7, 0, 5, 1)
+  TEST (0, 1, 5, 1)
+  TEST (1, 1, 5, 1)
+  TEST (2, 1, 5, 1)
+  TEST (3, 1, 5, 1)
+  TEST (4, 1, 5, 1)
+  TEST (5, 1, 5, 1)
+  TEST (6, 1, 5, 1)
+  TEST (7, 1, 5, 1)
+  TEST (0, 2, 5, 1)
+  TEST (1, 2, 5, 1)
+  TEST (2, 2, 5, 1)
+  TEST (3, 2, 5, 1)
+  TEST (4, 2, 5, 1)
+  TEST (5, 2, 5, 1)
+  TEST (6, 2, 5, 1)
+  TEST (7, 2, 5, 1)
+  TEST (0, 3, 5, 1)
+  TEST (1, 3, 5, 1)
+  TEST (2, 3, 5, 1)
+  TEST (3, 3, 5, 1)
+  TEST (4, 3, 5, 1)
+  TEST (5, 3, 5, 1)
+  TEST (6, 3, 5, 1)
+  TEST (7, 3, 5, 1)
+  TEST (0, 4, 5, 1)
+  TEST (1, 4, 5, 1)
+  TEST (2, 4, 5, 1)
+  TEST (3, 4, 5, 1)
+  TEST (4, 4, 5, 1)
+  TEST (5, 4, 5, 1)
+  TEST (6, 4, 5, 1)
+  TEST (7, 4, 5, 1)
+  TEST (0, 5, 5, 1)
+  TEST (1, 5, 5, 1)
+  TEST (2, 5, 5, 1)
+  TEST (3, 5, 5, 1)
+  TEST (4, 5, 5, 1)
+  TEST (5, 5, 5, 1)
+  TEST (6, 5, 5, 1)
+  TEST (7, 5, 5, 1)
+  TEST (0, 6, 5, 1)
+  TEST (1, 6, 5, 1)
+  TEST (2, 6, 5, 1)
+  TEST (3, 6, 5, 1)
+  TEST (4, 6, 5, 1)
+  TEST (5, 6, 5, 1)
+  TEST (6, 6, 5, 1)
+  TEST (7, 6, 5, 1)
+  TEST (0, 7, 5, 1)
+  TEST (1, 7, 5, 1)
+  TEST (2, 7, 5, 1)
+  TEST (3, 7, 5, 1)
+  TEST (4, 7, 5, 1)
+  TEST (5, 7, 5, 1)
+  TEST (6, 7, 5, 1)
+  TEST (7, 7, 5, 1)
+}
+
+void check7(void)
+{
+  TEST (0, 0, 6, 1)
+  TEST (1, 0, 6, 1)
+  TEST (2, 0, 6, 1)
+  TEST (3, 0, 6, 1)
+  TEST (4, 0, 6, 1)
+  TEST (5, 0, 6, 1)
+  TEST (6, 0, 6, 1)
+  TEST (7, 0, 6, 1)
+  TEST (0, 1, 6, 1)
+  TEST (1, 1, 6, 1)
+  TEST (2, 1, 6, 1)
+  TEST (3, 1, 6, 1)
+  TEST (4, 1, 6, 1)
+  TEST (5, 1, 6, 1)
+  TEST (6, 1, 6, 1)
+  TEST (7, 1, 6, 1)
+  TEST (0, 2, 6, 1)
+  TEST (1, 2, 6, 1)
+  TEST (2, 2, 6, 1)
+  TEST (3, 2, 6, 1)
+  TEST (4, 2, 6, 1)
+  TEST (5, 2, 6, 1)
+  TEST (6, 2, 6, 1)
+  TEST (7, 2, 6, 1)
+  TEST (0, 3, 6, 1)
+  TEST (1, 3, 6, 1)
+  TEST (2, 3, 6, 1)
+  TEST (3, 3, 6, 1)
+  TEST (4, 3, 6, 1)
+  TEST (5, 3, 6, 1)
+  TEST (6, 3, 6, 1)
+  TEST (7, 3, 6, 1)
+  TEST (0, 4, 6, 1)
+  TEST (1, 4, 6, 1)
+  TEST (2, 4, 6, 1)
+  TEST (3, 4, 6, 1)
+  TEST (4, 4, 6, 1)
+  TEST (5, 4, 6, 1)
+  TEST (6, 4, 6, 1)
+  TEST (7, 4, 6, 1)
+  TEST (0, 5, 6, 1)
+  TEST (1, 5, 6, 1)
+  TEST (2, 5, 6, 1)
+  TEST (3, 5, 6, 1)
+  TEST (4, 5, 6, 1)
+  TEST (5, 5, 6, 1)
+  TEST (6, 5, 6, 1)
+  TEST (7, 5, 6, 1)
+  TEST (0, 6, 6, 1)
+  TEST (1, 6, 6, 1)
+  TEST (2, 6, 6, 1)
+  TEST (3, 6, 6, 1)
+  TEST (4, 6, 6, 1)
+  TEST (5, 6, 6, 1)
+  TEST (6, 6, 6, 1)
+  TEST (7, 6, 6, 1)
+  TEST (0, 7, 6, 1)
+  TEST (1, 7, 6, 1)
+  TEST (2, 7, 6, 1)
+  TEST (3, 7, 6, 1)
+  TEST (4, 7, 6, 1)
+  TEST (5, 7, 6, 1)
+  TEST (6, 7, 6, 1)
+  TEST (7, 7, 6, 1)
+  TEST (0, 0, 7, 1)
+  TEST (1, 0, 7, 1)
+  TEST (2, 0, 7, 1)
+  TEST (3, 0, 7, 1)
+  TEST (4, 0, 7, 1)
+  TEST (5, 0, 7, 1)
+  TEST (6, 0, 7, 1)
+  TEST (7, 0, 7, 1)
+  TEST (0, 1, 7, 1)
+  TEST (1, 1, 7, 1)
+  TEST (2, 1, 7, 1)
+  TEST (3, 1, 7, 1)
+  TEST (4, 1, 7, 1)
+  TEST (5, 1, 7, 1)
+  TEST (6, 1, 7, 1)
+  TEST (7, 1, 7, 1)
+  TEST (0, 2, 7, 1)
+  TEST (1, 2, 7, 1)
+  TEST (2, 2, 7, 1)
+  TEST (3, 2, 7, 1)
+  TEST (4, 2, 7, 1)
+  TEST (5, 2, 7, 1)
+  TEST (6, 2, 7, 1)
+  TEST (7, 2, 7, 1)
+  TEST (0, 3, 7, 1)
+  TEST (1, 3, 7, 1)
+  TEST (2, 3, 7, 1)
+  TEST (3, 3, 7, 1)
+  TEST (4, 3, 7, 1)
+  TEST (5, 3, 7, 1)
+  TEST (6, 3, 7, 1)
+  TEST (7, 3, 7, 1)
+  TEST (0, 4, 7, 1)
+  TEST (1, 4, 7, 1)
+  TEST (2, 4, 7, 1)
+  TEST (3, 4, 7, 1)
+  TEST (4, 4, 7, 1)
+  TEST (5, 4, 7, 1)
+  TEST (6, 4, 7, 1)
+  TEST (7, 4, 7, 1)
+  TEST (0, 5, 7, 1)
+  TEST (1, 5, 7, 1)
+  TEST (2, 5, 7, 1)
+  TEST (3, 5, 7, 1)
+  TEST (4, 5, 7, 1)
+  TEST (5, 5, 7, 1)
+  TEST (6, 5, 7, 1)
+  TEST (7, 5, 7, 1)
+  TEST (0, 6, 7, 1)
+  TEST (1, 6, 7, 1)
+  TEST (2, 6, 7, 1)
+  TEST (3, 6, 7, 1)
+  TEST (4, 6, 7, 1)
+  TEST (5, 6, 7, 1)
+  TEST (6, 6, 7, 1)
+  TEST (7, 6, 7, 1)
+  TEST (0, 7, 7, 1)
+  TEST (1, 7, 7, 1)
+  TEST (2, 7, 7, 1)
+  TEST (3, 7, 7, 1)
+  TEST (4, 7, 7, 1)
+  TEST (5, 7, 7, 1)
+  TEST (6, 7, 7, 1)
+  TEST (7, 7, 7, 1)
+}
+
+void check8(void)
+{
+  TEST (0, 0, 0, 2)
+  TEST (1, 0, 0, 2)
+  TEST (2, 0, 0, 2)
+  TEST (3, 0, 0, 2)
+  TEST (4, 0, 0, 2)
+  TEST (5, 0, 0, 2)
+  TEST (6, 0, 0, 2)
+  TEST (7, 0, 0, 2)
+  TEST (0, 1, 0, 2)
+  TEST (1, 1, 0, 2)
+  TEST (2, 1, 0, 2)
+  TEST (3, 1, 0, 2)
+  TEST (4, 1, 0, 2)
+  TEST (5, 1, 0, 2)
+  TEST (6, 1, 0, 2)
+  TEST (7, 1, 0, 2)
+  TEST (0, 2, 0, 2)
+  TEST (1, 2, 0, 2)
+  TEST (2, 2, 0, 2)
+  TEST (3, 2, 0, 2)
+  TEST (4, 2, 0, 2)
+  TEST (5, 2, 0, 2)
+  TEST (6, 2, 0, 2)
+  TEST (7, 2, 0, 2)
+  TEST (0, 3, 0, 2)
+  TEST (1, 3, 0, 2)
+  TEST (2, 3, 0, 2)
+  TEST (3, 3, 0, 2)
+  TEST (4, 3, 0, 2)
+  TEST (5, 3, 0, 2)
+  TEST (6, 3, 0, 2)
+  TEST (7, 3, 0, 2)
+  TEST (0, 4, 0, 2)
+  TEST (1, 4, 0, 2)
+  TEST (2, 4, 0, 2)
+  TEST (3, 4, 0, 2)
+  TEST (4, 4, 0, 2)
+  TEST (5, 4, 0, 2)
+  TEST (6, 4, 0, 2)
+  TEST (7, 4, 0, 2)
+  TEST (0, 5, 0, 2)
+  TEST (1, 5, 0, 2)
+  TEST (2, 5, 0, 2)
+  TEST (3, 5, 0, 2)
+  TEST (4, 5, 0, 2)
+  TEST (5, 5, 0, 2)
+  TEST (6, 5, 0, 2)
+  TEST (7, 5, 0, 2)
+  TEST (0, 6, 0, 2)
+  TEST (1, 6, 0, 2)
+  TEST (2, 6, 0, 2)
+  TEST (3, 6, 0, 2)
+  TEST (4, 6, 0, 2)
+  TEST (5, 6, 0, 2)
+  TEST (6, 6, 0, 2)
+  TEST (7, 6, 0, 2)
+  TEST (0, 7, 0, 2)
+  TEST (1, 7, 0, 2)
+  TEST (2, 7, 0, 2)
+  TEST (3, 7, 0, 2)
+  TEST (4, 7, 0, 2)
+  TEST (5, 7, 0, 2)
+  TEST (6, 7, 0, 2)
+  TEST (7, 7, 0, 2)
+  TEST (0, 0, 1, 2)
+  TEST (1, 0, 1, 2)
+  TEST (2, 0, 1, 2)
+  TEST (3, 0, 1, 2)
+  TEST (4, 0, 1, 2)
+  TEST (5, 0, 1, 2)
+  TEST (6, 0, 1, 2)
+  TEST (7, 0, 1, 2)
+  TEST (0, 1, 1, 2)
+  TEST (1, 1, 1, 2)
+  TEST (2, 1, 1, 2)
+  TEST (3, 1, 1, 2)
+  TEST (4, 1, 1, 2)
+  TEST (5, 1, 1, 2)
+  TEST (6, 1, 1, 2)
+  TEST (7, 1, 1, 2)
+  TEST (0, 2, 1, 2)
+  TEST (1, 2, 1, 2)
+  TEST (2, 2, 1, 2)
+  TEST (3, 2, 1, 2)
+  TEST (4, 2, 1, 2)
+  TEST (5, 2, 1, 2)
+  TEST (6, 2, 1, 2)
+  TEST (7, 2, 1, 2)
+  TEST (0, 3, 1, 2)
+  TEST (1, 3, 1, 2)
+  TEST (2, 3, 1, 2)
+  TEST (3, 3, 1, 2)
+  TEST (4, 3, 1, 2)
+  TEST (5, 3, 1, 2)
+  TEST (6, 3, 1, 2)
+  TEST (7, 3, 1, 2)
+  TEST (0, 4, 1, 2)
+  TEST (1, 4, 1, 2)
+  TEST (2, 4, 1, 2)
+  TEST (3, 4, 1, 2)
+  TEST (4, 4, 1, 2)
+  TEST (5, 4, 1, 2)
+  TEST (6, 4, 1, 2)
+  TEST (7, 4, 1, 2)
+  TEST (0, 5, 1, 2)
+  TEST (1, 5, 1, 2)
+  TEST (2, 5, 1, 2)
+  TEST (3, 5, 1, 2)
+  TEST (4, 5, 1, 2)
+  TEST (5, 5, 1, 2)
+  TEST (6, 5, 1, 2)
+  TEST (7, 5, 1, 2)
+  TEST (0, 6, 1, 2)
+  TEST (1, 6, 1, 2)
+  TEST (2, 6, 1, 2)
+  TEST (3, 6, 1, 2)
+  TEST (4, 6, 1, 2)
+  TEST (5, 6, 1, 2)
+  TEST (6, 6, 1, 2)
+  TEST (7, 6, 1, 2)
+  TEST (0, 7, 1, 2)
+  TEST (1, 7, 1, 2)
+  TEST (2, 7, 1, 2)
+  TEST (3, 7, 1, 2)
+  TEST (4, 7, 1, 2)
+  TEST (5, 7, 1, 2)
+  TEST (6, 7, 1, 2)
+  TEST (7, 7, 1, 2)
+}
+
+void check9(void)
+{
+  TEST (0, 0, 2, 2)
+  TEST (1, 0, 2, 2)
+  TEST (2, 0, 2, 2)
+  TEST (3, 0, 2, 2)
+  TEST (4, 0, 2, 2)
+  TEST (5, 0, 2, 2)
+  TEST (6, 0, 2, 2)
+  TEST (7, 0, 2, 2)
+  TEST (0, 1, 2, 2)
+  TEST (1, 1, 2, 2)
+  TEST (2, 1, 2, 2)
+  TEST (3, 1, 2, 2)
+  TEST (4, 1, 2, 2)
+  TEST (5, 1, 2, 2)
+  TEST (6, 1, 2, 2)
+  TEST (7, 1, 2, 2)
+  TEST (0, 2, 2, 2)
+  TEST (1, 2, 2, 2)
+  TEST (2, 2, 2, 2)
+  TEST (3, 2, 2, 2)
+  TEST (4, 2, 2, 2)
+  TEST (5, 2, 2, 2)
+  TEST (6, 2, 2, 2)
+  TEST (7, 2, 2, 2)
+  TEST (0, 3, 2, 2)
+  TEST (1, 3, 2, 2)
+  TEST (2, 3, 2, 2)
+  TEST (3, 3, 2, 2)
+  TEST (4, 3, 2, 2)
+  TEST (5, 3, 2, 2)
+  TEST (6, 3, 2, 2)
+  TEST (7, 3, 2, 2)
+  TEST (0, 4, 2, 2)
+  TEST (1, 4, 2, 2)
+  TEST (2, 4, 2, 2)
+  TEST (3, 4, 2, 2)
+  TEST (4, 4, 2, 2)
+  TEST (5, 4, 2, 2)
+  TEST (6, 4, 2, 2)
+  TEST (7, 4, 2, 2)
+  TEST (0, 5, 2, 2)
+  TEST (1, 5, 2, 2)
+  TEST (2, 5, 2, 2)
+  TEST (3, 5, 2, 2)
+  TEST (4, 5, 2, 2)
+  TEST (5, 5, 2, 2)
+  TEST (6, 5, 2, 2)
+  TEST (7, 5, 2, 2)
+  TEST (0, 6, 2, 2)
+  TEST (1, 6, 2, 2)
+  TEST (2, 6, 2, 2)
+  TEST (3, 6, 2, 2)
+  TEST (4, 6, 2, 2)
+  TEST (5, 6, 2, 2)
+  TEST (6, 6, 2, 2)
+  TEST (7, 6, 2, 2)
+  TEST (0, 7, 2, 2)
+  TEST (1, 7, 2, 2)
+  TEST (2, 7, 2, 2)
+  TEST (3, 7, 2, 2)
+  TEST (4, 7, 2, 2)
+  TEST (5, 7, 2, 2)
+  TEST (6, 7, 2, 2)
+  TEST (7, 7, 2, 2)
+  TEST (0, 0, 3, 2)
+  TEST (1, 0, 3, 2)
+  TEST (2, 0, 3, 2)
+  TEST (3, 0, 3, 2)
+  TEST (4, 0, 3, 2)
+  TEST (5, 0, 3, 2)
+  TEST (6, 0, 3, 2)
+  TEST (7, 0, 3, 2)
+  TEST (0, 1, 3, 2)
+  TEST (1, 1, 3, 2)
+  TEST (2, 1, 3, 2)
+  TEST (3, 1, 3, 2)
+  TEST (4, 1, 3, 2)
+  TEST (5, 1, 3, 2)
+  TEST (6, 1, 3, 2)
+  TEST (7, 1, 3, 2)
+  TEST (0, 2, 3, 2)
+  TEST (1, 2, 3, 2)
+  TEST (2, 2, 3, 2)
+  TEST (3, 2, 3, 2)
+  TEST (4, 2, 3, 2)
+  TEST (5, 2, 3, 2)
+  TEST (6, 2, 3, 2)
+  TEST (7, 2, 3, 2)
+  TEST (0, 3, 3, 2)
+  TEST (1, 3, 3, 2)
+  TEST (2, 3, 3, 2)
+  TEST (3, 3, 3, 2)
+  TEST (4, 3, 3, 2)
+  TEST (5, 3, 3, 2)
+  TEST (6, 3, 3, 2)
+  TEST (7, 3, 3, 2)
+  TEST (0, 4, 3, 2)
+  TEST (1, 4, 3, 2)
+  TEST (2, 4, 3, 2)
+  TEST (3, 4, 3, 2)
+  TEST (4, 4, 3, 2)
+  TEST (5, 4, 3, 2)
+  TEST (6, 4, 3, 2)
+  TEST (7, 4, 3, 2)
+  TEST (0, 5, 3, 2)
+  TEST (1, 5, 3, 2)
+  TEST (2, 5, 3, 2)
+  TEST (3, 5, 3, 2)
+  TEST (4, 5, 3, 2)
+  TEST (5, 5, 3, 2)
+  TEST (6, 5, 3, 2)
+  TEST (7, 5, 3, 2)
+  TEST (0, 6, 3, 2)
+  TEST (1, 6, 3, 2)
+  TEST (2, 6, 3, 2)
+  TEST (3, 6, 3, 2)
+  TEST (4, 6, 3, 2)
+  TEST (5, 6, 3, 2)
+  TEST (6, 6, 3, 2)
+  TEST (7, 6, 3, 2)
+  TEST (0, 7, 3, 2)
+  TEST (1, 7, 3, 2)
+  TEST (2, 7, 3, 2)
+  TEST (3, 7, 3, 2)
+  TEST (4, 7, 3, 2)
+  TEST (5, 7, 3, 2)
+  TEST (6, 7, 3, 2)
+  TEST (7, 7, 3, 2)
+}
+
+void check10(void)
+{
+  TEST (0, 0, 4, 2)
+  TEST (1, 0, 4, 2)
+  TEST (2, 0, 4, 2)
+  TEST (3, 0, 4, 2)
+  TEST (4, 0, 4, 2)
+  TEST (5, 0, 4, 2)
+  TEST (6, 0, 4, 2)
+  TEST (7, 0, 4, 2)
+  TEST (0, 1, 4, 2)
+  TEST (1, 1, 4, 2)
+  TEST (2, 1, 4, 2)
+  TEST (3, 1, 4, 2)
+  TEST (4, 1, 4, 2)
+  TEST (5, 1, 4, 2)
+  TEST (6, 1, 4, 2)
+  TEST (7, 1, 4, 2)
+  TEST (0, 2, 4, 2)
+  TEST (1, 2, 4, 2)
+  TEST (2, 2, 4, 2)
+  TEST (3, 2, 4, 2)
+  TEST (4, 2, 4, 2)
+  TEST (5, 2, 4, 2)
+  TEST (6, 2, 4, 2)
+  TEST (7, 2, 4, 2)
+  TEST (0, 3, 4, 2)
+  TEST (1, 3, 4, 2)
+  TEST (2, 3, 4, 2)
+  TEST (3, 3, 4, 2)
+  TEST (4, 3, 4, 2)
+  TEST (5, 3, 4, 2)
+  TEST (6, 3, 4, 2)
+  TEST (7, 3, 4, 2)
+  TEST (0, 4, 4, 2)
+  TEST (1, 4, 4, 2)
+  TEST (2, 4, 4, 2)
+  TEST (3, 4, 4, 2)
+  TEST (4, 4, 4, 2)
+  TEST (5, 4, 4, 2)
+  TEST (6, 4, 4, 2)
+  TEST (7, 4, 4, 2)
+  TEST (0, 5, 4, 2)
+  TEST (1, 5, 4, 2)
+  TEST (2, 5, 4, 2)
+  TEST (3, 5, 4, 2)
+  TEST (4, 5, 4, 2)
+  TEST (5, 5, 4, 2)
+  TEST (6, 5, 4, 2)
+  TEST (7, 5, 4, 2)
+  TEST (0, 6, 4, 2)
+  TEST (1, 6, 4, 2)
+  TEST (2, 6, 4, 2)
+  TEST (3, 6, 4, 2)
+  TEST (4, 6, 4, 2)
+  TEST (5, 6, 4, 2)
+  TEST (6, 6, 4, 2)
+  TEST (7, 6, 4, 2)
+  TEST (0, 7, 4, 2)
+  TEST (1, 7, 4, 2)
+  TEST (2, 7, 4, 2)
+  TEST (3, 7, 4, 2)
+  TEST (4, 7, 4, 2)
+  TEST (5, 7, 4, 2)
+  TEST (6, 7, 4, 2)
+  TEST (7, 7, 4, 2)
+  TEST (0, 0, 5, 2)
+  TEST (1, 0, 5, 2)
+  TEST (2, 0, 5, 2)
+  TEST (3, 0, 5, 2)
+  TEST (4, 0, 5, 2)
+  TEST (5, 0, 5, 2)
+  TEST (6, 0, 5, 2)
+  TEST (7, 0, 5, 2)
+  TEST (0, 1, 5, 2)
+  TEST (1, 1, 5, 2)
+  TEST (2, 1, 5, 2)
+  TEST (3, 1, 5, 2)
+  TEST (4, 1, 5, 2)
+  TEST (5, 1, 5, 2)
+  TEST (6, 1, 5, 2)
+  TEST (7, 1, 5, 2)
+  TEST (0, 2, 5, 2)
+  TEST (1, 2, 5, 2)
+  TEST (2, 2, 5, 2)
+  TEST (3, 2, 5, 2)
+  TEST (4, 2, 5, 2)
+  TEST (5, 2, 5, 2)
+  TEST (6, 2, 5, 2)
+  TEST (7, 2, 5, 2)
+  TEST (0, 3, 5, 2)
+  TEST (1, 3, 5, 2)
+  TEST (2, 3, 5, 2)
+  TEST (3, 3, 5, 2)
+  TEST (4, 3, 5, 2)
+  TEST (5, 3, 5, 2)
+  TEST (6, 3, 5, 2)
+  TEST (7, 3, 5, 2)
+  TEST (0, 4, 5, 2)
+  TEST (1, 4, 5, 2)
+  TEST (2, 4, 5, 2)
+  TEST (3, 4, 5, 2)
+  TEST (4, 4, 5, 2)
+  TEST (5, 4, 5, 2)
+  TEST (6, 4, 5, 2)
+  TEST (7, 4, 5, 2)
+  TEST (0, 5, 5, 2)
+  TEST (1, 5, 5, 2)
+  TEST (2, 5, 5, 2)
+  TEST (3, 5, 5, 2)
+  TEST (4, 5, 5, 2)
+  TEST (5, 5, 5, 2)
+  TEST (6, 5, 5, 2)
+  TEST (7, 5, 5, 2)
+  TEST (0, 6, 5, 2)
+  TEST (1, 6, 5, 2)
+  TEST (2, 6, 5, 2)
+  TEST (3, 6, 5, 2)
+  TEST (4, 6, 5, 2)
+  TEST (5, 6, 5, 2)
+  TEST (6, 6, 5, 2)
+  TEST (7, 6, 5, 2)
+  TEST (0, 7, 5, 2)
+  TEST (1, 7, 5, 2)
+  TEST (2, 7, 5, 2)
+  TEST (3, 7, 5, 2)
+  TEST (4, 7, 5, 2)
+  TEST (5, 7, 5, 2)
+  TEST (6, 7, 5, 2)
+  TEST (7, 7, 5, 2)
+}
+
+void check11(void)
+{
+  TEST (0, 0, 6, 2)
+  TEST (1, 0, 6, 2)
+  TEST (2, 0, 6, 2)
+  TEST (3, 0, 6, 2)
+  TEST (4, 0, 6, 2)
+  TEST (5, 0, 6, 2)
+  TEST (6, 0, 6, 2)
+  TEST (7, 0, 6, 2)
+  TEST (0, 1, 6, 2)
+  TEST (1, 1, 6, 2)
+  TEST (2, 1, 6, 2)
+  TEST (3, 1, 6, 2)
+  TEST (4, 1, 6, 2)
+  TEST (5, 1, 6, 2)
+  TEST (6, 1, 6, 2)
+  TEST (7, 1, 6, 2)
+  TEST (0, 2, 6, 2)
+  TEST (1, 2, 6, 2)
+  TEST (2, 2, 6, 2)
+  TEST (3, 2, 6, 2)
+  TEST (4, 2, 6, 2)
+  TEST (5, 2, 6, 2)
+  TEST (6, 2, 6, 2)
+  TEST (7, 2, 6, 2)
+  TEST (0, 3, 6, 2)
+  TEST (1, 3, 6, 2)
+  TEST (2, 3, 6, 2)
+  TEST (3, 3, 6, 2)
+  TEST (4, 3, 6, 2)
+  TEST (5, 3, 6, 2)
+  TEST (6, 3, 6, 2)
+  TEST (7, 3, 6, 2)
+  TEST (0, 4, 6, 2)
+  TEST (1, 4, 6, 2)
+  TEST (2, 4, 6, 2)
+  TEST (3, 4, 6, 2)
+  TEST (4, 4, 6, 2)
+  TEST (5, 4, 6, 2)
+  TEST (6, 4, 6, 2)
+  TEST (7, 4, 6, 2)
+  TEST (0, 5, 6, 2)
+  TEST (1, 5, 6, 2)
+  TEST (2, 5, 6, 2)
+  TEST (3, 5, 6, 2)
+  TEST (4, 5, 6, 2)
+  TEST (5, 5, 6, 2)
+  TEST (6, 5, 6, 2)
+  TEST (7, 5, 6, 2)
+  TEST (0, 6, 6, 2)
+  TEST (1, 6, 6, 2)
+  TEST (2, 6, 6, 2)
+  TEST (3, 6, 6, 2)
+  TEST (4, 6, 6, 2)
+  TEST (5, 6, 6, 2)
+  TEST (6, 6, 6, 2)
+  TEST (7, 6, 6, 2)
+  TEST (0, 7, 6, 2)
+  TEST (1, 7, 6, 2)
+  TEST (2, 7, 6, 2)
+  TEST (3, 7, 6, 2)
+  TEST (4, 7, 6, 2)
+  TEST (5, 7, 6, 2)
+  TEST (6, 7, 6, 2)
+  TEST (7, 7, 6, 2)
+  TEST (0, 0, 7, 2)
+  TEST (1, 0, 7, 2)
+  TEST (2, 0, 7, 2)
+  TEST (3, 0, 7, 2)
+  TEST (4, 0, 7, 2)
+  TEST (5, 0, 7, 2)
+  TEST (6, 0, 7, 2)
+  TEST (7, 0, 7, 2)
+  TEST (0, 1, 7, 2)
+  TEST (1, 1, 7, 2)
+  TEST (2, 1, 7, 2)
+  TEST (3, 1, 7, 2)
+  TEST (4, 1, 7, 2)
+  TEST (5, 1, 7, 2)
+  TEST (6, 1, 7, 2)
+  TEST (7, 1, 7, 2)
+  TEST (0, 2, 7, 2)
+  TEST (1, 2, 7, 2)
+  TEST (2, 2, 7, 2)
+  TEST (3, 2, 7, 2)
+  TEST (4, 2, 7, 2)
+  TEST (5, 2, 7, 2)
+  TEST (6, 2, 7, 2)
+  TEST (7, 2, 7, 2)
+  TEST (0, 3, 7, 2)
+  TEST (1, 3, 7, 2)
+  TEST (2, 3, 7, 2)
+  TEST (3, 3, 7, 2)
+  TEST (4, 3, 7, 2)
+  TEST (5, 3, 7, 2)
+  TEST (6, 3, 7, 2)
+  TEST (7, 3, 7, 2)
+  TEST (0, 4, 7, 2)
+  TEST (1, 4, 7, 2)
+  TEST (2, 4, 7, 2)
+  TEST (3, 4, 7, 2)
+  TEST (4, 4, 7, 2)
+  TEST (5, 4, 7, 2)
+  TEST (6, 4, 7, 2)
+  TEST (7, 4, 7, 2)
+  TEST (0, 5, 7, 2)
+  TEST (1, 5, 7, 2)
+  TEST (2, 5, 7, 2)
+  TEST (3, 5, 7, 2)
+  TEST (4, 5, 7, 2)
+  TEST (5, 5, 7, 2)
+  TEST (6, 5, 7, 2)
+  TEST (7, 5, 7, 2)
+  TEST (0, 6, 7, 2)
+  TEST (1, 6, 7, 2)
+  TEST (2, 6, 7, 2)
+  TEST (3, 6, 7, 2)
+  TEST (4, 6, 7, 2)
+  TEST (5, 6, 7, 2)
+  TEST (6, 6, 7, 2)
+  TEST (7, 6, 7, 2)
+  TEST (0, 7, 7, 2)
+  TEST (1, 7, 7, 2)
+  TEST (2, 7, 7, 2)
+  TEST (3, 7, 7, 2)
+  TEST (4, 7, 7, 2)
+  TEST (5, 7, 7, 2)
+  TEST (6, 7, 7, 2)
+  TEST (7, 7, 7, 2)
+}
+
+void check12(void)
+{
+  TEST (0, 0, 0, 3)
+  TEST (1, 0, 0, 3)
+  TEST (2, 0, 0, 3)
+  TEST (3, 0, 0, 3)
+  TEST (4, 0, 0, 3)
+  TEST (5, 0, 0, 3)
+  TEST (6, 0, 0, 3)
+  TEST (7, 0, 0, 3)
+  TEST (0, 1, 0, 3)
+  TEST (1, 1, 0, 3)
+  TEST (2, 1, 0, 3)
+  TEST (3, 1, 0, 3)
+  TEST (4, 1, 0, 3)
+  TEST (5, 1, 0, 3)
+  TEST (6, 1, 0, 3)
+  TEST (7, 1, 0, 3)
+  TEST (0, 2, 0, 3)
+  TEST (1, 2, 0, 3)
+  TEST (2, 2, 0, 3)
+  TEST (3, 2, 0, 3)
+  TEST (4, 2, 0, 3)
+  TEST (5, 2, 0, 3)
+  TEST (6, 2, 0, 3)
+  TEST (7, 2, 0, 3)
+  TEST (0, 3, 0, 3)
+  TEST (1, 3, 0, 3)
+  TEST (2, 3, 0, 3)
+  TEST (3, 3, 0, 3)
+  TEST (4, 3, 0, 3)
+  TEST (5, 3, 0, 3)
+  TEST (6, 3, 0, 3)
+  TEST (7, 3, 0, 3)
+  TEST (0, 4, 0, 3)
+  TEST (1, 4, 0, 3)
+  TEST (2, 4, 0, 3)
+  TEST (3, 4, 0, 3)
+  TEST (4, 4, 0, 3)
+  TEST (5, 4, 0, 3)
+  TEST (6, 4, 0, 3)
+  TEST (7, 4, 0, 3)
+  TEST (0, 5, 0, 3)
+  TEST (1, 5, 0, 3)
+  TEST (2, 5, 0, 3)
+  TEST (3, 5, 0, 3)
+  TEST (4, 5, 0, 3)
+  TEST (5, 5, 0, 3)
+  TEST (6, 5, 0, 3)
+  TEST (7, 5, 0, 3)
+  TEST (0, 6, 0, 3)
+  TEST (1, 6, 0, 3)
+  TEST (2, 6, 0, 3)
+  TEST (3, 6, 0, 3)
+  TEST (4, 6, 0, 3)
+  TEST (5, 6, 0, 3)
+  TEST (6, 6, 0, 3)
+  TEST (7, 6, 0, 3)
+  TEST (0, 7, 0, 3)
+  TEST (1, 7, 0, 3)
+  TEST (2, 7, 0, 3)
+  TEST (3, 7, 0, 3)
+  TEST (4, 7, 0, 3)
+  TEST (5, 7, 0, 3)
+  TEST (6, 7, 0, 3)
+  TEST (7, 7, 0, 3)
+  TEST (0, 0, 1, 3)
+  TEST (1, 0, 1, 3)
+  TEST (2, 0, 1, 3)
+  TEST (3, 0, 1, 3)
+  TEST (4, 0, 1, 3)
+  TEST (5, 0, 1, 3)
+  TEST (6, 0, 1, 3)
+  TEST (7, 0, 1, 3)
+  TEST (0, 1, 1, 3)
+  TEST (1, 1, 1, 3)
+  TEST (2, 1, 1, 3)
+  TEST (3, 1, 1, 3)
+  TEST (4, 1, 1, 3)
+  TEST (5, 1, 1, 3)
+  TEST (6, 1, 1, 3)
+  TEST (7, 1, 1, 3)
+  TEST (0, 2, 1, 3)
+  TEST (1, 2, 1, 3)
+  TEST (2, 2, 1, 3)
+  TEST (3, 2, 1, 3)
+  TEST (4, 2, 1, 3)
+  TEST (5, 2, 1, 3)
+  TEST (6, 2, 1, 3)
+  TEST (7, 2, 1, 3)
+  TEST (0, 3, 1, 3)
+  TEST (1, 3, 1, 3)
+  TEST (2, 3, 1, 3)
+  TEST (3, 3, 1, 3)
+  TEST (4, 3, 1, 3)
+  TEST (5, 3, 1, 3)
+  TEST (6, 3, 1, 3)
+  TEST (7, 3, 1, 3)
+  TEST (0, 4, 1, 3)
+  TEST (1, 4, 1, 3)
+  TEST (2, 4, 1, 3)
+  TEST (3, 4, 1, 3)
+  TEST (4, 4, 1, 3)
+  TEST (5, 4, 1, 3)
+  TEST (6, 4, 1, 3)
+  TEST (7, 4, 1, 3)
+  TEST (0, 5, 1, 3)
+  TEST (1, 5, 1, 3)
+  TEST (2, 5, 1, 3)
+  TEST (3, 5, 1, 3)
+  TEST (4, 5, 1, 3)
+  TEST (5, 5, 1, 3)
+  TEST (6, 5, 1, 3)
+  TEST (7, 5, 1, 3)
+  TEST (0, 6, 1, 3)
+  TEST (1, 6, 1, 3)
+  TEST (2, 6, 1, 3)
+  TEST (3, 6, 1, 3)
+  TEST (4, 6, 1, 3)
+  TEST (5, 6, 1, 3)
+  TEST (6, 6, 1, 3)
+  TEST (7, 6, 1, 3)
+  TEST (0, 7, 1, 3)
+  TEST (1, 7, 1, 3)
+  TEST (2, 7, 1, 3)
+  TEST (3, 7, 1, 3)
+  TEST (4, 7, 1, 3)
+  TEST (5, 7, 1, 3)
+  TEST (6, 7, 1, 3)
+  TEST (7, 7, 1, 3)
+}
+
+void check13(void)
+{
+  TEST (0, 0, 2, 3)
+  TEST (1, 0, 2, 3)
+  TEST (2, 0, 2, 3)
+  TEST (3, 0, 2, 3)
+  TEST (4, 0, 2, 3)
+  TEST (5, 0, 2, 3)
+  TEST (6, 0, 2, 3)
+  TEST (7, 0, 2, 3)
+  TEST (0, 1, 2, 3)
+  TEST (1, 1, 2, 3)
+  TEST (2, 1, 2, 3)
+  TEST (3, 1, 2, 3)
+  TEST (4, 1, 2, 3)
+  TEST (5, 1, 2, 3)
+  TEST (6, 1, 2, 3)
+  TEST (7, 1, 2, 3)
+  TEST (0, 2, 2, 3)
+  TEST (1, 2, 2, 3)
+  TEST (2, 2, 2, 3)
+  TEST (3, 2, 2, 3)
+  TEST (4, 2, 2, 3)
+  TEST (5, 2, 2, 3)
+  TEST (6, 2, 2, 3)
+  TEST (7, 2, 2, 3)
+  TEST (0, 3, 2, 3)
+  TEST (1, 3, 2, 3)
+  TEST (2, 3, 2, 3)
+  TEST (3, 3, 2, 3)
+  TEST (4, 3, 2, 3)
+  TEST (5, 3, 2, 3)
+  TEST (6, 3, 2, 3)
+  TEST (7, 3, 2, 3)
+  TEST (0, 4, 2, 3)
+  TEST (1, 4, 2, 3)
+  TEST (2, 4, 2, 3)
+  TEST (3, 4, 2, 3)
+  TEST (4, 4, 2, 3)
+  TEST (5, 4, 2, 3)
+  TEST (6, 4, 2, 3)
+  TEST (7, 4, 2, 3)
+  TEST (0, 5, 2, 3)
+  TEST (1, 5, 2, 3)
+  TEST (2, 5, 2, 3)
+  TEST (3, 5, 2, 3)
+  TEST (4, 5, 2, 3)
+  TEST (5, 5, 2, 3)
+  TEST (6, 5, 2, 3)
+  TEST (7, 5, 2, 3)
+  TEST (0, 6, 2, 3)
+  TEST (1, 6, 2, 3)
+  TEST (2, 6, 2, 3)
+  TEST (3, 6, 2, 3)
+  TEST (4, 6, 2, 3)
+  TEST (5, 6, 2, 3)
+  TEST (6, 6, 2, 3)
+  TEST (7, 6, 2, 3)
+  TEST (0, 7, 2, 3)
+  TEST (1, 7, 2, 3)
+  TEST (2, 7, 2, 3)
+  TEST (3, 7, 2, 3)
+  TEST (4, 7, 2, 3)
+  TEST (5, 7, 2, 3)
+  TEST (6, 7, 2, 3)
+  TEST (7, 7, 2, 3)
+  TEST (0, 0, 3, 3)
+  TEST (1, 0, 3, 3)
+  TEST (2, 0, 3, 3)
+  TEST (3, 0, 3, 3)
+  TEST (4, 0, 3, 3)
+  TEST (5, 0, 3, 3)
+  TEST (6, 0, 3, 3)
+  TEST (7, 0, 3, 3)
+  TEST (0, 1, 3, 3)
+  TEST (1, 1, 3, 3)
+  TEST (2, 1, 3, 3)
+  TEST (3, 1, 3, 3)
+  TEST (4, 1, 3, 3)
+  TEST (5, 1, 3, 3)
+  TEST (6, 1, 3, 3)
+  TEST (7, 1, 3, 3)
+  TEST (0, 2, 3, 3)
+  TEST (1, 2, 3, 3)
+  TEST (2, 2, 3, 3)
+  TEST (3, 2, 3, 3)
+  TEST (4, 2, 3, 3)
+  TEST (5, 2, 3, 3)
+  TEST (6, 2, 3, 3)
+  TEST (7, 2, 3, 3)
+  TEST (0, 3, 3, 3)
+  TEST (1, 3, 3, 3)
+  TEST (2, 3, 3, 3)
+  TEST (3, 3, 3, 3)
+  TEST (4, 3, 3, 3)
+  TEST (5, 3, 3, 3)
+  TEST (6, 3, 3, 3)
+  TEST (7, 3, 3, 3)
+  TEST (0, 4, 3, 3)
+  TEST (1, 4, 3, 3)
+  TEST (2, 4, 3, 3)
+  TEST (3, 4, 3, 3)
+  TEST (4, 4, 3, 3)
+  TEST (5, 4, 3, 3)
+  TEST (6, 4, 3, 3)
+  TEST (7, 4, 3, 3)
+  TEST (0, 5, 3, 3)
+  TEST (1, 5, 3, 3)
+  TEST (2, 5, 3, 3)
+  TEST (3, 5, 3, 3)
+  TEST (4, 5, 3, 3)
+  TEST (5, 5, 3, 3)
+  TEST (6, 5, 3, 3)
+  TEST (7, 5, 3, 3)
+  TEST (0, 6, 3, 3)
+  TEST (1, 6, 3, 3)
+  TEST (2, 6, 3, 3)
+  TEST (3, 6, 3, 3)
+  TEST (4, 6, 3, 3)
+  TEST (5, 6, 3, 3)
+  TEST (6, 6, 3, 3)
+  TEST (7, 6, 3, 3)
+  TEST (0, 7, 3, 3)
+  TEST (1, 7, 3, 3)
+  TEST (2, 7, 3, 3)
+  TEST (3, 7, 3, 3)
+  TEST (4, 7, 3, 3)
+  TEST (5, 7, 3, 3)
+  TEST (6, 7, 3, 3)
+  TEST (7, 7, 3, 3)
+}
+
+void check14(void)
+{
+  TEST (0, 0, 4, 3)
+  TEST (1, 0, 4, 3)
+  TEST (2, 0, 4, 3)
+  TEST (3, 0, 4, 3)
+  TEST (4, 0, 4, 3)
+  TEST (5, 0, 4, 3)
+  TEST (6, 0, 4, 3)
+  TEST (7, 0, 4, 3)
+  TEST (0, 1, 4, 3)
+  TEST (1, 1, 4, 3)
+  TEST (2, 1, 4, 3)
+  TEST (3, 1, 4, 3)
+  TEST (4, 1, 4, 3)
+  TEST (5, 1, 4, 3)
+  TEST (6, 1, 4, 3)
+  TEST (7, 1, 4, 3)
+  TEST (0, 2, 4, 3)
+  TEST (1, 2, 4, 3)
+  TEST (2, 2, 4, 3)
+  TEST (3, 2, 4, 3)
+  TEST (4, 2, 4, 3)
+  TEST (5, 2, 4, 3)
+  TEST (6, 2, 4, 3)
+  TEST (7, 2, 4, 3)
+  TEST (0, 3, 4, 3)
+  TEST (1, 3, 4, 3)
+  TEST (2, 3, 4, 3)
+  TEST (3, 3, 4, 3)
+  TEST (4, 3, 4, 3)
+  TEST (5, 3, 4, 3)
+  TEST (6, 3, 4, 3)
+  TEST (7, 3, 4, 3)
+  TEST (0, 4, 4, 3)
+  TEST (1, 4, 4, 3)
+  TEST (2, 4, 4, 3)
+  TEST (3, 4, 4, 3)
+  TEST (4, 4, 4, 3)
+  TEST (5, 4, 4, 3)
+  TEST (6, 4, 4, 3)
+  TEST (7, 4, 4, 3)
+  TEST (0, 5, 4, 3)
+  TEST (1, 5, 4, 3)
+  TEST (2, 5, 4, 3)
+  TEST (3, 5, 4, 3)
+  TEST (4, 5, 4, 3)
+  TEST (5, 5, 4, 3)
+  TEST (6, 5, 4, 3)
+  TEST (7, 5, 4, 3)
+  TEST (0, 6, 4, 3)
+  TEST (1, 6, 4, 3)
+  TEST (2, 6, 4, 3)
+  TEST (3, 6, 4, 3)
+  TEST (4, 6, 4, 3)
+  TEST (5, 6, 4, 3)
+  TEST (6, 6, 4, 3)
+  TEST (7, 6, 4, 3)
+  TEST (0, 7, 4, 3)
+  TEST (1, 7, 4, 3)
+  TEST (2, 7, 4, 3)
+  TEST (3, 7, 4, 3)
+  TEST (4, 7, 4, 3)
+  TEST (5, 7, 4, 3)
+  TEST (6, 7, 4, 3)
+  TEST (7, 7, 4, 3)
+  TEST (0, 0, 5, 3)
+  TEST (1, 0, 5, 3)
+  TEST (2, 0, 5, 3)
+  TEST (3, 0, 5, 3)
+  TEST (4, 0, 5, 3)
+  TEST (5, 0, 5, 3)
+  TEST (6, 0, 5, 3)
+  TEST (7, 0, 5, 3)
+  TEST (0, 1, 5, 3)
+  TEST (1, 1, 5, 3)
+  TEST (2, 1, 5, 3)
+  TEST (3, 1, 5, 3)
+  TEST (4, 1, 5, 3)
+  TEST (5, 1, 5, 3)
+  TEST (6, 1, 5, 3)
+  TEST (7, 1, 5, 3)
+  TEST (0, 2, 5, 3)
+  TEST (1, 2, 5, 3)
+  TEST (2, 2, 5, 3)
+  TEST (3, 2, 5, 3)
+  TEST (4, 2, 5, 3)
+  TEST (5, 2, 5, 3)
+  TEST (6, 2, 5, 3)
+  TEST (7, 2, 5, 3)
+  TEST (0, 3, 5, 3)
+  TEST (1, 3, 5, 3)
+  TEST (2, 3, 5, 3)
+  TEST (3, 3, 5, 3)
+  TEST (4, 3, 5, 3)
+  TEST (5, 3, 5, 3)
+  TEST (6, 3, 5, 3)
+  TEST (7, 3, 5, 3)
+  TEST (0, 4, 5, 3)
+  TEST (1, 4, 5, 3)
+  TEST (2, 4, 5, 3)
+  TEST (3, 4, 5, 3)
+  TEST (4, 4, 5, 3)
+  TEST (5, 4, 5, 3)
+  TEST (6, 4, 5, 3)
+  TEST (7, 4, 5, 3)
+  TEST (0, 5, 5, 3)
+  TEST (1, 5, 5, 3)
+  TEST (2, 5, 5, 3)
+  TEST (3, 5, 5, 3)
+  TEST (4, 5, 5, 3)
+  TEST (5, 5, 5, 3)
+  TEST (6, 5, 5, 3)
+  TEST (7, 5, 5, 3)
+  TEST (0, 6, 5, 3)
+  TEST (1, 6, 5, 3)
+  TEST (2, 6, 5, 3)
+  TEST (3, 6, 5, 3)
+  TEST (4, 6, 5, 3)
+  TEST (5, 6, 5, 3)
+  TEST (6, 6, 5, 3)
+  TEST (7, 6, 5, 3)
+  TEST (0, 7, 5, 3)
+  TEST (1, 7, 5, 3)
+  TEST (2, 7, 5, 3)
+  TEST (3, 7, 5, 3)
+  TEST (4, 7, 5, 3)
+  TEST (5, 7, 5, 3)
+  TEST (6, 7, 5, 3)
+  TEST (7, 7, 5, 3)
+}
+
+void check15(void)
+{
+  TEST (0, 0, 6, 3)
+  TEST (1, 0, 6, 3)
+  TEST (2, 0, 6, 3)
+  TEST (3, 0, 6, 3)
+  TEST (4, 0, 6, 3)
+  TEST (5, 0, 6, 3)
+  TEST (6, 0, 6, 3)
+  TEST (7, 0, 6, 3)
+  TEST (0, 1, 6, 3)
+  TEST (1, 1, 6, 3)
+  TEST (2, 1, 6, 3)
+  TEST (3, 1, 6, 3)
+  TEST (4, 1, 6, 3)
+  TEST (5, 1, 6, 3)
+  TEST (6, 1, 6, 3)
+  TEST (7, 1, 6, 3)
+  TEST (0, 2, 6, 3)
+  TEST (1, 2, 6, 3)
+  TEST (2, 2, 6, 3)
+  TEST (3, 2, 6, 3)
+  TEST (4, 2, 6, 3)
+  TEST (5, 2, 6, 3)
+  TEST (6, 2, 6, 3)
+  TEST (7, 2, 6, 3)
+  TEST (0, 3, 6, 3)
+  TEST (1, 3, 6, 3)
+  TEST (2, 3, 6, 3)
+  TEST (3, 3, 6, 3)
+  TEST (4, 3, 6, 3)
+  TEST (5, 3, 6, 3)
+  TEST (6, 3, 6, 3)
+  TEST (7, 3, 6, 3)
+  TEST (0, 4, 6, 3)
+  TEST (1, 4, 6, 3)
+  TEST (2, 4, 6, 3)
+  TEST (3, 4, 6, 3)
+  TEST (4, 4, 6, 3)
+  TEST (5, 4, 6, 3)
+  TEST (6, 4, 6, 3)
+  TEST (7, 4, 6, 3)
+  TEST (0, 5, 6, 3)
+  TEST (1, 5, 6, 3)
+  TEST (2, 5, 6, 3)
+  TEST (3, 5, 6, 3)
+  TEST (4, 5, 6, 3)
+  TEST (5, 5, 6, 3)
+  TEST (6, 5, 6, 3)
+  TEST (7, 5, 6, 3)
+  TEST (0, 6, 6, 3)
+  TEST (1, 6, 6, 3)
+  TEST (2, 6, 6, 3)
+  TEST (3, 6, 6, 3)
+  TEST (4, 6, 6, 3)
+  TEST (5, 6, 6, 3)
+  TEST (6, 6, 6, 3)
+  TEST (7, 6, 6, 3)
+  TEST (0, 7, 6, 3)
+  TEST (1, 7, 6, 3)
+  TEST (2, 7, 6, 3)
+  TEST (3, 7, 6, 3)
+  TEST (4, 7, 6, 3)
+  TEST (5, 7, 6, 3)
+  TEST (6, 7, 6, 3)
+  TEST (7, 7, 6, 3)
+  TEST (0, 0, 7, 3)
+  TEST (1, 0, 7, 3)
+  TEST (2, 0, 7, 3)
+  TEST (3, 0, 7, 3)
+  TEST (4, 0, 7, 3)
+  TEST (5, 0, 7, 3)
+  TEST (6, 0, 7, 3)
+  TEST (7, 0, 7, 3)
+  TEST (0, 1, 7, 3)
+  TEST (1, 1, 7, 3)
+  TEST (2, 1, 7, 3)
+  TEST (3, 1, 7, 3)
+  TEST (4, 1, 7, 3)
+  TEST (5, 1, 7, 3)
+  TEST (6, 1, 7, 3)
+  TEST (7, 1, 7, 3)
+  TEST (0, 2, 7, 3)
+  TEST (1, 2, 7, 3)
+  TEST (2, 2, 7, 3)
+  TEST (3, 2, 7, 3)
+  TEST (4, 2, 7, 3)
+  TEST (5, 2, 7, 3)
+  TEST (6, 2, 7, 3)
+  TEST (7, 2, 7, 3)
+  TEST (0, 3, 7, 3)
+  TEST (1, 3, 7, 3)
+  TEST (2, 3, 7, 3)
+  TEST (3, 3, 7, 3)
+  TEST (4, 3, 7, 3)
+  TEST (5, 3, 7, 3)
+  TEST (6, 3, 7, 3)
+  TEST (7, 3, 7, 3)
+  TEST (0, 4, 7, 3)
+  TEST (1, 4, 7, 3)
+  TEST (2, 4, 7, 3)
+  TEST (3, 4, 7, 3)
+  TEST (4, 4, 7, 3)
+  TEST (5, 4, 7, 3)
+  TEST (6, 4, 7, 3)
+  TEST (7, 4, 7, 3)
+  TEST (0, 5, 7, 3)
+  TEST (1, 5, 7, 3)
+  TEST (2, 5, 7, 3)
+  TEST (3, 5, 7, 3)
+  TEST (4, 5, 7, 3)
+  TEST (5, 5, 7, 3)
+  TEST (6, 5, 7, 3)
+  TEST (7, 5, 7, 3)
+  TEST (0, 6, 7, 3)
+  TEST (1, 6, 7, 3)
+  TEST (2, 6, 7, 3)
+  TEST (3, 6, 7, 3)
+  TEST (4, 6, 7, 3)
+  TEST (5, 6, 7, 3)
+  TEST (6, 6, 7, 3)
+  TEST (7, 6, 7, 3)
+  TEST (0, 7, 7, 3)
+  TEST (1, 7, 7, 3)
+  TEST (2, 7, 7, 3)
+  TEST (3, 7, 7, 3)
+  TEST (4, 7, 7, 3)
+  TEST (5, 7, 7, 3)
+  TEST (6, 7, 7, 3)
+  TEST (7, 7, 7, 3)
+}
+
+void check16(void)
+{
+  TEST (0, 0, 0, 4)
+  TEST (1, 0, 0, 4)
+  TEST (2, 0, 0, 4)
+  TEST (3, 0, 0, 4)
+  TEST (4, 0, 0, 4)
+  TEST (5, 0, 0, 4)
+  TEST (6, 0, 0, 4)
+  TEST (7, 0, 0, 4)
+  TEST (0, 1, 0, 4)
+  TEST (1, 1, 0, 4)
+  TEST (2, 1, 0, 4)
+  TEST (3, 1, 0, 4)
+  TEST (4, 1, 0, 4)
+  TEST (5, 1, 0, 4)
+  TEST (6, 1, 0, 4)
+  TEST (7, 1, 0, 4)
+  TEST (0, 2, 0, 4)
+  TEST (1, 2, 0, 4)
+  TEST (2, 2, 0, 4)
+  TEST (3, 2, 0, 4)
+  TEST (4, 2, 0, 4)
+  TEST (5, 2, 0, 4)
+  TEST (6, 2, 0, 4)
+  TEST (7, 2, 0, 4)
+  TEST (0, 3, 0, 4)
+  TEST (1, 3, 0, 4)
+  TEST (2, 3, 0, 4)
+  TEST (3, 3, 0, 4)
+  TEST (4, 3, 0, 4)
+  TEST (5, 3, 0, 4)
+  TEST (6, 3, 0, 4)
+  TEST (7, 3, 0, 4)
+  TEST (0, 4, 0, 4)
+  TEST (1, 4, 0, 4)
+  TEST (2, 4, 0, 4)
+  TEST (3, 4, 0, 4)
+  TEST (4, 4, 0, 4)
+  TEST (5, 4, 0, 4)
+  TEST (6, 4, 0, 4)
+  TEST (7, 4, 0, 4)
+  TEST (0, 5, 0, 4)
+  TEST (1, 5, 0, 4)
+  TEST (2, 5, 0, 4)
+  TEST (3, 5, 0, 4)
+  TEST (4, 5, 0, 4)
+  TEST (5, 5, 0, 4)
+  TEST (6, 5, 0, 4)
+  TEST (7, 5, 0, 4)
+  TEST (0, 6, 0, 4)
+  TEST (1, 6, 0, 4)
+  TEST (2, 6, 0, 4)
+  TEST (3, 6, 0, 4)
+  TEST (4, 6, 0, 4)
+  TEST (5, 6, 0, 4)
+  TEST (6, 6, 0, 4)
+  TEST (7, 6, 0, 4)
+  TEST (0, 7, 0, 4)
+  TEST (1, 7, 0, 4)
+  TEST (2, 7, 0, 4)
+  TEST (3, 7, 0, 4)
+  TEST (4, 7, 0, 4)
+  TEST (5, 7, 0, 4)
+  TEST (6, 7, 0, 4)
+  TEST (7, 7, 0, 4)
+  TEST (0, 0, 1, 4)
+  TEST (1, 0, 1, 4)
+  TEST (2, 0, 1, 4)
+  TEST (3, 0, 1, 4)
+  TEST (4, 0, 1, 4)
+  TEST (5, 0, 1, 4)
+  TEST (6, 0, 1, 4)
+  TEST (7, 0, 1, 4)
+  TEST (0, 1, 1, 4)
+  TEST (1, 1, 1, 4)
+  TEST (2, 1, 1, 4)
+  TEST (3, 1, 1, 4)
+  TEST (4, 1, 1, 4)
+  TEST (5, 1, 1, 4)
+  TEST (6, 1, 1, 4)
+  TEST (7, 1, 1, 4)
+  TEST (0, 2, 1, 4)
+  TEST (1, 2, 1, 4)
+  TEST (2, 2, 1, 4)
+  TEST (3, 2, 1, 4)
+  TEST (4, 2, 1, 4)
+  TEST (5, 2, 1, 4)
+  TEST (6, 2, 1, 4)
+  TEST (7, 2, 1, 4)
+  TEST (0, 3, 1, 4)
+  TEST (1, 3, 1, 4)
+  TEST (2, 3, 1, 4)
+  TEST (3, 3, 1, 4)
+  TEST (4, 3, 1, 4)
+  TEST (5, 3, 1, 4)
+  TEST (6, 3, 1, 4)
+  TEST (7, 3, 1, 4)
+  TEST (0, 4, 1, 4)
+  TEST (1, 4, 1, 4)
+  TEST (2, 4, 1, 4)
+  TEST (3, 4, 1, 4)
+  TEST (4, 4, 1, 4)
+  TEST (5, 4, 1, 4)
+  TEST (6, 4, 1, 4)
+  TEST (7, 4, 1, 4)
+  TEST (0, 5, 1, 4)
+  TEST (1, 5, 1, 4)
+  TEST (2, 5, 1, 4)
+  TEST (3, 5, 1, 4)
+  TEST (4, 5, 1, 4)
+  TEST (5, 5, 1, 4)
+  TEST (6, 5, 1, 4)
+  TEST (7, 5, 1, 4)
+  TEST (0, 6, 1, 4)
+  TEST (1, 6, 1, 4)
+  TEST (2, 6, 1, 4)
+  TEST (3, 6, 1, 4)
+  TEST (4, 6, 1, 4)
+  TEST (5, 6, 1, 4)
+  TEST (6, 6, 1, 4)
+  TEST (7, 6, 1, 4)
+  TEST (0, 7, 1, 4)
+  TEST (1, 7, 1, 4)
+  TEST (2, 7, 1, 4)
+  TEST (3, 7, 1, 4)
+  TEST (4, 7, 1, 4)
+  TEST (5, 7, 1, 4)
+  TEST (6, 7, 1, 4)
+  TEST (7, 7, 1, 4)
+}
+
+void check17(void)
+{
+  TEST (0, 0, 2, 4)
+  TEST (1, 0, 2, 4)
+  TEST (2, 0, 2, 4)
+  TEST (3, 0, 2, 4)
+  TEST (4, 0, 2, 4)
+  TEST (5, 0, 2, 4)
+  TEST (6, 0, 2, 4)
+  TEST (7, 0, 2, 4)
+  TEST (0, 1, 2, 4)
+  TEST (1, 1, 2, 4)
+  TEST (2, 1, 2, 4)
+  TEST (3, 1, 2, 4)
+  TEST (4, 1, 2, 4)
+  TEST (5, 1, 2, 4)
+  TEST (6, 1, 2, 4)
+  TEST (7, 1, 2, 4)
+  TEST (0, 2, 2, 4)
+  TEST (1, 2, 2, 4)
+  TEST (2, 2, 2, 4)
+  TEST (3, 2, 2, 4)
+  TEST (4, 2, 2, 4)
+  TEST (5, 2, 2, 4)
+  TEST (6, 2, 2, 4)
+  TEST (7, 2, 2, 4)
+  TEST (0, 3, 2, 4)
+  TEST (1, 3, 2, 4)
+  TEST (2, 3, 2, 4)
+  TEST (3, 3, 2, 4)
+  TEST (4, 3, 2, 4)
+  TEST (5, 3, 2, 4)
+  TEST (6, 3, 2, 4)
+  TEST (7, 3, 2, 4)
+  TEST (0, 4, 2, 4)
+  TEST (1, 4, 2, 4)
+  TEST (2, 4, 2, 4)
+  TEST (3, 4, 2, 4)
+  TEST (4, 4, 2, 4)
+  TEST (5, 4, 2, 4)
+  TEST (6, 4, 2, 4)
+  TEST (7, 4, 2, 4)
+  TEST (0, 5, 2, 4)
+  TEST (1, 5, 2, 4)
+  TEST (2, 5, 2, 4)
+  TEST (3, 5, 2, 4)
+  TEST (4, 5, 2, 4)
+  TEST (5, 5, 2, 4)
+  TEST (6, 5, 2, 4)
+  TEST (7, 5, 2, 4)
+  TEST (0, 6, 2, 4)
+  TEST (1, 6, 2, 4)
+  TEST (2, 6, 2, 4)
+  TEST (3, 6, 2, 4)
+  TEST (4, 6, 2, 4)
+  TEST (5, 6, 2, 4)
+  TEST (6, 6, 2, 4)
+  TEST (7, 6, 2, 4)
+  TEST (0, 7, 2, 4)
+  TEST (1, 7, 2, 4)
+  TEST (2, 7, 2, 4)
+  TEST (3, 7, 2, 4)
+  TEST (4, 7, 2, 4)
+  TEST (5, 7, 2, 4)
+  TEST (6, 7, 2, 4)
+  TEST (7, 7, 2, 4)
+  TEST (0, 0, 3, 4)
+  TEST (1, 0, 3, 4)
+  TEST (2, 0, 3, 4)
+  TEST (3, 0, 3, 4)
+  TEST (4, 0, 3, 4)
+  TEST (5, 0, 3, 4)
+  TEST (6, 0, 3, 4)
+  TEST (7, 0, 3, 4)
+  TEST (0, 1, 3, 4)
+  TEST (1, 1, 3, 4)
+  TEST (2, 1, 3, 4)
+  TEST (3, 1, 3, 4)
+  TEST (4, 1, 3, 4)
+  TEST (5, 1, 3, 4)
+  TEST (6, 1, 3, 4)
+  TEST (7, 1, 3, 4)
+  TEST (0, 2, 3, 4)
+  TEST (1, 2, 3, 4)
+  TEST (2, 2, 3, 4)
+  TEST (3, 2, 3, 4)
+  TEST (4, 2, 3, 4)
+  TEST (5, 2, 3, 4)
+  TEST (6, 2, 3, 4)
+  TEST (7, 2, 3, 4)
+  TEST (0, 3, 3, 4)
+  TEST (1, 3, 3, 4)
+  TEST (2, 3, 3, 4)
+  TEST (3, 3, 3, 4)
+  TEST (4, 3, 3, 4)
+  TEST (5, 3, 3, 4)
+  TEST (6, 3, 3, 4)
+  TEST (7, 3, 3, 4)
+  TEST (0, 4, 3, 4)
+  TEST (1, 4, 3, 4)
+  TEST (2, 4, 3, 4)
+  TEST (3, 4, 3, 4)
+  TEST (4, 4, 3, 4)
+  TEST (5, 4, 3, 4)
+  TEST (6, 4, 3, 4)
+  TEST (7, 4, 3, 4)
+  TEST (0, 5, 3, 4)
+  TEST (1, 5, 3, 4)
+  TEST (2, 5, 3, 4)
+  TEST (3, 5, 3, 4)
+  TEST (4, 5, 3, 4)
+  TEST (5, 5, 3, 4)
+  TEST (6, 5, 3, 4)
+  TEST (7, 5, 3, 4)
+  TEST (0, 6, 3, 4)
+  TEST (1, 6, 3, 4)
+  TEST (2, 6, 3, 4)
+  TEST (3, 6, 3, 4)
+  TEST (4, 6, 3, 4)
+  TEST (5, 6, 3, 4)
+  TEST (6, 6, 3, 4)
+  TEST (7, 6, 3, 4)
+  TEST (0, 7, 3, 4)
+  TEST (1, 7, 3, 4)
+  TEST (2, 7, 3, 4)
+  TEST (3, 7, 3, 4)
+  TEST (4, 7, 3, 4)
+  TEST (5, 7, 3, 4)
+  TEST (6, 7, 3, 4)
+  TEST (7, 7, 3, 4)
+}
+
+void check18(void)
+{
+  TEST (0, 0, 4, 4)
+  TEST (1, 0, 4, 4)
+  TEST (2, 0, 4, 4)
+  TEST (3, 0, 4, 4)
+  TEST (4, 0, 4, 4)
+  TEST (5, 0, 4, 4)
+  TEST (6, 0, 4, 4)
+  TEST (7, 0, 4, 4)
+  TEST (0, 1, 4, 4)
+  TEST (1, 1, 4, 4)
+  TEST (2, 1, 4, 4)
+  TEST (3, 1, 4, 4)
+  TEST (4, 1, 4, 4)
+  TEST (5, 1, 4, 4)
+  TEST (6, 1, 4, 4)
+  TEST (7, 1, 4, 4)
+  TEST (0, 2, 4, 4)
+  TEST (1, 2, 4, 4)
+  TEST (2, 2, 4, 4)
+  TEST (3, 2, 4, 4)
+  TEST (4, 2, 4, 4)
+  TEST (5, 2, 4, 4)
+  TEST (6, 2, 4, 4)
+  TEST (7, 2, 4, 4)
+  TEST (0, 3, 4, 4)
+  TEST (1, 3, 4, 4)
+  TEST (2, 3, 4, 4)
+  TEST (3, 3, 4, 4)
+  TEST (4, 3, 4, 4)
+  TEST (5, 3, 4, 4)
+  TEST (6, 3, 4, 4)
+  TEST (7, 3, 4, 4)
+  TEST (0, 4, 4, 4)
+  TEST (1, 4, 4, 4)
+  TEST (2, 4, 4, 4)
+  TEST (3, 4, 4, 4)
+  TEST (4, 4, 4, 4)
+  TEST (5, 4, 4, 4)
+  TEST (6, 4, 4, 4)
+  TEST (7, 4, 4, 4)
+  TEST (0, 5, 4, 4)
+  TEST (1, 5, 4, 4)
+  TEST (2, 5, 4, 4)
+  TEST (3, 5, 4, 4)
+  TEST (4, 5, 4, 4)
+  TEST (5, 5, 4, 4)
+  TEST (6, 5, 4, 4)
+  TEST (7, 5, 4, 4)
+  TEST (0, 6, 4, 4)
+  TEST (1, 6, 4, 4)
+  TEST (2, 6, 4, 4)
+  TEST (3, 6, 4, 4)
+  TEST (4, 6, 4, 4)
+  TEST (5, 6, 4, 4)
+  TEST (6, 6, 4, 4)
+  TEST (7, 6, 4, 4)
+  TEST (0, 7, 4, 4)
+  TEST (1, 7, 4, 4)
+  TEST (2, 7, 4, 4)
+  TEST (3, 7, 4, 4)
+  TEST (4, 7, 4, 4)
+  TEST (5, 7, 4, 4)
+  TEST (6, 7, 4, 4)
+  TEST (7, 7, 4, 4)
+  TEST (0, 0, 5, 4)
+  TEST (1, 0, 5, 4)
+  TEST (2, 0, 5, 4)
+  TEST (3, 0, 5, 4)
+  TEST (4, 0, 5, 4)
+  TEST (5, 0, 5, 4)
+  TEST (6, 0, 5, 4)
+  TEST (7, 0, 5, 4)
+  TEST (0, 1, 5, 4)
+  TEST (1, 1, 5, 4)
+  TEST (2, 1, 5, 4)
+  TEST (3, 1, 5, 4)
+  TEST (4, 1, 5, 4)
+  TEST (5, 1, 5, 4)
+  TEST (6, 1, 5, 4)
+  TEST (7, 1, 5, 4)
+  TEST (0, 2, 5, 4)
+  TEST (1, 2, 5, 4)
+  TEST (2, 2, 5, 4)
+  TEST (3, 2, 5, 4)
+  TEST (4, 2, 5, 4)
+  TEST (5, 2, 5, 4)
+  TEST (6, 2, 5, 4)
+  TEST (7, 2, 5, 4)
+  TEST (0, 3, 5, 4)
+  TEST (1, 3, 5, 4)
+  TEST (2, 3, 5, 4)
+  TEST (3, 3, 5, 4)
+  TEST (4, 3, 5, 4)
+  TEST (5, 3, 5, 4)
+  TEST (6, 3, 5, 4)
+  TEST (7, 3, 5, 4)
+  TEST (0, 4, 5, 4)
+  TEST (1, 4, 5, 4)
+  TEST (2, 4, 5, 4)
+  TEST (3, 4, 5, 4)
+  TEST (4, 4, 5, 4)
+  TEST (5, 4, 5, 4)
+  TEST (6, 4, 5, 4)
+  TEST (7, 4, 5, 4)
+  TEST (0, 5, 5, 4)
+  TEST (1, 5, 5, 4)
+  TEST (2, 5, 5, 4)
+  TEST (3, 5, 5, 4)
+  TEST (4, 5, 5, 4)
+  TEST (5, 5, 5, 4)
+  TEST (6, 5, 5, 4)
+  TEST (7, 5, 5, 4)
+  TEST (0, 6, 5, 4)
+  TEST (1, 6, 5, 4)
+  TEST (2, 6, 5, 4)
+  TEST (3, 6, 5, 4)
+  TEST (4, 6, 5, 4)
+  TEST (5, 6, 5, 4)
+  TEST (6, 6, 5, 4)
+  TEST (7, 6, 5, 4)
+  TEST (0, 7, 5, 4)
+  TEST (1, 7, 5, 4)
+  TEST (2, 7, 5, 4)
+  TEST (3, 7, 5, 4)
+  TEST (4, 7, 5, 4)
+  TEST (5, 7, 5, 4)
+  TEST (6, 7, 5, 4)
+  TEST (7, 7, 5, 4)
+}
+
+void check19(void)
+{
+  TEST (0, 0, 6, 4)
+  TEST (1, 0, 6, 4)
+  TEST (2, 0, 6, 4)
+  TEST (3, 0, 6, 4)
+  TEST (4, 0, 6, 4)
+  TEST (5, 0, 6, 4)
+  TEST (6, 0, 6, 4)
+  TEST (7, 0, 6, 4)
+  TEST (0, 1, 6, 4)
+  TEST (1, 1, 6, 4)
+  TEST (2, 1, 6, 4)
+  TEST (3, 1, 6, 4)
+  TEST (4, 1, 6, 4)
+  TEST (5, 1, 6, 4)
+  TEST (6, 1, 6, 4)
+  TEST (7, 1, 6, 4)
+  TEST (0, 2, 6, 4)
+  TEST (1, 2, 6, 4)
+  TEST (2, 2, 6, 4)
+  TEST (3, 2, 6, 4)
+  TEST (4, 2, 6, 4)
+  TEST (5, 2, 6, 4)
+  TEST (6, 2, 6, 4)
+  TEST (7, 2, 6, 4)
+  TEST (0, 3, 6, 4)
+  TEST (1, 3, 6, 4)
+  TEST (2, 3, 6, 4)
+  TEST (3, 3, 6, 4)
+  TEST (4, 3, 6, 4)
+  TEST (5, 3, 6, 4)
+  TEST (6, 3, 6, 4)
+  TEST (7, 3, 6, 4)
+  TEST (0, 4, 6, 4)
+  TEST (1, 4, 6, 4)
+  TEST (2, 4, 6, 4)
+  TEST (3, 4, 6, 4)
+  TEST (4, 4, 6, 4)
+  TEST (5, 4, 6, 4)
+  TEST (6, 4, 6, 4)
+  TEST (7, 4, 6, 4)
+  TEST (0, 5, 6, 4)
+  TEST (1, 5, 6, 4)
+  TEST (2, 5, 6, 4)
+  TEST (3, 5, 6, 4)
+  TEST (4, 5, 6, 4)
+  TEST (5, 5, 6, 4)
+  TEST (6, 5, 6, 4)
+  TEST (7, 5, 6, 4)
+  TEST (0, 6, 6, 4)
+  TEST (1, 6, 6, 4)
+  TEST (2, 6, 6, 4)
+  TEST (3, 6, 6, 4)
+  TEST (4, 6, 6, 4)
+  TEST (5, 6, 6, 4)
+  TEST (6, 6, 6, 4)
+  TEST (7, 6, 6, 4)
+  TEST (0, 7, 6, 4)
+  TEST (1, 7, 6, 4)
+  TEST (2, 7, 6, 4)
+  TEST (3, 7, 6, 4)
+  TEST (4, 7, 6, 4)
+  TEST (5, 7, 6, 4)
+  TEST (6, 7, 6, 4)
+  TEST (7, 7, 6, 4)
+  TEST (0, 0, 7, 4)
+  TEST (1, 0, 7, 4)
+  TEST (2, 0, 7, 4)
+  TEST (3, 0, 7, 4)
+  TEST (4, 0, 7, 4)
+  TEST (5, 0, 7, 4)
+  TEST (6, 0, 7, 4)
+  TEST (7, 0, 7, 4)
+  TEST (0, 1, 7, 4)
+  TEST (1, 1, 7, 4)
+  TEST (2, 1, 7, 4)
+  TEST (3, 1, 7, 4)
+  TEST (4, 1, 7, 4)
+  TEST (5, 1, 7, 4)
+  TEST (6, 1, 7, 4)
+  TEST (7, 1, 7, 4)
+  TEST (0, 2, 7, 4)
+  TEST (1, 2, 7, 4)
+  TEST (2, 2, 7, 4)
+  TEST (3, 2, 7, 4)
+  TEST (4, 2, 7, 4)
+  TEST (5, 2, 7, 4)
+  TEST (6, 2, 7, 4)
+  TEST (7, 2, 7, 4)
+  TEST (0, 3, 7, 4)
+  TEST (1, 3, 7, 4)
+  TEST (2, 3, 7, 4)
+  TEST (3, 3, 7, 4)
+  TEST (4, 3, 7, 4)
+  TEST (5, 3, 7, 4)
+  TEST (6, 3, 7, 4)
+  TEST (7, 3, 7, 4)
+  TEST (0, 4, 7, 4)
+  TEST (1, 4, 7, 4)
+  TEST (2, 4, 7, 4)
+  TEST (3, 4, 7, 4)
+  TEST (4, 4, 7, 4)
+  TEST (5, 4, 7, 4)
+  TEST (6, 4, 7, 4)
+  TEST (7, 4, 7, 4)
+  TEST (0, 5, 7, 4)
+  TEST (1, 5, 7, 4)
+  TEST (2, 5, 7, 4)
+  TEST (3, 5, 7, 4)
+  TEST (4, 5, 7, 4)
+  TEST (5, 5, 7, 4)
+  TEST (6, 5, 7, 4)
+  TEST (7, 5, 7, 4)
+  TEST (0, 6, 7, 4)
+  TEST (1, 6, 7, 4)
+  TEST (2, 6, 7, 4)
+  TEST (3, 6, 7, 4)
+  TEST (4, 6, 7, 4)
+  TEST (5, 6, 7, 4)
+  TEST (6, 6, 7, 4)
+  TEST (7, 6, 7, 4)
+  TEST (0, 7, 7, 4)
+  TEST (1, 7, 7, 4)
+  TEST (2, 7, 7, 4)
+  TEST (3, 7, 7, 4)
+  TEST (4, 7, 7, 4)
+  TEST (5, 7, 7, 4)
+  TEST (6, 7, 7, 4)
+  TEST (7, 7, 7, 4)
+}
+
+void check20(void)
+{
+  TEST (0, 0, 0, 5)
+  TEST (1, 0, 0, 5)
+  TEST (2, 0, 0, 5)
+  TEST (3, 0, 0, 5)
+  TEST (4, 0, 0, 5)
+  TEST (5, 0, 0, 5)
+  TEST (6, 0, 0, 5)
+  TEST (7, 0, 0, 5)
+  TEST (0, 1, 0, 5)
+  TEST (1, 1, 0, 5)
+  TEST (2, 1, 0, 5)
+  TEST (3, 1, 0, 5)
+  TEST (4, 1, 0, 5)
+  TEST (5, 1, 0, 5)
+  TEST (6, 1, 0, 5)
+  TEST (7, 1, 0, 5)
+  TEST (0, 2, 0, 5)
+  TEST (1, 2, 0, 5)
+  TEST (2, 2, 0, 5)
+  TEST (3, 2, 0, 5)
+  TEST (4, 2, 0, 5)
+  TEST (5, 2, 0, 5)
+  TEST (6, 2, 0, 5)
+  TEST (7, 2, 0, 5)
+  TEST (0, 3, 0, 5)
+  TEST (1, 3, 0, 5)
+  TEST (2, 3, 0, 5)
+  TEST (3, 3, 0, 5)
+  TEST (4, 3, 0, 5)
+  TEST (5, 3, 0, 5)
+  TEST (6, 3, 0, 5)
+  TEST (7, 3, 0, 5)
+  TEST (0, 4, 0, 5)
+  TEST (1, 4, 0, 5)
+  TEST (2, 4, 0, 5)
+  TEST (3, 4, 0, 5)
+  TEST (4, 4, 0, 5)
+  TEST (5, 4, 0, 5)
+  TEST (6, 4, 0, 5)
+  TEST (7, 4, 0, 5)
+  TEST (0, 5, 0, 5)
+  TEST (1, 5, 0, 5)
+  TEST (2, 5, 0, 5)
+  TEST (3, 5, 0, 5)
+  TEST (4, 5, 0, 5)
+  TEST (5, 5, 0, 5)
+  TEST (6, 5, 0, 5)
+  TEST (7, 5, 0, 5)
+  TEST (0, 6, 0, 5)
+  TEST (1, 6, 0, 5)
+  TEST (2, 6, 0, 5)
+  TEST (3, 6, 0, 5)
+  TEST (4, 6, 0, 5)
+  TEST (5, 6, 0, 5)
+  TEST (6, 6, 0, 5)
+  TEST (7, 6, 0, 5)
+  TEST (0, 7, 0, 5)
+  TEST (1, 7, 0, 5)
+  TEST (2, 7, 0, 5)
+  TEST (3, 7, 0, 5)
+  TEST (4, 7, 0, 5)
+  TEST (5, 7, 0, 5)
+  TEST (6, 7, 0, 5)
+  TEST (7, 7, 0, 5)
+  TEST (0, 0, 1, 5)
+  TEST (1, 0, 1, 5)
+  TEST (2, 0, 1, 5)
+  TEST (3, 0, 1, 5)
+  TEST (4, 0, 1, 5)
+  TEST (5, 0, 1, 5)
+  TEST (6, 0, 1, 5)
+  TEST (7, 0, 1, 5)
+  TEST (0, 1, 1, 5)
+  TEST (1, 1, 1, 5)
+  TEST (2, 1, 1, 5)
+  TEST (3, 1, 1, 5)
+  TEST (4, 1, 1, 5)
+  TEST (5, 1, 1, 5)
+  TEST (6, 1, 1, 5)
+  TEST (7, 1, 1, 5)
+  TEST (0, 2, 1, 5)
+  TEST (1, 2, 1, 5)
+  TEST (2, 2, 1, 5)
+  TEST (3, 2, 1, 5)
+  TEST (4, 2, 1, 5)
+  TEST (5, 2, 1, 5)
+  TEST (6, 2, 1, 5)
+  TEST (7, 2, 1, 5)
+  TEST (0, 3, 1, 5)
+  TEST (1, 3, 1, 5)
+  TEST (2, 3, 1, 5)
+  TEST (3, 3, 1, 5)
+  TEST (4, 3, 1, 5)
+  TEST (5, 3, 1, 5)
+  TEST (6, 3, 1, 5)
+  TEST (7, 3, 1, 5)
+  TEST (0, 4, 1, 5)
+  TEST (1, 4, 1, 5)
+  TEST (2, 4, 1, 5)
+  TEST (3, 4, 1, 5)
+  TEST (4, 4, 1, 5)
+  TEST (5, 4, 1, 5)
+  TEST (6, 4, 1, 5)
+  TEST (7, 4, 1, 5)
+  TEST (0, 5, 1, 5)
+  TEST (1, 5, 1, 5)
+  TEST (2, 5, 1, 5)
+  TEST (3, 5, 1, 5)
+  TEST (4, 5, 1, 5)
+  TEST (5, 5, 1, 5)
+  TEST (6, 5, 1, 5)
+  TEST (7, 5, 1, 5)
+  TEST (0, 6, 1, 5)
+  TEST (1, 6, 1, 5)
+  TEST (2, 6, 1, 5)
+  TEST (3, 6, 1, 5)
+  TEST (4, 6, 1, 5)
+  TEST (5, 6, 1, 5)
+  TEST (6, 6, 1, 5)
+  TEST (7, 6, 1, 5)
+  TEST (0, 7, 1, 5)
+  TEST (1, 7, 1, 5)
+  TEST (2, 7, 1, 5)
+  TEST (3, 7, 1, 5)
+  TEST (4, 7, 1, 5)
+  TEST (5, 7, 1, 5)
+  TEST (6, 7, 1, 5)
+  TEST (7, 7, 1, 5)
+}
+
+void check21(void)
+{
+  TEST (0, 0, 2, 5)
+  TEST (1, 0, 2, 5)
+  TEST (2, 0, 2, 5)
+  TEST (3, 0, 2, 5)
+  TEST (4, 0, 2, 5)
+  TEST (5, 0, 2, 5)
+  TEST (6, 0, 2, 5)
+  TEST (7, 0, 2, 5)
+  TEST (0, 1, 2, 5)
+  TEST (1, 1, 2, 5)
+  TEST (2, 1, 2, 5)
+  TEST (3, 1, 2, 5)
+  TEST (4, 1, 2, 5)
+  TEST (5, 1, 2, 5)
+  TEST (6, 1, 2, 5)
+  TEST (7, 1, 2, 5)
+  TEST (0, 2, 2, 5)
+  TEST (1, 2, 2, 5)
+  TEST (2, 2, 2, 5)
+  TEST (3, 2, 2, 5)
+  TEST (4, 2, 2, 5)
+  TEST (5, 2, 2, 5)
+  TEST (6, 2, 2, 5)
+  TEST (7, 2, 2, 5)
+  TEST (0, 3, 2, 5)
+  TEST (1, 3, 2, 5)
+  TEST (2, 3, 2, 5)
+  TEST (3, 3, 2, 5)
+  TEST (4, 3, 2, 5)
+  TEST (5, 3, 2, 5)
+  TEST (6, 3, 2, 5)
+  TEST (7, 3, 2, 5)
+  TEST (0, 4, 2, 5)
+  TEST (1, 4, 2, 5)
+  TEST (2, 4, 2, 5)
+  TEST (3, 4, 2, 5)
+  TEST (4, 4, 2, 5)
+  TEST (5, 4, 2, 5)
+  TEST (6, 4, 2, 5)
+  TEST (7, 4, 2, 5)
+  TEST (0, 5, 2, 5)
+  TEST (1, 5, 2, 5)
+  TEST (2, 5, 2, 5)
+  TEST (3, 5, 2, 5)
+  TEST (4, 5, 2, 5)
+  TEST (5, 5, 2, 5)
+  TEST (6, 5, 2, 5)
+  TEST (7, 5, 2, 5)
+  TEST (0, 6, 2, 5)
+  TEST (1, 6, 2, 5)
+  TEST (2, 6, 2, 5)
+  TEST (3, 6, 2, 5)
+  TEST (4, 6, 2, 5)
+  TEST (5, 6, 2, 5)
+  TEST (6, 6, 2, 5)
+  TEST (7, 6, 2, 5)
+  TEST (0, 7, 2, 5)
+  TEST (1, 7, 2, 5)
+  TEST (2, 7, 2, 5)
+  TEST (3, 7, 2, 5)
+  TEST (4, 7, 2, 5)
+  TEST (5, 7, 2, 5)
+  TEST (6, 7, 2, 5)
+  TEST (7, 7, 2, 5)
+  TEST (0, 0, 3, 5)
+  TEST (1, 0, 3, 5)
+  TEST (2, 0, 3, 5)
+  TEST (3, 0, 3, 5)
+  TEST (4, 0, 3, 5)
+  TEST (5, 0, 3, 5)
+  TEST (6, 0, 3, 5)
+  TEST (7, 0, 3, 5)
+  TEST (0, 1, 3, 5)
+  TEST (1, 1, 3, 5)
+  TEST (2, 1, 3, 5)
+  TEST (3, 1, 3, 5)
+  TEST (4, 1, 3, 5)
+  TEST (5, 1, 3, 5)
+  TEST (6, 1, 3, 5)
+  TEST (7, 1, 3, 5)
+  TEST (0, 2, 3, 5)
+  TEST (1, 2, 3, 5)
+  TEST (2, 2, 3, 5)
+  TEST (3, 2, 3, 5)
+  TEST (4, 2, 3, 5)
+  TEST (5, 2, 3, 5)
+  TEST (6, 2, 3, 5)
+  TEST (7, 2, 3, 5)
+  TEST (0, 3, 3, 5)
+  TEST (1, 3, 3, 5)
+  TEST (2, 3, 3, 5)
+  TEST (3, 3, 3, 5)
+  TEST (4, 3, 3, 5)
+  TEST (5, 3, 3, 5)
+  TEST (6, 3, 3, 5)
+  TEST (7, 3, 3, 5)
+  TEST (0, 4, 3, 5)
+  TEST (1, 4, 3, 5)
+  TEST (2, 4, 3, 5)
+  TEST (3, 4, 3, 5)
+  TEST (4, 4, 3, 5)
+  TEST (5, 4, 3, 5)
+  TEST (6, 4, 3, 5)
+  TEST (7, 4, 3, 5)
+  TEST (0, 5, 3, 5)
+  TEST (1, 5, 3, 5)
+  TEST (2, 5, 3, 5)
+  TEST (3, 5, 3, 5)
+  TEST (4, 5, 3, 5)
+  TEST (5, 5, 3, 5)
+  TEST (6, 5, 3, 5)
+  TEST (7, 5, 3, 5)
+  TEST (0, 6, 3, 5)
+  TEST (1, 6, 3, 5)
+  TEST (2, 6, 3, 5)
+  TEST (3, 6, 3, 5)
+  TEST (4, 6, 3, 5)
+  TEST (5, 6, 3, 5)
+  TEST (6, 6, 3, 5)
+  TEST (7, 6, 3, 5)
+  TEST (0, 7, 3, 5)
+  TEST (1, 7, 3, 5)
+  TEST (2, 7, 3, 5)
+  TEST (3, 7, 3, 5)
+  TEST (4, 7, 3, 5)
+  TEST (5, 7, 3, 5)
+  TEST (6, 7, 3, 5)
+  TEST (7, 7, 3, 5)
+}
+
+void check22(void)
+{
+  TEST (0, 0, 4, 5)
+  TEST (1, 0, 4, 5)
+  TEST (2, 0, 4, 5)
+  TEST (3, 0, 4, 5)
+  TEST (4, 0, 4, 5)
+  TEST (5, 0, 4, 5)
+  TEST (6, 0, 4, 5)
+  TEST (7, 0, 4, 5)
+  TEST (0, 1, 4, 5)
+  TEST (1, 1, 4, 5)
+  TEST (2, 1, 4, 5)
+  TEST (3, 1, 4, 5)
+  TEST (4, 1, 4, 5)
+  TEST (5, 1, 4, 5)
+  TEST (6, 1, 4, 5)
+  TEST (7, 1, 4, 5)
+  TEST (0, 2, 4, 5)
+  TEST (1, 2, 4, 5)
+  TEST (2, 2, 4, 5)
+  TEST (3, 2, 4, 5)
+  TEST (4, 2, 4, 5)
+  TEST (5, 2, 4, 5)
+  TEST (6, 2, 4, 5)
+  TEST (7, 2, 4, 5)
+  TEST (0, 3, 4, 5)
+  TEST (1, 3, 4, 5)
+  TEST (2, 3, 4, 5)
+  TEST (3, 3, 4, 5)
+  TEST (4, 3, 4, 5)
+  TEST (5, 3, 4, 5)
+  TEST (6, 3, 4, 5)
+  TEST (7, 3, 4, 5)
+  TEST (0, 4, 4, 5)
+  TEST (1, 4, 4, 5)
+  TEST (2, 4, 4, 5)
+  TEST (3, 4, 4, 5)
+  TEST (4, 4, 4, 5)
+  TEST (5, 4, 4, 5)
+  TEST (6, 4, 4, 5)
+  TEST (7, 4, 4, 5)
+  TEST (0, 5, 4, 5)
+  TEST (1, 5, 4, 5)
+  TEST (2, 5, 4, 5)
+  TEST (3, 5, 4, 5)
+  TEST (4, 5, 4, 5)
+  TEST (5, 5, 4, 5)
+  TEST (6, 5, 4, 5)
+  TEST (7, 5, 4, 5)
+  TEST (0, 6, 4, 5)
+  TEST (1, 6, 4, 5)
+  TEST (2, 6, 4, 5)
+  TEST (3, 6, 4, 5)
+  TEST (4, 6, 4, 5)
+  TEST (5, 6, 4, 5)
+  TEST (6, 6, 4, 5)
+  TEST (7, 6, 4, 5)
+  TEST (0, 7, 4, 5)
+  TEST (1, 7, 4, 5)
+  TEST (2, 7, 4, 5)
+  TEST (3, 7, 4, 5)
+  TEST (4, 7, 4, 5)
+  TEST (5, 7, 4, 5)
+  TEST (6, 7, 4, 5)
+  TEST (7, 7, 4, 5)
+  TEST (0, 0, 5, 5)
+  TEST (1, 0, 5, 5)
+  TEST (2, 0, 5, 5)
+  TEST (3, 0, 5, 5)
+  TEST (4, 0, 5, 5)
+  TEST (5, 0, 5, 5)
+  TEST (6, 0, 5, 5)
+  TEST (7, 0, 5, 5)
+  TEST (0, 1, 5, 5)
+  TEST (1, 1, 5, 5)
+  TEST (2, 1, 5, 5)
+  TEST (3, 1, 5, 5)
+  TEST (4, 1, 5, 5)
+  TEST (5, 1, 5, 5)
+  TEST (6, 1, 5, 5)
+  TEST (7, 1, 5, 5)
+  TEST (0, 2, 5, 5)
+  TEST (1, 2, 5, 5)
+  TEST (2, 2, 5, 5)
+  TEST (3, 2, 5, 5)
+  TEST (4, 2, 5, 5)
+  TEST (5, 2, 5, 5)
+  TEST (6, 2, 5, 5)
+  TEST (7, 2, 5, 5)
+  TEST (0, 3, 5, 5)
+  TEST (1, 3, 5, 5)
+  TEST (2, 3, 5, 5)
+  TEST (3, 3, 5, 5)
+  TEST (4, 3, 5, 5)
+  TEST (5, 3, 5, 5)
+  TEST (6, 3, 5, 5)
+  TEST (7, 3, 5, 5)
+  TEST (0, 4, 5, 5)
+  TEST (1, 4, 5, 5)
+  TEST (2, 4, 5, 5)
+  TEST (3, 4, 5, 5)
+  TEST (4, 4, 5, 5)
+  TEST (5, 4, 5, 5)
+  TEST (6, 4, 5, 5)
+  TEST (7, 4, 5, 5)
+  TEST (0, 5, 5, 5)
+  TEST (1, 5, 5, 5)
+  TEST (2, 5, 5, 5)
+  TEST (3, 5, 5, 5)
+  TEST (4, 5, 5, 5)
+  TEST (5, 5, 5, 5)
+  TEST (6, 5, 5, 5)
+  TEST (7, 5, 5, 5)
+  TEST (0, 6, 5, 5)
+  TEST (1, 6, 5, 5)
+  TEST (2, 6, 5, 5)
+  TEST (3, 6, 5, 5)
+  TEST (4, 6, 5, 5)
+  TEST (5, 6, 5, 5)
+  TEST (6, 6, 5, 5)
+  TEST (7, 6, 5, 5)
+  TEST (0, 7, 5, 5)
+  TEST (1, 7, 5, 5)
+  TEST (2, 7, 5, 5)
+  TEST (3, 7, 5, 5)
+  TEST (4, 7, 5, 5)
+  TEST (5, 7, 5, 5)
+  TEST (6, 7, 5, 5)
+  TEST (7, 7, 5, 5)
+}
+
+void check23(void)
+{
+  TEST (0, 0, 6, 5)
+  TEST (1, 0, 6, 5)
+  TEST (2, 0, 6, 5)
+  TEST (3, 0, 6, 5)
+  TEST (4, 0, 6, 5)
+  TEST (5, 0, 6, 5)
+  TEST (6, 0, 6, 5)
+  TEST (7, 0, 6, 5)
+  TEST (0, 1, 6, 5)
+  TEST (1, 1, 6, 5)
+  TEST (2, 1, 6, 5)
+  TEST (3, 1, 6, 5)
+  TEST (4, 1, 6, 5)
+  TEST (5, 1, 6, 5)
+  TEST (6, 1, 6, 5)
+  TEST (7, 1, 6, 5)
+  TEST (0, 2, 6, 5)
+  TEST (1, 2, 6, 5)
+  TEST (2, 2, 6, 5)
+  TEST (3, 2, 6, 5)
+  TEST (4, 2, 6, 5)
+  TEST (5, 2, 6, 5)
+  TEST (6, 2, 6, 5)
+  TEST (7, 2, 6, 5)
+  TEST (0, 3, 6, 5)
+  TEST (1, 3, 6, 5)
+  TEST (2, 3, 6, 5)
+  TEST (3, 3, 6, 5)
+  TEST (4, 3, 6, 5)
+  TEST (5, 3, 6, 5)
+  TEST (6, 3, 6, 5)
+  TEST (7, 3, 6, 5)
+  TEST (0, 4, 6, 5)
+  TEST (1, 4, 6, 5)
+  TEST (2, 4, 6, 5)
+  TEST (3, 4, 6, 5)
+  TEST (4, 4, 6, 5)
+  TEST (5, 4, 6, 5)
+  TEST (6, 4, 6, 5)
+  TEST (7, 4, 6, 5)
+  TEST (0, 5, 6, 5)
+  TEST (1, 5, 6, 5)
+  TEST (2, 5, 6, 5)
+  TEST (3, 5, 6, 5)
+  TEST (4, 5, 6, 5)
+  TEST (5, 5, 6, 5)
+  TEST (6, 5, 6, 5)
+  TEST (7, 5, 6, 5)
+  TEST (0, 6, 6, 5)
+  TEST (1, 6, 6, 5)
+  TEST (2, 6, 6, 5)
+  TEST (3, 6, 6, 5)
+  TEST (4, 6, 6, 5)
+  TEST (5, 6, 6, 5)
+  TEST (6, 6, 6, 5)
+  TEST (7, 6, 6, 5)
+  TEST (0, 7, 6, 5)
+  TEST (1, 7, 6, 5)
+  TEST (2, 7, 6, 5)
+  TEST (3, 7, 6, 5)
+  TEST (4, 7, 6, 5)
+  TEST (5, 7, 6, 5)
+  TEST (6, 7, 6, 5)
+  TEST (7, 7, 6, 5)
+  TEST (0, 0, 7, 5)
+  TEST (1, 0, 7, 5)
+  TEST (2, 0, 7, 5)
+  TEST (3, 0, 7, 5)
+  TEST (4, 0, 7, 5)
+  TEST (5, 0, 7, 5)
+  TEST (6, 0, 7, 5)
+  TEST (7, 0, 7, 5)
+  TEST (0, 1, 7, 5)
+  TEST (1, 1, 7, 5)
+  TEST (2, 1, 7, 5)
+  TEST (3, 1, 7, 5)
+  TEST (4, 1, 7, 5)
+  TEST (5, 1, 7, 5)
+  TEST (6, 1, 7, 5)
+  TEST (7, 1, 7, 5)
+  TEST (0, 2, 7, 5)
+  TEST (1, 2, 7, 5)
+  TEST (2, 2, 7, 5)
+  TEST (3, 2, 7, 5)
+  TEST (4, 2, 7, 5)
+  TEST (5, 2, 7, 5)
+  TEST (6, 2, 7, 5)
+  TEST (7, 2, 7, 5)
+  TEST (0, 3, 7, 5)
+  TEST (1, 3, 7, 5)
+  TEST (2, 3, 7, 5)
+  TEST (3, 3, 7, 5)
+  TEST (4, 3, 7, 5)
+  TEST (5, 3, 7, 5)
+  TEST (6, 3, 7, 5)
+  TEST (7, 3, 7, 5)
+  TEST (0, 4, 7, 5)
+  TEST (1, 4, 7, 5)
+  TEST (2, 4, 7, 5)
+  TEST (3, 4, 7, 5)
+  TEST (4, 4, 7, 5)
+  TEST (5, 4, 7, 5)
+  TEST (6, 4, 7, 5)
+  TEST (7, 4, 7, 5)
+  TEST (0, 5, 7, 5)
+  TEST (1, 5, 7, 5)
+  TEST (2, 5, 7, 5)
+  TEST (3, 5, 7, 5)
+  TEST (4, 5, 7, 5)
+  TEST (5, 5, 7, 5)
+  TEST (6, 5, 7, 5)
+  TEST (7, 5, 7, 5)
+  TEST (0, 6, 7, 5)
+  TEST (1, 6, 7, 5)
+  TEST (2, 6, 7, 5)
+  TEST (3, 6, 7, 5)
+  TEST (4, 6, 7, 5)
+  TEST (5, 6, 7, 5)
+  TEST (6, 6, 7, 5)
+  TEST (7, 6, 7, 5)
+  TEST (0, 7, 7, 5)
+  TEST (1, 7, 7, 5)
+  TEST (2, 7, 7, 5)
+  TEST (3, 7, 7, 5)
+  TEST (4, 7, 7, 5)
+  TEST (5, 7, 7, 5)
+  TEST (6, 7, 7, 5)
+  TEST (7, 7, 7, 5)
+}
+
+void check24(void)
+{
+  TEST (0, 0, 0, 6)
+  TEST (1, 0, 0, 6)
+  TEST (2, 0, 0, 6)
+  TEST (3, 0, 0, 6)
+  TEST (4, 0, 0, 6)
+  TEST (5, 0, 0, 6)
+  TEST (6, 0, 0, 6)
+  TEST (7, 0, 0, 6)
+  TEST (0, 1, 0, 6)
+  TEST (1, 1, 0, 6)
+  TEST (2, 1, 0, 6)
+  TEST (3, 1, 0, 6)
+  TEST (4, 1, 0, 6)
+  TEST (5, 1, 0, 6)
+  TEST (6, 1, 0, 6)
+  TEST (7, 1, 0, 6)
+  TEST (0, 2, 0, 6)
+  TEST (1, 2, 0, 6)
+  TEST (2, 2, 0, 6)
+  TEST (3, 2, 0, 6)
+  TEST (4, 2, 0, 6)
+  TEST (5, 2, 0, 6)
+  TEST (6, 2, 0, 6)
+  TEST (7, 2, 0, 6)
+  TEST (0, 3, 0, 6)
+  TEST (1, 3, 0, 6)
+  TEST (2, 3, 0, 6)
+  TEST (3, 3, 0, 6)
+  TEST (4, 3, 0, 6)
+  TEST (5, 3, 0, 6)
+  TEST (6, 3, 0, 6)
+  TEST (7, 3, 0, 6)
+  TEST (0, 4, 0, 6)
+  TEST (1, 4, 0, 6)
+  TEST (2, 4, 0, 6)
+  TEST (3, 4, 0, 6)
+  TEST (4, 4, 0, 6)
+  TEST (5, 4, 0, 6)
+  TEST (6, 4, 0, 6)
+  TEST (7, 4, 0, 6)
+  TEST (0, 5, 0, 6)
+  TEST (1, 5, 0, 6)
+  TEST (2, 5, 0, 6)
+  TEST (3, 5, 0, 6)
+  TEST (4, 5, 0, 6)
+  TEST (5, 5, 0, 6)
+  TEST (6, 5, 0, 6)
+  TEST (7, 5, 0, 6)
+  TEST (0, 6, 0, 6)
+  TEST (1, 6, 0, 6)
+  TEST (2, 6, 0, 6)
+  TEST (3, 6, 0, 6)
+  TEST (4, 6, 0, 6)
+  TEST (5, 6, 0, 6)
+  TEST (6, 6, 0, 6)
+  TEST (7, 6, 0, 6)
+  TEST (0, 7, 0, 6)
+  TEST (1, 7, 0, 6)
+  TEST (2, 7, 0, 6)
+  TEST (3, 7, 0, 6)
+  TEST (4, 7, 0, 6)
+  TEST (5, 7, 0, 6)
+  TEST (6, 7, 0, 6)
+  TEST (7, 7, 0, 6)
+  TEST (0, 0, 1, 6)
+  TEST (1, 0, 1, 6)
+  TEST (2, 0, 1, 6)
+  TEST (3, 0, 1, 6)
+  TEST (4, 0, 1, 6)
+  TEST (5, 0, 1, 6)
+  TEST (6, 0, 1, 6)
+  TEST (7, 0, 1, 6)
+  TEST (0, 1, 1, 6)
+  TEST (1, 1, 1, 6)
+  TEST (2, 1, 1, 6)
+  TEST (3, 1, 1, 6)
+  TEST (4, 1, 1, 6)
+  TEST (5, 1, 1, 6)
+  TEST (6, 1, 1, 6)
+  TEST (7, 1, 1, 6)
+  TEST (0, 2, 1, 6)
+  TEST (1, 2, 1, 6)
+  TEST (2, 2, 1, 6)
+  TEST (3, 2, 1, 6)
+  TEST (4, 2, 1, 6)
+  TEST (5, 2, 1, 6)
+  TEST (6, 2, 1, 6)
+  TEST (7, 2, 1, 6)
+  TEST (0, 3, 1, 6)
+  TEST (1, 3, 1, 6)
+  TEST (2, 3, 1, 6)
+  TEST (3, 3, 1, 6)
+  TEST (4, 3, 1, 6)
+  TEST (5, 3, 1, 6)
+  TEST (6, 3, 1, 6)
+  TEST (7, 3, 1, 6)
+  TEST (0, 4, 1, 6)
+  TEST (1, 4, 1, 6)
+  TEST (2, 4, 1, 6)
+  TEST (3, 4, 1, 6)
+  TEST (4, 4, 1, 6)
+  TEST (5, 4, 1, 6)
+  TEST (6, 4, 1, 6)
+  TEST (7, 4, 1, 6)
+  TEST (0, 5, 1, 6)
+  TEST (1, 5, 1, 6)
+  TEST (2, 5, 1, 6)
+  TEST (3, 5, 1, 6)
+  TEST (4, 5, 1, 6)
+  TEST (5, 5, 1, 6)
+  TEST (6, 5, 1, 6)
+  TEST (7, 5, 1, 6)
+  TEST (0, 6, 1, 6)
+  TEST (1, 6, 1, 6)
+  TEST (2, 6, 1, 6)
+  TEST (3, 6, 1, 6)
+  TEST (4, 6, 1, 6)
+  TEST (5, 6, 1, 6)
+  TEST (6, 6, 1, 6)
+  TEST (7, 6, 1, 6)
+  TEST (0, 7, 1, 6)
+  TEST (1, 7, 1, 6)
+  TEST (2, 7, 1, 6)
+  TEST (3, 7, 1, 6)
+  TEST (4, 7, 1, 6)
+  TEST (5, 7, 1, 6)
+  TEST (6, 7, 1, 6)
+  TEST (7, 7, 1, 6)
+}
+
+void check25(void)
+{
+  TEST (0, 0, 2, 6)
+  TEST (1, 0, 2, 6)
+  TEST (2, 0, 2, 6)
+  TEST (3, 0, 2, 6)
+  TEST (4, 0, 2, 6)
+  TEST (5, 0, 2, 6)
+  TEST (6, 0, 2, 6)
+  TEST (7, 0, 2, 6)
+  TEST (0, 1, 2, 6)
+  TEST (1, 1, 2, 6)
+  TEST (2, 1, 2, 6)
+  TEST (3, 1, 2, 6)
+  TEST (4, 1, 2, 6)
+  TEST (5, 1, 2, 6)
+  TEST (6, 1, 2, 6)
+  TEST (7, 1, 2, 6)
+  TEST (0, 2, 2, 6)
+  TEST (1, 2, 2, 6)
+  TEST (2, 2, 2, 6)
+  TEST (3, 2, 2, 6)
+  TEST (4, 2, 2, 6)
+  TEST (5, 2, 2, 6)
+  TEST (6, 2, 2, 6)
+  TEST (7, 2, 2, 6)
+  TEST (0, 3, 2, 6)
+  TEST (1, 3, 2, 6)
+  TEST (2, 3, 2, 6)
+  TEST (3, 3, 2, 6)
+  TEST (4, 3, 2, 6)
+  TEST (5, 3, 2, 6)
+  TEST (6, 3, 2, 6)
+  TEST (7, 3, 2, 6)
+  TEST (0, 4, 2, 6)
+  TEST (1, 4, 2, 6)
+  TEST (2, 4, 2, 6)
+  TEST (3, 4, 2, 6)
+  TEST (4, 4, 2, 6)
+  TEST (5, 4, 2, 6)
+  TEST (6, 4, 2, 6)
+  TEST (7, 4, 2, 6)
+  TEST (0, 5, 2, 6)
+  TEST (1, 5, 2, 6)
+  TEST (2, 5, 2, 6)
+  TEST (3, 5, 2, 6)
+  TEST (4, 5, 2, 6)
+  TEST (5, 5, 2, 6)
+  TEST (6, 5, 2, 6)
+  TEST (7, 5, 2, 6)
+  TEST (0, 6, 2, 6)
+  TEST (1, 6, 2, 6)
+  TEST (2, 6, 2, 6)
+  TEST (3, 6, 2, 6)
+  TEST (4, 6, 2, 6)
+  TEST (5, 6, 2, 6)
+  TEST (6, 6, 2, 6)
+  TEST (7, 6, 2, 6)
+  TEST (0, 7, 2, 6)
+  TEST (1, 7, 2, 6)
+  TEST (2, 7, 2, 6)
+  TEST (3, 7, 2, 6)
+  TEST (4, 7, 2, 6)
+  TEST (5, 7, 2, 6)
+  TEST (6, 7, 2, 6)
+  TEST (7, 7, 2, 6)
+  TEST (0, 0, 3, 6)
+  TEST (1, 0, 3, 6)
+  TEST (2, 0, 3, 6)
+  TEST (3, 0, 3, 6)
+  TEST (4, 0, 3, 6)
+  TEST (5, 0, 3, 6)
+  TEST (6, 0, 3, 6)
+  TEST (7, 0, 3, 6)
+  TEST (0, 1, 3, 6)
+  TEST (1, 1, 3, 6)
+  TEST (2, 1, 3, 6)
+  TEST (3, 1, 3, 6)
+  TEST (4, 1, 3, 6)
+  TEST (5, 1, 3, 6)
+  TEST (6, 1, 3, 6)
+  TEST (7, 1, 3, 6)
+  TEST (0, 2, 3, 6)
+  TEST (1, 2, 3, 6)
+  TEST (2, 2, 3, 6)
+  TEST (3, 2, 3, 6)
+  TEST (4, 2, 3, 6)
+  TEST (5, 2, 3, 6)
+  TEST (6, 2, 3, 6)
+  TEST (7, 2, 3, 6)
+  TEST (0, 3, 3, 6)
+  TEST (1, 3, 3, 6)
+  TEST (2, 3, 3, 6)
+  TEST (3, 3, 3, 6)
+  TEST (4, 3, 3, 6)
+  TEST (5, 3, 3, 6)
+  TEST (6, 3, 3, 6)
+  TEST (7, 3, 3, 6)
+  TEST (0, 4, 3, 6)
+  TEST (1, 4, 3, 6)
+  TEST (2, 4, 3, 6)
+  TEST (3, 4, 3, 6)
+  TEST (4, 4, 3, 6)
+  TEST (5, 4, 3, 6)
+  TEST (6, 4, 3, 6)
+  TEST (7, 4, 3, 6)
+  TEST (0, 5, 3, 6)
+  TEST (1, 5, 3, 6)
+  TEST (2, 5, 3, 6)
+  TEST (3, 5, 3, 6)
+  TEST (4, 5, 3, 6)
+  TEST (5, 5, 3, 6)
+  TEST (6, 5, 3, 6)
+  TEST (7, 5, 3, 6)
+  TEST (0, 6, 3, 6)
+  TEST (1, 6, 3, 6)
+  TEST (2, 6, 3, 6)
+  TEST (3, 6, 3, 6)
+  TEST (4, 6, 3, 6)
+  TEST (5, 6, 3, 6)
+  TEST (6, 6, 3, 6)
+  TEST (7, 6, 3, 6)
+  TEST (0, 7, 3, 6)
+  TEST (1, 7, 3, 6)
+  TEST (2, 7, 3, 6)
+  TEST (3, 7, 3, 6)
+  TEST (4, 7, 3, 6)
+  TEST (5, 7, 3, 6)
+  TEST (6, 7, 3, 6)
+  TEST (7, 7, 3, 6)
+}
+
+void check26(void)
+{
+  TEST (0, 0, 4, 6)
+  TEST (1, 0, 4, 6)
+  TEST (2, 0, 4, 6)
+  TEST (3, 0, 4, 6)
+  TEST (4, 0, 4, 6)
+  TEST (5, 0, 4, 6)
+  TEST (6, 0, 4, 6)
+  TEST (7, 0, 4, 6)
+  TEST (0, 1, 4, 6)
+  TEST (1, 1, 4, 6)
+  TEST (2, 1, 4, 6)
+  TEST (3, 1, 4, 6)
+  TEST (4, 1, 4, 6)
+  TEST (5, 1, 4, 6)
+  TEST (6, 1, 4, 6)
+  TEST (7, 1, 4, 6)
+  TEST (0, 2, 4, 6)
+  TEST (1, 2, 4, 6)
+  TEST (2, 2, 4, 6)
+  TEST (3, 2, 4, 6)
+  TEST (4, 2, 4, 6)
+  TEST (5, 2, 4, 6)
+  TEST (6, 2, 4, 6)
+  TEST (7, 2, 4, 6)
+  TEST (0, 3, 4, 6)
+  TEST (1, 3, 4, 6)
+  TEST (2, 3, 4, 6)
+  TEST (3, 3, 4, 6)
+  TEST (4, 3, 4, 6)
+  TEST (5, 3, 4, 6)
+  TEST (6, 3, 4, 6)
+  TEST (7, 3, 4, 6)
+  TEST (0, 4, 4, 6)
+  TEST (1, 4, 4, 6)
+  TEST (2, 4, 4, 6)
+  TEST (3, 4, 4, 6)
+  TEST (4, 4, 4, 6)
+  TEST (5, 4, 4, 6)
+  TEST (6, 4, 4, 6)
+  TEST (7, 4, 4, 6)
+  TEST (0, 5, 4, 6)
+  TEST (1, 5, 4, 6)
+  TEST (2, 5, 4, 6)
+  TEST (3, 5, 4, 6)
+  TEST (4, 5, 4, 6)
+  TEST (5, 5, 4, 6)
+  TEST (6, 5, 4, 6)
+  TEST (7, 5, 4, 6)
+  TEST (0, 6, 4, 6)
+  TEST (1, 6, 4, 6)
+  TEST (2, 6, 4, 6)
+  TEST (3, 6, 4, 6)
+  TEST (4, 6, 4, 6)
+  TEST (5, 6, 4, 6)
+  TEST (6, 6, 4, 6)
+  TEST (7, 6, 4, 6)
+  TEST (0, 7, 4, 6)
+  TEST (1, 7, 4, 6)
+  TEST (2, 7, 4, 6)
+  TEST (3, 7, 4, 6)
+  TEST (4, 7, 4, 6)
+  TEST (5, 7, 4, 6)
+  TEST (6, 7, 4, 6)
+  TEST (7, 7, 4, 6)
+  TEST (0, 0, 5, 6)
+  TEST (1, 0, 5, 6)
+  TEST (2, 0, 5, 6)
+  TEST (3, 0, 5, 6)
+  TEST (4, 0, 5, 6)
+  TEST (5, 0, 5, 6)
+  TEST (6, 0, 5, 6)
+  TEST (7, 0, 5, 6)
+  TEST (0, 1, 5, 6)
+  TEST (1, 1, 5, 6)
+  TEST (2, 1, 5, 6)
+  TEST (3, 1, 5, 6)
+  TEST (4, 1, 5, 6)
+  TEST (5, 1, 5, 6)
+  TEST (6, 1, 5, 6)
+  TEST (7, 1, 5, 6)
+  TEST (0, 2, 5, 6)
+  TEST (1, 2, 5, 6)
+  TEST (2, 2, 5, 6)
+  TEST (3, 2, 5, 6)
+  TEST (4, 2, 5, 6)
+  TEST (5, 2, 5, 6)
+  TEST (6, 2, 5, 6)
+  TEST (7, 2, 5, 6)
+  TEST (0, 3, 5, 6)
+  TEST (1, 3, 5, 6)
+  TEST (2, 3, 5, 6)
+  TEST (3, 3, 5, 6)
+  TEST (4, 3, 5, 6)
+  TEST (5, 3, 5, 6)
+  TEST (6, 3, 5, 6)
+  TEST (7, 3, 5, 6)
+  TEST (0, 4, 5, 6)
+  TEST (1, 4, 5, 6)
+  TEST (2, 4, 5, 6)
+  TEST (3, 4, 5, 6)
+  TEST (4, 4, 5, 6)
+  TEST (5, 4, 5, 6)
+  TEST (6, 4, 5, 6)
+  TEST (7, 4, 5, 6)
+  TEST (0, 5, 5, 6)
+  TEST (1, 5, 5, 6)
+  TEST (2, 5, 5, 6)
+  TEST (3, 5, 5, 6)
+  TEST (4, 5, 5, 6)
+  TEST (5, 5, 5, 6)
+  TEST (6, 5, 5, 6)
+  TEST (7, 5, 5, 6)
+  TEST (0, 6, 5, 6)
+  TEST (1, 6, 5, 6)
+  TEST (2, 6, 5, 6)
+  TEST (3, 6, 5, 6)
+  TEST (4, 6, 5, 6)
+  TEST (5, 6, 5, 6)
+  TEST (6, 6, 5, 6)
+  TEST (7, 6, 5, 6)
+  TEST (0, 7, 5, 6)
+  TEST (1, 7, 5, 6)
+  TEST (2, 7, 5, 6)
+  TEST (3, 7, 5, 6)
+  TEST (4, 7, 5, 6)
+  TEST (5, 7, 5, 6)
+  TEST (6, 7, 5, 6)
+  TEST (7, 7, 5, 6)
+}
+
+void check27(void)
+{
+  TEST (0, 0, 6, 6)
+  TEST (1, 0, 6, 6)
+  TEST (2, 0, 6, 6)
+  TEST (3, 0, 6, 6)
+  TEST (4, 0, 6, 6)
+  TEST (5, 0, 6, 6)
+  TEST (6, 0, 6, 6)
+  TEST (7, 0, 6, 6)
+  TEST (0, 1, 6, 6)
+  TEST (1, 1, 6, 6)
+  TEST (2, 1, 6, 6)
+  TEST (3, 1, 6, 6)
+  TEST (4, 1, 6, 6)
+  TEST (5, 1, 6, 6)
+  TEST (6, 1, 6, 6)
+  TEST (7, 1, 6, 6)
+  TEST (0, 2, 6, 6)
+  TEST (1, 2, 6, 6)
+  TEST (2, 2, 6, 6)
+  TEST (3, 2, 6, 6)
+  TEST (4, 2, 6, 6)
+  TEST (5, 2, 6, 6)
+  TEST (6, 2, 6, 6)
+  TEST (7, 2, 6, 6)
+  TEST (0, 3, 6, 6)
+  TEST (1, 3, 6, 6)
+  TEST (2, 3, 6, 6)
+  TEST (3, 3, 6, 6)
+  TEST (4, 3, 6, 6)
+  TEST (5, 3, 6, 6)
+  TEST (6, 3, 6, 6)
+  TEST (7, 3, 6, 6)
+  TEST (0, 4, 6, 6)
+  TEST (1, 4, 6, 6)
+  TEST (2, 4, 6, 6)
+  TEST (3, 4, 6, 6)
+  TEST (4, 4, 6, 6)
+  TEST (5, 4, 6, 6)
+  TEST (6, 4, 6, 6)
+  TEST (7, 4, 6, 6)
+  TEST (0, 5, 6, 6)
+  TEST (1, 5, 6, 6)
+  TEST (2, 5, 6, 6)
+  TEST (3, 5, 6, 6)
+  TEST (4, 5, 6, 6)
+  TEST (5, 5, 6, 6)
+  TEST (6, 5, 6, 6)
+  TEST (7, 5, 6, 6)
+  TEST (0, 6, 6, 6)
+  TEST (1, 6, 6, 6)
+  TEST (2, 6, 6, 6)
+  TEST (3, 6, 6, 6)
+  TEST (4, 6, 6, 6)
+  TEST (5, 6, 6, 6)
+  TEST (6, 6, 6, 6)
+  TEST (7, 6, 6, 6)
+  TEST (0, 7, 6, 6)
+  TEST (1, 7, 6, 6)
+  TEST (2, 7, 6, 6)
+  TEST (3, 7, 6, 6)
+  TEST (4, 7, 6, 6)
+  TEST (5, 7, 6, 6)
+  TEST (6, 7, 6, 6)
+  TEST (7, 7, 6, 6)
+  TEST (0, 0, 7, 6)
+  TEST (1, 0, 7, 6)
+  TEST (2, 0, 7, 6)
+  TEST (3, 0, 7, 6)
+  TEST (4, 0, 7, 6)
+  TEST (5, 0, 7, 6)
+  TEST (6, 0, 7, 6)
+  TEST (7, 0, 7, 6)
+  TEST (0, 1, 7, 6)
+  TEST (1, 1, 7, 6)
+  TEST (2, 1, 7, 6)
+  TEST (3, 1, 7, 6)
+  TEST (4, 1, 7, 6)
+  TEST (5, 1, 7, 6)
+  TEST (6, 1, 7, 6)
+  TEST (7, 1, 7, 6)
+  TEST (0, 2, 7, 6)
+  TEST (1, 2, 7, 6)
+  TEST (2, 2, 7, 6)
+  TEST (3, 2, 7, 6)
+  TEST (4, 2, 7, 6)
+  TEST (5, 2, 7, 6)
+  TEST (6, 2, 7, 6)
+  TEST (7, 2, 7, 6)
+  TEST (0, 3, 7, 6)
+  TEST (1, 3, 7, 6)
+  TEST (2, 3, 7, 6)
+  TEST (3, 3, 7, 6)
+  TEST (4, 3, 7, 6)
+  TEST (5, 3, 7, 6)
+  TEST (6, 3, 7, 6)
+  TEST (7, 3, 7, 6)
+  TEST (0, 4, 7, 6)
+  TEST (1, 4, 7, 6)
+  TEST (2, 4, 7, 6)
+  TEST (3, 4, 7, 6)
+  TEST (4, 4, 7, 6)
+  TEST (5, 4, 7, 6)
+  TEST (6, 4, 7, 6)
+  TEST (7, 4, 7, 6)
+  TEST (0, 5, 7, 6)
+  TEST (1, 5, 7, 6)
+  TEST (2, 5, 7, 6)
+  TEST (3, 5, 7, 6)
+  TEST (4, 5, 7, 6)
+  TEST (5, 5, 7, 6)
+  TEST (6, 5, 7, 6)
+  TEST (7, 5, 7, 6)
+  TEST (0, 6, 7, 6)
+  TEST (1, 6, 7, 6)
+  TEST (2, 6, 7, 6)
+  TEST (3, 6, 7, 6)
+  TEST (4, 6, 7, 6)
+  TEST (5, 6, 7, 6)
+  TEST (6, 6, 7, 6)
+  TEST (7, 6, 7, 6)
+  TEST (0, 7, 7, 6)
+  TEST (1, 7, 7, 6)
+  TEST (2, 7, 7, 6)
+  TEST (3, 7, 7, 6)
+  TEST (4, 7, 7, 6)
+  TEST (5, 7, 7, 6)
+  TEST (6, 7, 7, 6)
+  TEST (7, 7, 7, 6)
+}
+
+void check28(void)
+{
+  TEST (0, 0, 0, 7)
+  TEST (1, 0, 0, 7)
+  TEST (2, 0, 0, 7)
+  TEST (3, 0, 0, 7)
+  TEST (4, 0, 0, 7)
+  TEST (5, 0, 0, 7)
+  TEST (6, 0, 0, 7)
+  TEST (7, 0, 0, 7)
+  TEST (0, 1, 0, 7)
+  TEST (1, 1, 0, 7)
+  TEST (2, 1, 0, 7)
+  TEST (3, 1, 0, 7)
+  TEST (4, 1, 0, 7)
+  TEST (5, 1, 0, 7)
+  TEST (6, 1, 0, 7)
+  TEST (7, 1, 0, 7)
+  TEST (0, 2, 0, 7)
+  TEST (1, 2, 0, 7)
+  TEST (2, 2, 0, 7)
+  TEST (3, 2, 0, 7)
+  TEST (4, 2, 0, 7)
+  TEST (5, 2, 0, 7)
+  TEST (6, 2, 0, 7)
+  TEST (7, 2, 0, 7)
+  TEST (0, 3, 0, 7)
+  TEST (1, 3, 0, 7)
+  TEST (2, 3, 0, 7)
+  TEST (3, 3, 0, 7)
+  TEST (4, 3, 0, 7)
+  TEST (5, 3, 0, 7)
+  TEST (6, 3, 0, 7)
+  TEST (7, 3, 0, 7)
+  TEST (0, 4, 0, 7)
+  TEST (1, 4, 0, 7)
+  TEST (2, 4, 0, 7)
+  TEST (3, 4, 0, 7)
+  TEST (4, 4, 0, 7)
+  TEST (5, 4, 0, 7)
+  TEST (6, 4, 0, 7)
+  TEST (7, 4, 0, 7)
+  TEST (0, 5, 0, 7)
+  TEST (1, 5, 0, 7)
+  TEST (2, 5, 0, 7)
+  TEST (3, 5, 0, 7)
+  TEST (4, 5, 0, 7)
+  TEST (5, 5, 0, 7)
+  TEST (6, 5, 0, 7)
+  TEST (7, 5, 0, 7)
+  TEST (0, 6, 0, 7)
+  TEST (1, 6, 0, 7)
+  TEST (2, 6, 0, 7)
+  TEST (3, 6, 0, 7)
+  TEST (4, 6, 0, 7)
+  TEST (5, 6, 0, 7)
+  TEST (6, 6, 0, 7)
+  TEST (7, 6, 0, 7)
+  TEST (0, 7, 0, 7)
+  TEST (1, 7, 0, 7)
+  TEST (2, 7, 0, 7)
+  TEST (3, 7, 0, 7)
+  TEST (4, 7, 0, 7)
+  TEST (5, 7, 0, 7)
+  TEST (6, 7, 0, 7)
+  TEST (7, 7, 0, 7)
+  TEST (0, 0, 1, 7)
+  TEST (1, 0, 1, 7)
+  TEST (2, 0, 1, 7)
+  TEST (3, 0, 1, 7)
+  TEST (4, 0, 1, 7)
+  TEST (5, 0, 1, 7)
+  TEST (6, 0, 1, 7)
+  TEST (7, 0, 1, 7)
+  TEST (0, 1, 1, 7)
+  TEST (1, 1, 1, 7)
+  TEST (2, 1, 1, 7)
+  TEST (3, 1, 1, 7)
+  TEST (4, 1, 1, 7)
+  TEST (5, 1, 1, 7)
+  TEST (6, 1, 1, 7)
+  TEST (7, 1, 1, 7)
+  TEST (0, 2, 1, 7)
+  TEST (1, 2, 1, 7)
+  TEST (2, 2, 1, 7)
+  TEST (3, 2, 1, 7)
+  TEST (4, 2, 1, 7)
+  TEST (5, 2, 1, 7)
+  TEST (6, 2, 1, 7)
+  TEST (7, 2, 1, 7)
+  TEST (0, 3, 1, 7)
+  TEST (1, 3, 1, 7)
+  TEST (2, 3, 1, 7)
+  TEST (3, 3, 1, 7)
+  TEST (4, 3, 1, 7)
+  TEST (5, 3, 1, 7)
+  TEST (6, 3, 1, 7)
+  TEST (7, 3, 1, 7)
+  TEST (0, 4, 1, 7)
+  TEST (1, 4, 1, 7)
+  TEST (2, 4, 1, 7)
+  TEST (3, 4, 1, 7)
+  TEST (4, 4, 1, 7)
+  TEST (5, 4, 1, 7)
+  TEST (6, 4, 1, 7)
+  TEST (7, 4, 1, 7)
+  TEST (0, 5, 1, 7)
+  TEST (1, 5, 1, 7)
+  TEST (2, 5, 1, 7)
+  TEST (3, 5, 1, 7)
+  TEST (4, 5, 1, 7)
+  TEST (5, 5, 1, 7)
+  TEST (6, 5, 1, 7)
+  TEST (7, 5, 1, 7)
+  TEST (0, 6, 1, 7)
+  TEST (1, 6, 1, 7)
+  TEST (2, 6, 1, 7)
+  TEST (3, 6, 1, 7)
+  TEST (4, 6, 1, 7)
+  TEST (5, 6, 1, 7)
+  TEST (6, 6, 1, 7)
+  TEST (7, 6, 1, 7)
+  TEST (0, 7, 1, 7)
+  TEST (1, 7, 1, 7)
+  TEST (2, 7, 1, 7)
+  TEST (3, 7, 1, 7)
+  TEST (4, 7, 1, 7)
+  TEST (5, 7, 1, 7)
+  TEST (6, 7, 1, 7)
+  TEST (7, 7, 1, 7)
+}
+
+void check29(void)
+{
+  TEST (0, 0, 2, 7)
+  TEST (1, 0, 2, 7)
+  TEST (2, 0, 2, 7)
+  TEST (3, 0, 2, 7)
+  TEST (4, 0, 2, 7)
+  TEST (5, 0, 2, 7)
+  TEST (6, 0, 2, 7)
+  TEST (7, 0, 2, 7)
+  TEST (0, 1, 2, 7)
+  TEST (1, 1, 2, 7)
+  TEST (2, 1, 2, 7)
+  TEST (3, 1, 2, 7)
+  TEST (4, 1, 2, 7)
+  TEST (5, 1, 2, 7)
+  TEST (6, 1, 2, 7)
+  TEST (7, 1, 2, 7)
+  TEST (0, 2, 2, 7)
+  TEST (1, 2, 2, 7)
+  TEST (2, 2, 2, 7)
+  TEST (3, 2, 2, 7)
+  TEST (4, 2, 2, 7)
+  TEST (5, 2, 2, 7)
+  TEST (6, 2, 2, 7)
+  TEST (7, 2, 2, 7)
+  TEST (0, 3, 2, 7)
+  TEST (1, 3, 2, 7)
+  TEST (2, 3, 2, 7)
+  TEST (3, 3, 2, 7)
+  TEST (4, 3, 2, 7)
+  TEST (5, 3, 2, 7)
+  TEST (6, 3, 2, 7)
+  TEST (7, 3, 2, 7)
+  TEST (0, 4, 2, 7)
+  TEST (1, 4, 2, 7)
+  TEST (2, 4, 2, 7)
+  TEST (3, 4, 2, 7)
+  TEST (4, 4, 2, 7)
+  TEST (5, 4, 2, 7)
+  TEST (6, 4, 2, 7)
+  TEST (7, 4, 2, 7)
+  TEST (0, 5, 2, 7)
+  TEST (1, 5, 2, 7)
+  TEST (2, 5, 2, 7)
+  TEST (3, 5, 2, 7)
+  TEST (4, 5, 2, 7)
+  TEST (5, 5, 2, 7)
+  TEST (6, 5, 2, 7)
+  TEST (7, 5, 2, 7)
+  TEST (0, 6, 2, 7)
+  TEST (1, 6, 2, 7)
+  TEST (2, 6, 2, 7)
+  TEST (3, 6, 2, 7)
+  TEST (4, 6, 2, 7)
+  TEST (5, 6, 2, 7)
+  TEST (6, 6, 2, 7)
+  TEST (7, 6, 2, 7)
+  TEST (0, 7, 2, 7)
+  TEST (1, 7, 2, 7)
+  TEST (2, 7, 2, 7)
+  TEST (3, 7, 2, 7)
+  TEST (4, 7, 2, 7)
+  TEST (5, 7, 2, 7)
+  TEST (6, 7, 2, 7)
+  TEST (7, 7, 2, 7)
+  TEST (0, 0, 3, 7)
+  TEST (1, 0, 3, 7)
+  TEST (2, 0, 3, 7)
+  TEST (3, 0, 3, 7)
+  TEST (4, 0, 3, 7)
+  TEST (5, 0, 3, 7)
+  TEST (6, 0, 3, 7)
+  TEST (7, 0, 3, 7)
+  TEST (0, 1, 3, 7)
+  TEST (1, 1, 3, 7)
+  TEST (2, 1, 3, 7)
+  TEST (3, 1, 3, 7)
+  TEST (4, 1, 3, 7)
+  TEST (5, 1, 3, 7)
+  TEST (6, 1, 3, 7)
+  TEST (7, 1, 3, 7)
+  TEST (0, 2, 3, 7)
+  TEST (1, 2, 3, 7)
+  TEST (2, 2, 3, 7)
+  TEST (3, 2, 3, 7)
+  TEST (4, 2, 3, 7)
+  TEST (5, 2, 3, 7)
+  TEST (6, 2, 3, 7)
+  TEST (7, 2, 3, 7)
+  TEST (0, 3, 3, 7)
+  TEST (1, 3, 3, 7)
+  TEST (2, 3, 3, 7)
+  TEST (3, 3, 3, 7)
+  TEST (4, 3, 3, 7)
+  TEST (5, 3, 3, 7)
+  TEST (6, 3, 3, 7)
+  TEST (7, 3, 3, 7)
+  TEST (0, 4, 3, 7)
+  TEST (1, 4, 3, 7)
+  TEST (2, 4, 3, 7)
+  TEST (3, 4, 3, 7)
+  TEST (4, 4, 3, 7)
+  TEST (5, 4, 3, 7)
+  TEST (6, 4, 3, 7)
+  TEST (7, 4, 3, 7)
+  TEST (0, 5, 3, 7)
+  TEST (1, 5, 3, 7)
+  TEST (2, 5, 3, 7)
+  TEST (3, 5, 3, 7)
+  TEST (4, 5, 3, 7)
+  TEST (5, 5, 3, 7)
+  TEST (6, 5, 3, 7)
+  TEST (7, 5, 3, 7)
+  TEST (0, 6, 3, 7)
+  TEST (1, 6, 3, 7)
+  TEST (2, 6, 3, 7)
+  TEST (3, 6, 3, 7)
+  TEST (4, 6, 3, 7)
+  TEST (5, 6, 3, 7)
+  TEST (6, 6, 3, 7)
+  TEST (7, 6, 3, 7)
+  TEST (0, 7, 3, 7)
+  TEST (1, 7, 3, 7)
+  TEST (2, 7, 3, 7)
+  TEST (3, 7, 3, 7)
+  TEST (4, 7, 3, 7)
+  TEST (5, 7, 3, 7)
+  TEST (6, 7, 3, 7)
+  TEST (7, 7, 3, 7)
+}
+
+void check30(void)
+{
+  TEST (0, 0, 4, 7)
+  TEST (1, 0, 4, 7)
+  TEST (2, 0, 4, 7)
+  TEST (3, 0, 4, 7)
+  TEST (4, 0, 4, 7)
+  TEST (5, 0, 4, 7)
+  TEST (6, 0, 4, 7)
+  TEST (7, 0, 4, 7)
+  TEST (0, 1, 4, 7)
+  TEST (1, 1, 4, 7)
+  TEST (2, 1, 4, 7)
+  TEST (3, 1, 4, 7)
+  TEST (4, 1, 4, 7)
+  TEST (5, 1, 4, 7)
+  TEST (6, 1, 4, 7)
+  TEST (7, 1, 4, 7)
+  TEST (0, 2, 4, 7)
+  TEST (1, 2, 4, 7)
+  TEST (2, 2, 4, 7)
+  TEST (3, 2, 4, 7)
+  TEST (4, 2, 4, 7)
+  TEST (5, 2, 4, 7)
+  TEST (6, 2, 4, 7)
+  TEST (7, 2, 4, 7)
+  TEST (0, 3, 4, 7)
+  TEST (1, 3, 4, 7)
+  TEST (2, 3, 4, 7)
+  TEST (3, 3, 4, 7)
+  TEST (4, 3, 4, 7)
+  TEST (5, 3, 4, 7)
+  TEST (6, 3, 4, 7)
+  TEST (7, 3, 4, 7)
+  TEST (0, 4, 4, 7)
+  TEST (1, 4, 4, 7)
+  TEST (2, 4, 4, 7)
+  TEST (3, 4, 4, 7)
+  TEST (4, 4, 4, 7)
+  TEST (5, 4, 4, 7)
+  TEST (6, 4, 4, 7)
+  TEST (7, 4, 4, 7)
+  TEST (0, 5, 4, 7)
+  TEST (1, 5, 4, 7)
+  TEST (2, 5, 4, 7)
+  TEST (3, 5, 4, 7)
+  TEST (4, 5, 4, 7)
+  TEST (5, 5, 4, 7)
+  TEST (6, 5, 4, 7)
+  TEST (7, 5, 4, 7)
+  TEST (0, 6, 4, 7)
+  TEST (1, 6, 4, 7)
+  TEST (2, 6, 4, 7)
+  TEST (3, 6, 4, 7)
+  TEST (4, 6, 4, 7)
+  TEST (5, 6, 4, 7)
+  TEST (6, 6, 4, 7)
+  TEST (7, 6, 4, 7)
+  TEST (0, 7, 4, 7)
+  TEST (1, 7, 4, 7)
+  TEST (2, 7, 4, 7)
+  TEST (3, 7, 4, 7)
+  TEST (4, 7, 4, 7)
+  TEST (5, 7, 4, 7)
+  TEST (6, 7, 4, 7)
+  TEST (7, 7, 4, 7)
+  TEST (0, 0, 5, 7)
+  TEST (1, 0, 5, 7)
+  TEST (2, 0, 5, 7)
+  TEST (3, 0, 5, 7)
+  TEST (4, 0, 5, 7)
+  TEST (5, 0, 5, 7)
+  TEST (6, 0, 5, 7)
+  TEST (7, 0, 5, 7)
+  TEST (0, 1, 5, 7)
+  TEST (1, 1, 5, 7)
+  TEST (2, 1, 5, 7)
+  TEST (3, 1, 5, 7)
+  TEST (4, 1, 5, 7)
+  TEST (5, 1, 5, 7)
+  TEST (6, 1, 5, 7)
+  TEST (7, 1, 5, 7)
+  TEST (0, 2, 5, 7)
+  TEST (1, 2, 5, 7)
+  TEST (2, 2, 5, 7)
+  TEST (3, 2, 5, 7)
+  TEST (4, 2, 5, 7)
+  TEST (5, 2, 5, 7)
+  TEST (6, 2, 5, 7)
+  TEST (7, 2, 5, 7)
+  TEST (0, 3, 5, 7)
+  TEST (1, 3, 5, 7)
+  TEST (2, 3, 5, 7)
+  TEST (3, 3, 5, 7)
+  TEST (4, 3, 5, 7)
+  TEST (5, 3, 5, 7)
+  TEST (6, 3, 5, 7)
+  TEST (7, 3, 5, 7)
+  TEST (0, 4, 5, 7)
+  TEST (1, 4, 5, 7)
+  TEST (2, 4, 5, 7)
+  TEST (3, 4, 5, 7)
+  TEST (4, 4, 5, 7)
+  TEST (5, 4, 5, 7)
+  TEST (6, 4, 5, 7)
+  TEST (7, 4, 5, 7)
+  TEST (0, 5, 5, 7)
+  TEST (1, 5, 5, 7)
+  TEST (2, 5, 5, 7)
+  TEST (3, 5, 5, 7)
+  TEST (4, 5, 5, 7)
+  TEST (5, 5, 5, 7)
+  TEST (6, 5, 5, 7)
+  TEST (7, 5, 5, 7)
+  TEST (0, 6, 5, 7)
+  TEST (1, 6, 5, 7)
+  TEST (2, 6, 5, 7)
+  TEST (3, 6, 5, 7)
+  TEST (4, 6, 5, 7)
+  TEST (5, 6, 5, 7)
+  TEST (6, 6, 5, 7)
+  TEST (7, 6, 5, 7)
+  TEST (0, 7, 5, 7)
+  TEST (1, 7, 5, 7)
+  TEST (2, 7, 5, 7)
+  TEST (3, 7, 5, 7)
+  TEST (4, 7, 5, 7)
+  TEST (5, 7, 5, 7)
+  TEST (6, 7, 5, 7)
+  TEST (7, 7, 5, 7)
+}
+
+void check31(void)
+{
+  TEST (0, 0, 6, 7)
+  TEST (1, 0, 6, 7)
+  TEST (2, 0, 6, 7)
+  TEST (3, 0, 6, 7)
+  TEST (4, 0, 6, 7)
+  TEST (5, 0, 6, 7)
+  TEST (6, 0, 6, 7)
+  TEST (7, 0, 6, 7)
+  TEST (0, 1, 6, 7)
+  TEST (1, 1, 6, 7)
+  TEST (2, 1, 6, 7)
+  TEST (3, 1, 6, 7)
+  TEST (4, 1, 6, 7)
+  TEST (5, 1, 6, 7)
+  TEST (6, 1, 6, 7)
+  TEST (7, 1, 6, 7)
+  TEST (0, 2, 6, 7)
+  TEST (1, 2, 6, 7)
+  TEST (2, 2, 6, 7)
+  TEST (3, 2, 6, 7)
+  TEST (4, 2, 6, 7)
+  TEST (5, 2, 6, 7)
+  TEST (6, 2, 6, 7)
+  TEST (7, 2, 6, 7)
+  TEST (0, 3, 6, 7)
+  TEST (1, 3, 6, 7)
+  TEST (2, 3, 6, 7)
+  TEST (3, 3, 6, 7)
+  TEST (4, 3, 6, 7)
+  TEST (5, 3, 6, 7)
+  TEST (6, 3, 6, 7)
+  TEST (7, 3, 6, 7)
+  TEST (0, 4, 6, 7)
+  TEST (1, 4, 6, 7)
+  TEST (2, 4, 6, 7)
+  TEST (3, 4, 6, 7)
+  TEST (4, 4, 6, 7)
+  TEST (5, 4, 6, 7)
+  TEST (6, 4, 6, 7)
+  TEST (7, 4, 6, 7)
+  TEST (0, 5, 6, 7)
+  TEST (1, 5, 6, 7)
+  TEST (2, 5, 6, 7)
+  TEST (3, 5, 6, 7)
+  TEST (4, 5, 6, 7)
+  TEST (5, 5, 6, 7)
+  TEST (6, 5, 6, 7)
+  TEST (7, 5, 6, 7)
+  TEST (0, 6, 6, 7)
+  TEST (1, 6, 6, 7)
+  TEST (2, 6, 6, 7)
+  TEST (3, 6, 6, 7)
+  TEST (4, 6, 6, 7)
+  TEST (5, 6, 6, 7)
+  TEST (6, 6, 6, 7)
+  TEST (7, 6, 6, 7)
+  TEST (0, 7, 6, 7)
+  TEST (1, 7, 6, 7)
+  TEST (2, 7, 6, 7)
+  TEST (3, 7, 6, 7)
+  TEST (4, 7, 6, 7)
+  TEST (5, 7, 6, 7)
+  TEST (6, 7, 6, 7)
+  TEST (7, 7, 6, 7)
+  TEST (0, 0, 7, 7)
+  TEST (1, 0, 7, 7)
+  TEST (2, 0, 7, 7)
+  TEST (3, 0, 7, 7)
+  TEST (4, 0, 7, 7)
+  TEST (5, 0, 7, 7)
+  TEST (6, 0, 7, 7)
+  TEST (7, 0, 7, 7)
+  TEST (0, 1, 7, 7)
+  TEST (1, 1, 7, 7)
+  TEST (2, 1, 7, 7)
+  TEST (3, 1, 7, 7)
+  TEST (4, 1, 7, 7)
+  TEST (5, 1, 7, 7)
+  TEST (6, 1, 7, 7)
+  TEST (7, 1, 7, 7)
+  TEST (0, 2, 7, 7)
+  TEST (1, 2, 7, 7)
+  TEST (2, 2, 7, 7)
+  TEST (3, 2, 7, 7)
+  TEST (4, 2, 7, 7)
+  TEST (5, 2, 7, 7)
+  TEST (6, 2, 7, 7)
+  TEST (7, 2, 7, 7)
+  TEST (0, 3, 7, 7)
+  TEST (1, 3, 7, 7)
+  TEST (2, 3, 7, 7)
+  TEST (3, 3, 7, 7)
+  TEST (4, 3, 7, 7)
+  TEST (5, 3, 7, 7)
+  TEST (6, 3, 7, 7)
+  TEST (7, 3, 7, 7)
+  TEST (0, 4, 7, 7)
+  TEST (1, 4, 7, 7)
+  TEST (2, 4, 7, 7)
+  TEST (3, 4, 7, 7)
+  TEST (4, 4, 7, 7)
+  TEST (5, 4, 7, 7)
+  TEST (6, 4, 7, 7)
+  TEST (7, 4, 7, 7)
+  TEST (0, 5, 7, 7)
+  TEST (1, 5, 7, 7)
+  TEST (2, 5, 7, 7)
+  TEST (3, 5, 7, 7)
+  TEST (4, 5, 7, 7)
+  TEST (5, 5, 7, 7)
+  TEST (6, 5, 7, 7)
+  TEST (7, 5, 7, 7)
+  TEST (0, 6, 7, 7)
+  TEST (1, 6, 7, 7)
+  TEST (2, 6, 7, 7)
+  TEST (3, 6, 7, 7)
+  TEST (4, 6, 7, 7)
+  TEST (5, 6, 7, 7)
+  TEST (6, 6, 7, 7)
+  TEST (7, 6, 7, 7)
+  TEST (0, 7, 7, 7)
+  TEST (1, 7, 7, 7)
+  TEST (2, 7, 7, 7)
+  TEST (3, 7, 7, 7)
+  TEST (4, 7, 7, 7)
+  TEST (5, 7, 7, 7)
+  TEST (6, 7, 7, 7)
+  TEST (7, 7, 7, 7)
+}
+
+void check(void)
+{
+  check0 ();
+  check1 ();
+  check2 ();
+  check3 ();
+  check4 ();
+  check5 ();
+  check6 ();
+  check7 ();
+  check8 ();
+  check9 ();
+  check10 ();
+  check11 ();
+  check12 ();
+  check13 ();
+  check14 ();
+  check15 ();
+  check16 ();
+  check17 ();
+  check18 ();
+  check19 ();
+  check20 ();
+  check21 ();
+  check22 ();
+  check23 ();
+  check24 ();
+  check25 ();
+  check26 ();
+  check27 ();
+  check28 ();
+  check29 ();
+  check30 ();
+  check31 ();
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v2df.c b/gcc/testsuite/gcc.target/i386/vperm-v2df.c
new file mode 100644
index 0000000..f17e065
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-v2df.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O -msse2" } */
+
+#include "isa-check.h"
+
+typedef double S;
+typedef double V __attribute__((vector_size(16)));
+typedef long long IV __attribute__((vector_size(16)));
+typedef union { S s[2]; V v; } U;
+
+static U i[2], b, c;
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+#define assert(T) ((T) || (__builtin_trap (), 0))
+
+#define TEST(E0, E1) \
+  b.v = __builtin_ia32_vec_perm_v2df (i[0].v, i[1].v, (IV){E0, E1}); \
+  c.s[0] = i[0].s[E0]; \
+  c.s[1] = i[0].s[E1]; \
+  __asm__("" : : : "memory"); \
+  assert (memcmp (&b, &c, sizeof(c)) == 0);
+
+#include "vperm-2-2.inc"
+
+int main()
+{
+  i[0].s[0] = 0;
+  i[0].s[1] = 1;
+  i[0].s[2] = 2;
+  i[0].s[3] = 3;
+
+  check();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v2di.c b/gcc/testsuite/gcc.target/i386/vperm-v2di.c
new file mode 100644
index 0000000..c6fe561
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-v2di.c
@@ -0,0 +1,34 @@
+/* { dg-do run } */
+/* { dg-options "-O -msse2" } */
+
+#include "isa-check.h"
+
+typedef long long S;
+typedef long long V __attribute__((vector_size(16)));
+typedef long long IV __attribute__((vector_size(16)));
+typedef union { S s[2]; V v; } U;
+
+static U i[2], b, c;
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+#define assert(T) ((T) || (__builtin_trap (), 0))
+
+#define TEST(E0, E1) \
+  b.v = __builtin_ia32_vec_perm_v2di (i[0].v, i[1].v, (IV){E0, E1}); \
+  c.s[0] = i[0].s[E0]; \
+  c.s[1] = i[0].s[E1]; \
+  __asm__("" : : : "memory"); \
+  assert (memcmp (&b, &c, sizeof(c)) == 0);
+
+#include "vperm-2-2.inc"
+
+int main()
+{
+  i[0].s[0] = 0;
+  i[0].s[1] = 1;
+  i[0].s[2] = 2;
+  i[0].s[3] = 3;
+
+  check();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c b/gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c
new file mode 100644
index 0000000..b9fc9b1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4sf-1.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O -msse" } */
+
+#include "isa-check.h"
+
+typedef float S;
+typedef float V __attribute__((vector_size(16)));
+typedef int IV __attribute__((vector_size(16)));
+typedef union { S s[4]; V v; } U;
+
+static U i[2], b, c;
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+#define assert(T) ((T) || (__builtin_trap (), 0))
+
+#define TEST(E0, E1, E2, E3) \
+  b.v = __builtin_ia32_vec_perm_v4sf (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+  c.s[0] = i[0].s[E0]; \
+  c.s[1] = i[0].s[E1]; \
+  c.s[2] = i[0].s[E2]; \
+  c.s[3] = i[0].s[E3]; \
+  __asm__("" : : : "memory"); \
+  assert (memcmp (&b, &c, sizeof(c)) == 0);
+
+#include "vperm-4-1.inc"
+
+int main()
+{
+  i[0].s[0] = 0;
+  i[0].s[1] = 1;
+  i[0].s[2] = 2;
+  i[0].s[3] = 3;
+  i[0].s[4] = 4;
+  i[0].s[5] = 5;
+  i[0].s[6] = 6;
+  i[0].s[7] = 7;
+
+  check();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c b/gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c
new file mode 100644
index 0000000..f81d241
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4sf-2.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O -mssse3" } */
+
+#include "isa-check.h"
+
+typedef float S;
+typedef float V __attribute__((vector_size(16)));
+typedef int IV __attribute__((vector_size(16)));
+typedef union { S s[4]; V v; } U;
+
+static U i[2], b, c;
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+#define assert(T) ((T) || (__builtin_trap (), 0))
+
+#define TEST(E0, E1, E2, E3) \
+  b.v = __builtin_ia32_vec_perm_v4sf (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+  c.s[0] = i[0].s[E0]; \
+  c.s[1] = i[0].s[E1]; \
+  c.s[2] = i[0].s[E2]; \
+  c.s[3] = i[0].s[E3]; \
+  __asm__("" : : : "memory"); \
+  assert (memcmp (&b, &c, sizeof(c)) == 0);
+
+#include "vperm-4-2.inc"
+
+int main()
+{
+  i[0].s[0] = 0;
+  i[0].s[1] = 1;
+  i[0].s[2] = 2;
+  i[0].s[3] = 3;
+  i[0].s[4] = 4;
+  i[0].s[5] = 5;
+  i[0].s[6] = 6;
+  i[0].s[7] = 7;
+
+  check();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4si-1.c b/gcc/testsuite/gcc.target/i386/vperm-v4si-1.c
new file mode 100644
index 0000000..663feb3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4si-1.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O -msse2" } */
+
+#include "isa-check.h"
+
+typedef int S;
+typedef int V __attribute__((vector_size(16)));
+typedef int IV __attribute__((vector_size(16)));
+typedef union { S s[4]; V v; } U;
+
+static U i[2], b, c;
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+#define assert(T) ((T) || (__builtin_trap (), 0))
+
+#define TEST(E0, E1, E2, E3) \
+  b.v = __builtin_ia32_vec_perm_v4si (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+  c.s[0] = i[0].s[E0]; \
+  c.s[1] = i[0].s[E1]; \
+  c.s[2] = i[0].s[E2]; \
+  c.s[3] = i[0].s[E3]; \
+  __asm__("" : : : "memory"); \
+  assert (memcmp (&b, &c, sizeof(c)) == 0);
+
+#include "vperm-4-1.inc"
+
+int main()
+{
+  i[0].s[0] = 0;
+  i[0].s[1] = 1;
+  i[0].s[2] = 2;
+  i[0].s[3] = 3;
+  i[0].s[4] = 4;
+  i[0].s[5] = 5;
+  i[0].s[6] = 6;
+  i[0].s[7] = 7;
+
+  check();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4si-2.c b/gcc/testsuite/gcc.target/i386/vperm-v4si-2.c
new file mode 100644
index 0000000..0da953b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4si-2.c
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O -mssse3" } */
+
+#include "isa-check.h"
+
+typedef int S;
+typedef int V __attribute__((vector_size(16)));
+typedef int IV __attribute__((vector_size(16)));
+typedef union { S s[4]; V v; } U;
+
+static U i[2], b, c;
+
+extern int memcmp (const void *, const void *, __SIZE_TYPE__);
+#define assert(T) ((T) || (__builtin_trap (), 0))
+
+#define TEST(E0, E1, E2, E3) \
+  b.v = __builtin_ia32_vec_perm_v4si (i[0].v, i[1].v, (IV){E0, E1, E2, E3}); \
+  c.s[0] = i[0].s[E0]; \
+  c.s[1] = i[0].s[E1]; \
+  c.s[2] = i[0].s[E2]; \
+  c.s[3] = i[0].s[E3]; \
+  __asm__("" : : : "memory"); \
+  assert (memcmp (&b, &c, sizeof(c)) == 0);
+
+#include "vperm-4-2.inc"
+
+int main()
+{
+  i[0].s[0] = 0;
+  i[0].s[1] = 1;
+  i[0].s[2] = 2;
+  i[0].s[3] = 3;
+  i[0].s[4] = 4;
+  i[0].s[5] = 5;
+  i[0].s[6] = 6;
+  i[0].s[7] = 7;
+
+  check();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/vperm-v4si-2x.c b/gcc/testsuite/gcc.target/i386/vperm-v4si-2x.c
new file mode 100644
index 0000000..4410d93
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm-v4si-2x.c
@@ -0,0 +1,3 @@
+/* { dg-do run } */
+/* { dg-options "-O -mxop" } */
+#include "vperm-v4si-2.c"
diff --git a/gcc/testsuite/gcc.target/i386/vperm.pl b/gcc/testsuite/gcc.target/i386/vperm.pl
new file mode 100755
index 0000000..80fae9d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/vperm.pl
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+$nelt = int($ARGV[0]);
+$leng = int($ARGV[1]);
+
+print "/* This file auto-generated with ./vperm.pl $nelt $leng.  */\n\n";
+
+for ($i = 0; $i < $nelt; ++$i) { $perm[$i] = 0; }
+$ncheck = 0;
+
+for ($i = 0; $i < ($leng * $nelt) ** $nelt; ++$i)
+{
+  if ($i % 128 == 0)
+  {
+    print "}\n\n" if $ncheck > 0;
+    print "void check$ncheck(void)\n{\n";
+    ++$ncheck;
+  }
+
+  print "  TEST (";
+  for ($j = 0; $j < $nelt; ++$j)
+  {
+    print $perm[$j];
+    print ", " if $j < $nelt - 1;
+  }
+  print ")\n";
+
+  INCR: for ($j = 0; $j < $nelt; ++$j)
+  {
+    last INCR if ++$perm[$j] < $leng * $nelt;
+    $perm[$j] = 0;
+  }
+}
+print "}\n\n";
+
+print "void check(void)\n{\n";
+for ($i = 0; $i < $ncheck; ++$i)
+{
+  print "  check$i ();\n";
+}
+print "}\n\n";
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 4b8d6f3..5155cba 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2562,7 +2562,9 @@ proc check_effective_target_vect_extract_even_odd { } {
         verbose "check_effective_target_vect_extract_even_odd: using cached result" 2
     } else {
         set et_vect_extract_even_odd_saved 0 
-        if { [istarget powerpc*-*-*]
+        if { [istarget powerpc*-*-*] 
+             || [istarget i?86-*-*]
+             || [istarget x86_64-*-*]
              || [istarget spu-*-*] } {
            set et_vect_extract_even_odd_saved 1
         }

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2010-11-23  1:56 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-12-02 20:04 Vector permutation support for x86 Uros Bizjak
2009-12-02 20:10 ` Sebastian Pop
2009-12-02 21:22 ` Sebastian Pop
2009-12-02 22:23   ` Sebastian Pop
2009-12-02 22:38     ` Richard Henderson
2009-12-02 23:05       ` Sebastian Pop
2009-12-02 23:39         ` Sebastian Pop
2009-12-02 23:55         ` Richard Henderson
2009-12-03 19:53           ` Sebastian Pop
2009-12-04  6:50             ` Sebastian Pop
2009-12-04 16:31               ` Richard Henderson
2009-12-04 16:40                 ` Sebastian Pop
2009-12-05 17:19                   ` Sebastian Pop
2009-12-05 17:55                     ` Richard Henderson
2009-12-03 19:30       ` Sebastian Pop
2009-12-03 20:44         ` Richard Henderson
2009-12-03 23:37           ` Sebastian Pop
2009-12-04  5:21             ` Richard Henderson
2009-12-05 17:07         ` Uros Bizjak
2009-12-05 17:49           ` Sebastian Pop
2009-12-05 20:40             ` Sebastian Pop
2009-12-05 21:51               ` Sebastian Pop
2009-12-06  8:42                 ` Sebastian Pop
2009-12-06 12:20               ` Uros Bizjak
2009-12-07  0:21               ` Richard Henderson
2009-12-07 17:35                 ` Sebastian Pop
2009-12-07 18:28                   ` Sebastian Pop
2009-12-07 19:14                     ` Richard Henderson
2009-12-07 20:10                       ` Sebastian Pop
2009-12-07 22:02                         ` Richard Henderson
  -- strict thread matches above, loose matches on Subject: below --
2009-11-27 10:17 Uros Bizjak
2009-11-27 16:02 ` Richard Henderson
2009-11-26  9:14 Uros Bizjak
2009-11-26 19:18 ` Richard Henderson
2009-11-26 20:36   ` Uros Bizjak
2009-11-26 20:57     ` Richard Henderson
2009-11-26 23:24       ` Richard Henderson
2009-11-26  3:55 Richard Henderson
2009-11-27 23:54 ` H.J. Lu
2010-04-17  5:27   ` H.J. Lu
2010-11-23  8:42     ` H.J. Lu
2009-11-30 18:36 ` Sebastian Pop
2009-11-30 20:40   ` Richard Henderson
2009-11-30 21:07     ` Sebastian Pop
2009-12-02 19:53       ` Sebastian Pop

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).