Index: src/compiler/wasm-compiler.cc |
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc |
index 7270ddd24848854d9e42a020404ed04bdcca7ed4..d3193e3b2443947f9e9b77d89c88d63bc38b11b0 100644 |
--- a/src/compiler/wasm-compiler.cc |
+++ b/src/compiler/wasm-compiler.cc |
@@ -992,6 +992,117 @@ Node* WasmGraphBuilder::MaskShiftCount64(Node* node) { |
return node; |
} |
+Node* WasmGraphBuilder::BuildChangeEndianness(Node* node, MachineType memtype, |
+ wasm::LocalType wasmtype) { |
+ Node* result; |
+ Node* value = node; |
+ wasm::WasmOpcode shiftLeftOpcode; |
+ wasm::WasmOpcode shiftRightOpcode; |
+ wasm::WasmOpcode andOpcode, orOpcode; |
+ int valueSizeInBytes = 1 << ElementSizeLog2Of(memtype.representation()); |
+ int valueSizeInBits = 8 * valueSizeInBytes; |
+ bool isFloat = false; |
+ |
+ switch (memtype.representation()) { |
+ case MachineRepresentation::kFloat64: |
+ value = Unop(wasm::kExprI64ReinterpretF64, node); |
+ isFloat = true; |
+ case MachineRepresentation::kWord64: |
+ shiftLeftOpcode = wasm::kExprI64Shl; |
+ shiftRightOpcode = wasm::kExprI64ShrU; |
+ andOpcode = wasm::kExprI64And; |
+ orOpcode = wasm::kExprI64Ior; |
+ result = jsgraph()->Int64Constant(0); |
+ break; |
+ case MachineRepresentation::kFloat32: |
+ value = Unop(wasm::kExprI32ReinterpretF32, node); |
+ isFloat = true; |
+ case MachineRepresentation::kWord32: |
+ case MachineRepresentation::kWord16: |
+ shiftLeftOpcode = wasm::kExprI32Shl; |
+ shiftRightOpcode = wasm::kExprI32ShrU; |
+ andOpcode = wasm::kExprI32And; |
+ orOpcode = wasm::kExprI32Ior; |
+ result = jsgraph()->Int32Constant(0); |
+ break; |
+ case MachineRepresentation::kWord8: |
+ // No need to change endianness for byte size, return original node |
+ return node; |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ |
+ int i; |
+ uint32_t shiftCount; |
+ |
+ for (i = 0, shiftCount = valueSizeInBits - 8; i < valueSizeInBits / 2; |
+ i += 8, shiftCount -= 16) { |
+ DCHECK(shiftCount > 0); |
+ DCHECK((shiftCount + 8) % 16 == 0); |
+ |
+ Node* shiftLower = |
+ Binop(shiftLeftOpcode, value, jsgraph()->Int32Constant(shiftCount)); |
titzer
2016/06/06 07:44:00
Reusing the Binop() routine is a little inefficien
|
+ Node* shiftHigher = |
+ Binop(shiftRightOpcode, value, jsgraph()->Int32Constant(shiftCount)); |
+ |
+ Node* lowerByte; |
+ Node* higherByte; |
+ |
+ if (valueSizeInBits > 32) { |
+ lowerByte = |
+ Binop(andOpcode, shiftLower, |
+ jsgraph()->Int64Constant(0xFFl << (valueSizeInBits - 8 - i))); |
+ higherByte = |
+ Binop(andOpcode, shiftHigher, jsgraph()->Int64Constant(0xFFl << i)); |
+ } else { |
+ lowerByte = |
+ Binop(andOpcode, shiftLower, |
+ jsgraph()->Int32Constant(0xFF << (valueSizeInBits - 8 - i))); |
+ higherByte = |
+ Binop(andOpcode, shiftHigher, jsgraph()->Int32Constant(0xFF << i)); |
+ } |
+ |
+ result = Binop(orOpcode, result, lowerByte); |
+ result = Binop(orOpcode, result, higherByte); |
+ } |
+ |
+ if (isFloat) { |
+ switch (memtype.representation()) { |
+ case MachineRepresentation::kFloat64: |
+ result = Unop(wasm::kExprF64ReinterpretI64, result); |
+ break; |
+ case MachineRepresentation::kFloat32: |
+ result = Unop(wasm::kExprF32ReinterpretI32, result); |
+ break; |
+ default: |
+ UNREACHABLE(); |
+ break; |
+ } |
+ } |
+ |
+ // We need to sign extend the value |
+ if (memtype.IsSigned()) { |
+ DCHECK(!isFloat); |
+ if ((wasmtype == wasm::kAstI64 || wasmtype == wasm::kAstI32) && |
+ valueSizeInBits < 32) { |
+ uint32_t mask = 1 << (valueSizeInBits - 1); |
+ |
+ Node* signBit = |
+ Binop(wasm::kExprI32And, result, jsgraph()->Int32Constant(mask)); |
+ Diamond d(graph(), jsgraph()->common(), Unop(wasm::kExprI32Eqz, signBit)); |
titzer
2016/06/06 07:44:00
What about using (x << machine_width - width) >> (
|
+ |
+ result = |
+ d.Phi(MachineRepresentation::kWord32, result, |
+ Binop(wasm::kExprI32Ior, result, |
+ jsgraph()->Int32Constant(0xFFFFFFFF << valueSizeInBits))); |
+ } |
+ } |
+ |
+ return result; |
+} |
+ |
Node* WasmGraphBuilder::BuildF32Neg(Node* input) { |
Node* result = |
Unop(wasm::kExprF32ReinterpretI32, |
@@ -2768,6 +2879,11 @@ Node* WasmGraphBuilder::LoadMem(wasm::LocalType type, MachineType memtype, |
} else { |
load = BuildUnalignedLoad(type, memtype, index, offset, alignment); |
} |
+#if defined(V8_TARGET_BIG_ENDIAN) |
+ // TODO(mips-team) Implement byte swap turbofan operator |
john.yan
2016/06/07 17:47:00
FYI: https://codereview.chromium.org/2045943002/
|
+ // and use it if available for better performance |
+ load = BuildChangeEndianness(load, memtype, type); |
+#endif |
if (type == wasm::kAstI64 && |
ElementSizeLog2Of(memtype.representation()) < 3) { |
@@ -2888,6 +3004,12 @@ Node* WasmGraphBuilder::StoreMem(MachineType memtype, Node* index, |
bool aligned = static_cast<int>(alignment) >= |
ElementSizeLog2Of(memtype.representation()); |
+#if defined(V8_TARGET_BIG_ENDIAN) |
+ // TODO(mips-team) Implement byte swap turbofan operator |
+ // and use it if available for better performance |
+ val = BuildChangeEndianness(val, memtype); |
+#endif |
+ |
if (aligned || |
jsgraph()->machine()->UnalignedStoreSupported(memtype, alignment)) { |
StoreRepresentation rep(memtype.representation(), kNoWriteBarrier); |