"d16", "d17", "d18", "d19", "d20", "d21", "d22",
		  "d23", "d24", "d25", "d26", "d27", "d28", "d29",
		  "d30", "d31", "cc", "memory");

	return joint;
}

#define PERM_BE(a, b, c, d) {             \
		(a * 2) + 1, (a * 2) + 0, \
		(b * 2) + 1, (b * 2) + 0, \
		(c * 2) + 1, (c * 2) + 0, \
		(d * 2) + 1, (d * 2) + 0  \
	}
#define PERM_LE(a, b, c, d) {             \
		(a * 2) + 0, (a * 2) + 1, \
		(b * 2) + 0, (b * 2) + 1, \
		(c * 2) + 0, (c * 2) + 1, \
		(d * 2) + 0, (d * 2) + 1  \
	}

static SBC_ALWAYS_INLINE int sbc_enc_process_input_4s_neon_internal(
	int position,
	const uint8_t *pcm, int16_t X[2][SBC_X_BUFFER_SIZE],
	int nsamples, int nchannels, int big_endian)
{
	static SBC_ALIGNED uint8_t perm_be[2][8] = {
		PERM_BE(7, 3, 6, 4),
		PERM_BE(0, 2, 1, 5)
	};
	static SBC_ALIGNED uint8_t perm_le[2][8] = {
		PERM_LE(7, 3, 6, 4),
		PERM_LE(0, 2, 1, 5)
	};
	/* handle X buffer wraparound */
	if (position < nsamples) {
		int16_t *dst = &X[0][SBC_X_BUFFER_SIZE - 40];
		int16_t *src = &X[0][position];
		asm volatile (
			"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
			"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
			"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
			"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
			"vld1.16 {d0}, [%[src], :64]!\n"
			"vst1.16 {d0}, [%[dst], :64]!\n"
			:
			  [dst] "+r" (dst),
			  [src] "+r" (src)
			: : "memory", "d0", "d1", "d2", "d3");
		if (nchannels > 1) {
			dst = &X[1][SBC_X_BUFFER_SIZE - 40];
			src = &X[1][position];
			asm volatile (
				"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
				"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
				"vld1.16 {d0, d1, d2, d3}, [%[src], :128]!\n"
				"vst1.16 {d0, d1, d2, d3}, [%[dst], :128]!\n"
				"vld1.16 {d0}, [%[src], :64]!\n"
				"vst1.16 {d0}, [%[dst], :64]!\n"
				:
				  [dst] "+r" (dst),
				  [src] "+r" (src)
				: : "memory", "d0", "d1", "d2", "d3");
		}
		position = SBC_X_BUFFER_SIZE - 40;
	}

	if ((nchannels > 1) && ((uintptr_t)pcm & 1)) {
		/* poor 'pcm' alignment */
		int16_t *x = &X[0][position];
		int16_t *y = &X[1][position