];
		asm volatile (
			"vld1.8  {d0, d1}, [%[perm], :128]\n"
		"1:\n"
			"sub     %[x], %[x], #16\n"
			"sub     %[y], %[y], #16\n"
			"sub     %[position], %[position], #8\n"
			"vld1.8  {d4, d5}, [%[pcm]]!\n"
			"vuzp.16 d4,  d5\n"
			"vld1.8  {d20, d21}, [%[pcm]]!\n"
			"vuzp.16 d20, d21\n"
			"vswp    d5,  d20\n"
			"vtbl.8  d16, {d4, d5}, d0\n"
			"vtbl.8  d17, {d4, d5}, d1\n"
			"vtbl.8  d18, {d20, d21}, d0\n"
			"vtbl.8  d19, {d20, d21}, d1\n"
			"vst1.16 {d16, d17}, [%[x], :128]\n"
			"vst1.16 {d18, d19}, [%[y], :128]\n"
			"subs    %[nsamples], %[nsamples], #8\n"
			"bgt     1b\n"
			:
			  [x]        "+r" (x),
			  [y]        "+r" (y),
			  [pcm]      "+r" (pcm),
			  [nsamples] "+r" (nsamples),
			  [position] "+r" (position)
			:
			  [perm]      "r" (big_endian ? perm_be : perm_le)
			: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
			  "d5", "d6", "d7", "d16", "d17", "d18", "d19",
			  "d20", "d21", "d22", "d23");
	} else if (nchannels > 1) {
		/* proper 'pcm' alignment */
		int16_t *x = &X[0][position];
		int16_t *y = &X[1][position];
		asm volatile (
			"vld1.8  {d0, d1}, [%[perm], :128]\n"
		"1:\n"
			"sub     %[x], %[x], #16\n"
			"sub     %[y], %[y], #16\n"
			"sub     %[position], %[position], #8\n"
			"vld2.16 {d4, d5}, [%[pcm]]!\n"
			"vld2.16 {d20, d21}, [%[pcm]]!\n"
			"vswp    d5, d20\n"
			"vtbl.8  d16, {d4, d5}, d0\n"
			"vtbl.8  d17, {d4, d5}, d1\n"
			"vtbl.8  d18, {d20, d21}, d0\n"
			"vtbl.8  d19, {d20, d21}, d1\n"
			"vst1.16 {d16, d17}, [%[x], :128]\n"
			"vst1.16 {d18, d19}, [%[y], :128]\n"
			"subs    %[nsamples], %[nsamples], #8\n"
			"bgt     1b\n"
			:
			  [x]        "+r" (x),
			  [y]        "+r" (y),
			  [pcm]      "+r" (pcm),
			  [nsamples] "+r" (nsamples),
			  [position] "+r" (position)
			:
			  [perm]      "r" (big_endian ? perm_be : perm_le)
			: "cc", "memory", "d0", "d1", "d2", "d3", "d4",
			  "d5", "d6", "d7", "d16", "d17", "d18", "d19",
			  "d20", "d21", "d22", "d23");
	} else {
		int16_t *x = &X[0][position];
		asm volatile (
			"vld1.8  {d0, d1}, [%[perm], 