Commit f328613d authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Fix i8 to i32 sign extension on ia32

The source register of {movsx_b} must be a byte register.

Drive-by: Add missing sign extension opcodes to wasm-constants.js.

R=herhut@chromium.org

Bug: chromium:916869
Change-Id: I571c1ea2a0e197afefc810f306eed238250cd5e0
Reviewed-on: https://chromium-review.googlesource.com/c/1386110Reviewed-by: 's avatarStephan Herhut <herhut@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58394}
parent 2d2c1374
...@@ -123,6 +123,15 @@ inline void SignExtendI32ToI64(Assembler* assm, LiftoffRegister reg) { ...@@ -123,6 +123,15 @@ inline void SignExtendI32ToI64(Assembler* assm, LiftoffRegister reg) {
assm->sar(reg.high_gp(), 31); assm->sar(reg.high_gp(), 31);
} }
// Get a temporary byte register, using {candidate} if possible.
// Might spill, but always keeps status flags intact.
inline Register GetTmpByteRegister(LiftoffAssembler* assm, Register candidate) {
if (candidate.is_byte_register()) return candidate;
// {GetUnusedRegister()} may insert move instructions to spill registers to
// the stack. This is OK because {mov} does not change the status flags.
return assm->GetUnusedRegister(liftoff::kByteRegs).gp();
}
constexpr DoubleRegister kScratchDoubleReg = xmm7; constexpr DoubleRegister kScratchDoubleReg = xmm7;
constexpr int kSubSpSize = 6; // 6 bytes for "sub esp, <imm32>" constexpr int kSubSpSize = 6; // 6 bytes for "sub esp, <imm32>"
...@@ -1410,7 +1419,9 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -1410,7 +1419,9 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
} }
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) { void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
movsx_b(dst, src); Register byte_reg = liftoff::GetTmpByteRegister(this, src);
if (byte_reg != src) mov(byte_reg, src);
movsx_b(dst, byte_reg);
} }
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) { void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
...@@ -1460,16 +1471,6 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label, ...@@ -1460,16 +1471,6 @@ void LiftoffAssembler::emit_cond_jump(Condition cond, Label* label,
namespace liftoff { namespace liftoff {
// Get a temporary byte register, using {candidate} if possible.
// Might spill, but always keeps status flags intact.
inline Register GetTmpByteRegister(LiftoffAssembler* assm, Register candidate) {
if (candidate.is_byte_register()) return candidate;
LiftoffRegList pinned = LiftoffRegList::ForRegs(candidate);
// {GetUnusedRegister()} may insert move instructions to spill registers to
// the stack. This is OK because {mov} does not change the status flags.
return assm->GetUnusedRegister(liftoff::kByteRegs, pinned).gp();
}
// Setcc into dst register, given a scratch byte register (might be the same as // Setcc into dst register, given a scratch byte register (might be the same as
// dst). Never spills. // dst). Never spills.
inline void setcc_32_no_spill(LiftoffAssembler* assm, Condition cond, inline void setcc_32_no_spill(LiftoffAssembler* assm, Condition cond,
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load('test/mjsunit/wasm/wasm-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
const sig = builder.addType(makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]));
builder.addFunction('main', sig)
.addBody([kExprI32Const, 0x01, kExprI32SExtendI8])
.exportFunc();
const instance = builder.instantiate();
assertEquals(1, instance.exports.main());
...@@ -352,6 +352,11 @@ let kExprI32ReinterpretF32 = 0xbc; ...@@ -352,6 +352,11 @@ let kExprI32ReinterpretF32 = 0xbc;
let kExprI64ReinterpretF64 = 0xbd; let kExprI64ReinterpretF64 = 0xbd;
let kExprF32ReinterpretI32 = 0xbe; let kExprF32ReinterpretI32 = 0xbe;
let kExprF64ReinterpretI64 = 0xbf; let kExprF64ReinterpretI64 = 0xbf;
let kExprI32SExtendI8 = 0xc0;
let kExprI32SExtendI16 = 0xc1;
let kExprI64SExtendI8 = 0xc2;
let kExprI64SExtendI16 = 0xc3;
let kExprI64SExtendI32 = 0xc4;
// Prefix opcodes // Prefix opcodes
let kNumericPrefix = 0xfc; let kNumericPrefix = 0xfc;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment