Support bitcasts between scalars and short vectors.

Subzero only supports 128-bit vectors currently, but we need to support
bitcasting between scalars and (emulated) short vectors of the same
size. Subzero implicitly supports it on x86 by using movd instructions,
but on ARM we have to emulate it in Reactor until support for it is
added in Subzero.

Bug swiftshader:48

Change-Id: I95accbc3665815a46dac8e52ce30939ac64aaf44
Reviewed-on: https://swiftshader-review.googlesource.com/10929
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Reactor/SubzeroReactor.cpp b/src/Reactor/SubzeroReactor.cpp
index 23bcedc..6fbd7a5 100644
--- a/src/Reactor/SubzeroReactor.cpp
+++ b/src/Reactor/SubzeroReactor.cpp
@@ -123,6 +123,7 @@
 	const bool CPUID::ARM = CPUID::detectARM();
 	const bool CPUID::SSE4_1 = CPUID::detectSSE4_1();
 	const bool emulateIntrinsics = CPUID::ARM;
+	const bool emulateMismatchedBitCast = CPUID::ARM;
 }
 
 namespace sw
@@ -981,6 +982,25 @@
 
 	Value *Nucleus::createBitCast(Value *v, Type *destType)
 	{
+		// Bitcasts must be between types of the same logical size. But with emulated narrow vectors we need
+		// support for casting between scalars and wide vectors. For platforms where this is not supported,
+		// emulate them by writing to the stack and reading back as the destination type.
+		if(emulateMismatchedBitCast)
+		{
+			if(!Ice::isVectorType(v->getType()) && Ice::isVectorType(T(destType)))
+			{
+				Value *address = allocateStackVariable(destType);
+				createStore(v, address, T(v->getType()));
+				return createLoad(address, destType);
+			}
+			else if(Ice::isVectorType(v->getType()) && !Ice::isVectorType(T(destType)))
+			{
+				Value *address = allocateStackVariable(T(v->getType()));
+				createStore(v, address, T(v->getType()));
+				return createLoad(address, destType);
+			}
+		}
+
 		return createCast(Ice::InstCast::Bitcast, v, destType);
 	}
 
diff --git a/src/Shader/SamplerCore.cpp b/src/Shader/SamplerCore.cpp
index 0ee9014..9c58e70 100644
--- a/src/Shader/SamplerCore.cpp
+++ b/src/Shader/SamplerCore.cpp
@@ -1937,16 +1937,16 @@
 					{
 					case FORMAT_R8I:
 					case FORMAT_R8UI:
-					{
-						Int zero(0);
-						c.x = Unpack(As<Byte4>(c0), As<Byte4>(zero));
-						// Propagate sign bit
-						if(state.textureFormat == FORMAT_R8I)
 						{
-							c.x = (c.x << 8) >> 8;
+							Int zero(0);
+							c.x = Unpack(As<Byte4>(c0), As<Byte4>(zero));
+							// Propagate sign bit
+							if(state.textureFormat == FORMAT_R8I)
+							{
+								c.x = (c.x << 8) >> 8;
+							}
 						}
-					}
-					break;
+						break;
 					default:
 						c.x = Unpack(As<Byte4>(c0));
 						break;