SpirvShader: Implement GLSLstd450Ldexp

Bug: b/126873455
Tests: dEQP-VK.glsl.builtin.function.common.ldexp.*
Change-Id: Ie8ab0db7a7f712c5f876f521773217be5f350e4f
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28648
Tested-by: Ben Clayton <bclayton@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SpirvShader.cpp b/src/Pipeline/SpirvShader.cpp
index fb7e620..aff801e 100644
--- a/src/Pipeline/SpirvShader.cpp
+++ b/src/Pipeline/SpirvShader.cpp
@@ -59,6 +59,14 @@
 	{
 		return a * b + c;
 	}
+
+	// Returns the exponent of the floating point number f.
+	// Assumes IEEE 754
+	rr::RValue<sw::SIMD::Int> Exponent(rr::RValue<sw::SIMD::Float> f)
+	{
+		auto v = rr::As<sw::SIMD::UInt>(f);
+		return (sw::SIMD::Int((v >> sw::SIMD::UInt(23)) & sw::SIMD::UInt(0xFF)) - sw::SIMD::Int(126));
+	}
 }
 
 namespace sw
@@ -3241,6 +3249,21 @@
 			}
 			break;
 		}
+		case GLSLstd450Ldexp:
+		{
+			auto significand = GenericValue(this, routine, insn.word(5));
+			auto exponent = GenericValue(this, routine, insn.word(6));
+			for (auto i = 0u; i < type.sizeInComponents; i++)
+			{
+				// Assumes IEEE 754
+				auto significandExponent = Exponent(significand.Float(i));
+				auto combinedExponent = exponent.Int(i) + significandExponent;
+				SIMD::UInt v = (significand.UInt(i) & SIMD::UInt(0x807FFFFF)) |
+						(SIMD::UInt(combinedExponent + SIMD::Int(126)) << SIMD::UInt(23));
+				dst.move(i, As<SIMD::Float>(v));
+			}
+			break;
+		}
 		default:
 			UNIMPLEMENTED("Unhandled ExtInst %d", extInstIndex);
 		}
@@ -3319,7 +3342,7 @@
 		auto isNotZero = CmpNEQ(v & SIMD::UInt(0x7FFFFFFF), SIMD::UInt(0));
 		auto zeroSign = v & SIMD::UInt(0x80000000) & ~isNotZero;
 		auto significand = As<SIMD::Float>((v & SIMD::UInt(0x807FFFFF) | SIMD::UInt(0x3F000000)) & isNotZero | zeroSign);
-		auto exponent = (SIMD::Int((v >> SIMD::UInt(23)) & SIMD::UInt(0xFF)) - SIMD::Int(126)) & SIMD::Int(isNotZero);
+		auto exponent = Exponent(val) & SIMD::Int(isNotZero);
 		return std::make_pair(significand, exponent);
 	}