#include "lp_bld_gather.h"
#include "lp_bld_debug.h"
#include "lp_bld_format.h"
+#include "lp_bld_intr.h"
/**
* matches floating point size */
assert (LLVMTypeOf(packed) == LLVMInt32TypeInContext(gallivm->context));
+#ifdef PIPE_ARCH_BIG_ENDIAN
+ packed = lp_build_bswap(gallivm, packed, lp_type_uint(32));
+#endif
+
/* Broadcast the packed value to all four channels
* before: packed = BGRA
* after: packed = {BGRA, BGRA, BGRA, BGRA}
format_desc->block.bits <= type.width * 4 &&
util_is_power_of_two(format_desc->block.bits)) {
LLVMValueRef packed;
+ LLVMTypeRef dst_vec_type = lp_build_vec_type(gallivm, type);
+ unsigned vec_len = type.width * type.length;
/*
* The format matches the type (apart of a swizzle) so no need for
format_desc->block.bits, type.width*4,
base_ptr, offset);
- assert(format_desc->block.bits <= type.width * type.length);
-
- packed = LLVMBuildBitCast(gallivm->builder, packed,
- lp_build_vec_type(gallivm, type), "");
+ assert(format_desc->block.bits <= vec_len);
+ packed = LLVMBuildBitCast(gallivm->builder, packed, dst_vec_type, "");
+#ifdef PIPE_ARCH_BIG_ENDIAN
+ if (type.floating)
+ packed = lp_build_bswap_vec(gallivm, packed, type,
+ lp_type_float_vec(type.width, vec_len));
+#endif
return lp_build_format_swizzle_aos(format_desc, &bld, packed);
}
#include "lp_bld_type.h"
#include "lp_bld_conv.h"
#include "lp_bld_pack.h"
+#include "lp_bld_intr.h"
+#include "lp_bld_gather.h"
#include "util/u_memory.h"
#include "util/u_format.h"
#include "pipe/p_state.h"
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+static LLVMValueRef
+lp_build_read_int_bswap(struct gallivm_state *gallivm,
+ LLVMValueRef base_ptr,
+ unsigned src_width,
+ LLVMTypeRef src_type,
+ unsigned i,
+ LLVMTypeRef dst_type)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef index = lp_build_const_int32(gallivm, i);
+ LLVMValueRef ptr = LLVMBuildGEP(builder, base_ptr, &index, 1, "");
+ LLVMValueRef res = LLVMBuildLoad(builder, ptr, "");
+ res = lp_build_bswap(gallivm, res, lp_type_uint(src_width));
+ return LLVMBuildBitCast(builder, res, dst_type, "");
+}
+
+static LLVMValueRef
+lp_build_fetch_read_big_endian(struct gallivm_state *gallivm,
+ struct lp_type src_type,
+ LLVMValueRef base_ptr)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ unsigned src_width = src_type.width;
+ unsigned length = src_type.length;
+ LLVMTypeRef src_elem_type = LLVMIntTypeInContext(gallivm->context, src_width);
+ LLVMTypeRef dst_elem_type = lp_build_elem_type (gallivm, src_type);
+ LLVMTypeRef src_ptr_type = LLVMPointerType(src_elem_type, 0);
+ LLVMValueRef res;
+
+ base_ptr = LLVMBuildPointerCast(builder, base_ptr, src_ptr_type, "");
+ if (length == 1) {
+ /* Scalar */
+ res = lp_build_read_int_bswap(gallivm, base_ptr, src_width, src_elem_type,
+ 0, dst_elem_type);
+ } else {
+ /* Vector */
+ LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length);
+ unsigned i;
+
+ res = LLVMGetUndef(dst_vec_type);
+ for (i = 0; i < length; ++i) {
+ LLVMValueRef index = lp_build_const_int32(gallivm, i);
+ LLVMValueRef elem = lp_build_read_int_bswap(gallivm, base_ptr, src_width,
+ src_elem_type, i, dst_elem_type);
+ res = LLVMBuildInsertElement(builder, res, elem, index, "");
+ }
+ }
+
+ return res;
+}
+#endif
+
/**
* @brief lp_build_fetch_rgba_aos_array
*
src_vec_type = lp_build_vec_type(gallivm, src_type);
/* Read whole vector from memory, unaligned */
- if (!res) {
- ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, "");
- ptr = LLVMBuildPointerCast(builder, ptr, LLVMPointerType(src_vec_type, 0), "");
- res = LLVMBuildLoad(builder, ptr, "");
- lp_set_load_alignment(res, src_type.width / 8);
- }
+ ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, "");
+#ifdef PIPE_ARCH_BIG_ENDIAN
+ res = lp_build_fetch_read_big_endian(gallivm, src_type, ptr);
+#else
+ ptr = LLVMBuildPointerCast(builder, ptr, LLVMPointerType(src_vec_type, 0), "");
+ res = LLVMBuildLoad(builder, ptr, "");
+ lp_set_load_alignment(res, src_type.width / 8);
+#endif
/* Truncate doubles to float */
if (src_type.floating && src_type.width == 64) {
assert(lp_check_value(type, i));
/*
+ * Little endian:
* y = (uyvy >> (16*i + 8)) & 0xff
* u = (uyvy ) & 0xff
* v = (uyvy >> 16 ) & 0xff
+ *
+ * Big endian:
+ * y = (uyvy >> (-16*i + 16)) & 0xff
+ * u = (uyvy >> 24) & 0xff
+ * v = (uyvy >> 8) & 0xff
*/
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
#endif
{
LLVMValueRef shift;
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, 16), "");
shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(gallivm, type, 8), "");
+#else
+ shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, -16), "");
+ shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(gallivm, type, 16), "");
+#endif
*y = LLVMBuildLShr(builder, packed, shift, "");
}
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
*u = packed;
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 16), "");
+#else
+ *u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 24), "");
+ *v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 8), "");
+#endif
mask = lp_build_const_int_vec(gallivm, type, 0xff);
assert(lp_check_value(type, i));
/*
+ * Little endian:
* y = (yuyv >> 16*i) & 0xff
* u = (yuyv >> 8 ) & 0xff
* v = (yuyv >> 24 ) & 0xff
+ *
+ * Big endian:
+ * y = (yuyv >> (-16*i + 24) & 0xff
+ * u = (yuyv >> 16) & 0xff
+ * v = (yuyv) & 0xff
*/
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
#endif
{
LLVMValueRef shift;
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, 16), "");
+#else
+ shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(gallivm, type, -16), "");
+ shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(gallivm, type, 24), "");
+#endif
*y = LLVMBuildLShr(builder, packed, shift, "");
}
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
*u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 8), "");
*v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 24), "");
+#else
+ *u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(gallivm, type, 16), "");
+ *v = packed;
+#endif
mask = lp_build_const_int_vec(gallivm, type, 0xff);
* Make a 4 x unorm8 vector
*/
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
r = r;
g = LLVMBuildShl(builder, g, lp_build_const_int_vec(gallivm, type, 8), "");
b = LLVMBuildShl(builder, b, lp_build_const_int_vec(gallivm, type, 16), "");
a = lp_build_const_int_vec(gallivm, type, 0xff000000);
+#else
+ r = LLVMBuildShl(builder, r, lp_build_const_int_vec(gallivm, type, 24), "");
+ g = LLVMBuildShl(builder, g, lp_build_const_int_vec(gallivm, type, 16), "");
+ b = LLVMBuildShl(builder, b, lp_build_const_int_vec(gallivm, type, 8), "");
+ a = lp_build_const_int_vec(gallivm, type, 0x000000ff);
+#endif
rgba = r;
rgba = LLVMBuildOr(builder, rgba, g, "");
#include "lp_bld_format.h"
#include "lp_bld_gather.h"
#include "lp_bld_init.h"
+#include "lp_bld_intr.h"
/**
res = LLVMBuildLoad(gallivm->builder, ptr, "");
assert(src_width <= dst_width);
- if (src_width > dst_width)
+ if (src_width > dst_width) {
res = LLVMBuildTrunc(gallivm->builder, res, dst_elem_type, "");
- if (src_width < dst_width)
+ } else if (src_width < dst_width) {
res = LLVMBuildZExt(gallivm->builder, res, dst_elem_type, "");
+#ifdef PIPE_ARCH_BIG_ENDIAN
+ res = LLVMBuildShl(gallivm->builder, res,
+ LLVMConstInt(dst_elem_type, dst_width - src_width, 0), "");
+#endif
+ }
return res;
}
*
* For example, this will convert BGRA to RGBA by doing
*
+ * Little endian:
* rgba = (bgra & 0x00ff0000) >> 16
* | (bgra & 0xff00ff00)
* | (bgra & 0x000000ff) << 16
*
+ * Big endian:A
+ * rgba = (bgra & 0x0000ff00) << 16
+ * | (bgra & 0x00ff00ff)
+ * | (bgra & 0xff000000) >> 16
+ *
* This is necessary not only for faster cause, but because X86 backend
* will refuse shuffles of <4 x i8> vectors
*/
/* FIXME: big endian */
if (swizzles[chan] < 4 &&
chan - swizzles[chan] == shift) {
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width);
+#else
+ mask |= ((1ULL << type.width) - 1) << (type4.width - type.width) >> (swizzles[chan] * type.width);
+#endif
}
}
masked = LLVMBuildAnd(builder, a,
lp_build_const_int_vec(bld->gallivm, type4, mask), "");
if (shift > 0) {
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
shifted = LLVMBuildShl(builder, masked,
lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
+#else
+ shifted = LLVMBuildLShr(builder, masked,
+ lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
+#endif
} else if (shift < 0) {
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
shifted = LLVMBuildLShr(builder, masked,
lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
+#else
+ shifted = LLVMBuildShl(builder, masked,
+ lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
+#endif
} else {
shifted = masked;
}