Commit 9da48031 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[Liftoff] Implement sign extensions

This implements the five sign extension opcodes for ia32 and x64 (and
bails out on other architectures).

R=titzer@chromium.org

Bug: v8:6600
Change-Id: Ibb8bae0e229e276b346f2d054b51864a0995a096
Reviewed-on: https://chromium-review.googlesource.com/1174533
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55898}
parent 74320a1b
......@@ -259,6 +259,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true;
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i8");
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i8");
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i32");
}
void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
......
......@@ -774,6 +774,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
}
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
sxtb(dst, src);
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
sxth(dst, src);
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
sxtb(dst.gp(), src.gp());
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
sxth(dst.gp(), src.gp());
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
sxtw(dst.gp(), src.gp());
}
void LiftoffAssembler::emit_jump(Label* label) { B(label); }
void LiftoffAssembler::emit_jump(Register target) { Br(target); }
......
......@@ -121,6 +121,11 @@ inline void SpillRegisters(LiftoffAssembler* assm, Regs... regs) {
}
}
inline void SignExtendI32ToI64(Assembler* assm, LiftoffRegister reg) {
assm->mov(reg.high_gp(), reg.low_gp());
assm->sar(reg.high_gp(), 31);
}
constexpr DoubleRegister kScratchDoubleReg = xmm7;
constexpr int kSubSpSize = 6; // 6 bytes for "sub esp, <imm32>"
......@@ -247,8 +252,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
break;
case LoadType::kI64Load8S:
movsx_b(dst.low_gp(), src_op);
mov(dst.high_gp(), dst.low_gp());
sar(dst.high_gp(), 31);
liftoff::SignExtendI32ToI64(this, dst);
break;
case LoadType::kI32Load16U:
movzx_w(dst.gp(), src_op);
......@@ -262,8 +266,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
break;
case LoadType::kI64Load16S:
movsx_w(dst.low_gp(), src_op);
mov(dst.high_gp(), dst.low_gp());
sar(dst.high_gp(), 31);
liftoff::SignExtendI32ToI64(this, dst);
break;
case LoadType::kI32Load:
mov(dst.gp(), src_op);
......@@ -274,8 +277,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
break;
case LoadType::kI64Load32S:
mov(dst.low_gp(), src_op);
mov(dst.high_gp(), dst.low_gp());
sar(dst.high_gp(), 31);
liftoff::SignExtendI32ToI64(this, dst);
break;
case LoadType::kI64Load: {
// Compute the operand for the load of the upper half.
......@@ -1311,7 +1313,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true;
case kExprI64SConvertI32:
if (dst.low_gp() != src.gp()) mov(dst.low_gp(), src.gp());
mov(dst.high_gp(), src.gp());
if (dst.high_gp() != src.gp()) mov(dst.high_gp(), src.gp());
sar(dst.high_gp(), 31);
return true;
case kExprI64UConvertI32:
......@@ -1363,6 +1365,32 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
}
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
movsx_b(dst, src);
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
movsx_w(dst, src);
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
movsx_b(dst.low_gp(), src.low_gp());
liftoff::SignExtendI32ToI64(this, dst);
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
movsx_w(dst.low_gp(), src.low_gp());
liftoff::SignExtendI32ToI64(this, dst);
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
if (dst.low_gp() != src.low_gp()) mov(dst.low_gp(), src.low_gp());
liftoff::SignExtendI32ToI64(this, dst);
}
void LiftoffAssembler::emit_jump(Label* label) { jmp(label); }
void LiftoffAssembler::emit_jump(Register target) { jmp(target); }
......
......@@ -521,10 +521,15 @@ class LiftoffAssembler : public TurboAssembler {
inline bool emit_f64_nearest_int(DoubleRegister dst, DoubleRegister src);
inline void emit_f64_sqrt(DoubleRegister dst, DoubleRegister src);
// type conversions.
inline bool emit_type_conversion(WasmOpcode opcode, LiftoffRegister dst,
LiftoffRegister src, Label* trap = nullptr);
inline void emit_i32_signextend_i8(Register dst, Register src);
inline void emit_i32_signextend_i16(Register dst, Register src);
inline void emit_i64_signextend_i8(LiftoffRegister dst, LiftoffRegister src);
inline void emit_i64_signextend_i16(LiftoffRegister dst, LiftoffRegister src);
inline void emit_i64_signextend_i32(LiftoffRegister dst, LiftoffRegister src);
inline void emit_jump(Label*);
inline void emit_jump(Register);
......
......@@ -637,6 +637,20 @@ class LiftoffCompiler {
__ emit_##fn(dst.gp(), src.gp()); \
}); \
break;
#define CASE_I32_SIGN_EXTENSION(opcode, fn) \
case WasmOpcode::kExpr##opcode: \
EmitUnOp<kWasmI32, kWasmI32>( \
[=](LiftoffRegister dst, LiftoffRegister src) { \
__ emit_##fn(dst.gp(), src.gp()); \
}); \
break;
#define CASE_I64_SIGN_EXTENSION(opcode, fn) \
case WasmOpcode::kExpr##opcode: \
EmitUnOp<kWasmI64, kWasmI64>( \
[=](LiftoffRegister dst, LiftoffRegister src) { \
__ emit_##fn(dst, src); \
}); \
break;
#define CASE_FLOAT_UNOP(opcode, type, fn) \
case WasmOpcode::kExpr##opcode: \
EmitUnOp<kWasm##type, kWasm##type>( \
......@@ -705,6 +719,11 @@ class LiftoffCompiler {
&ExternalReference::wasm_uint64_to_float64, kNoTrap)
CASE_TYPE_CONVERSION(F64ConvertF32, F64, F32, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(F64ReinterpretI64, F64, I64, nullptr, kNoTrap)
CASE_I32_SIGN_EXTENSION(I32SExtendI8, i32_signextend_i8)
CASE_I32_SIGN_EXTENSION(I32SExtendI16, i32_signextend_i16)
CASE_I64_SIGN_EXTENSION(I64SExtendI8, i64_signextend_i8)
CASE_I64_SIGN_EXTENSION(I64SExtendI16, i64_signextend_i16)
CASE_I64_SIGN_EXTENSION(I64SExtendI32, i64_signextend_i32)
case kExprI32Popcnt:
EmitI32UnOpWithCFallback(&LiftoffAssembler::emit_i32_popcnt,
&ExternalReference::wasm_word32_popcnt);
......@@ -719,6 +738,8 @@ class LiftoffCompiler {
return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
}
#undef CASE_I32_UNOP
#undef CASE_I32_SIGN_EXTENSION
#undef CASE_I64_SIGN_EXTENSION
#undef CASE_FLOAT_UNOP
#undef CASE_FLOAT_UNOP_WITH_CFALLBACK
#undef CASE_TYPE_CONVERSION
......
......@@ -1072,6 +1072,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
}
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i8");
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i8");
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i32");
}
void LiftoffAssembler::emit_jump(Label* label) {
TurboAssembler::Branch(label);
}
......
......@@ -962,6 +962,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
}
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i8");
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i8");
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i32");
}
void LiftoffAssembler::emit_jump(Label* label) {
TurboAssembler::Branch(label);
}
......
......@@ -272,6 +272,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true;
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i8");
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i8");
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i32");
}
void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
......
......@@ -272,6 +272,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true;
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i8");
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
BAILOUT("emit_i32_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i8");
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i16");
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
BAILOUT("emit_i64_signextend_i32");
}
void LiftoffAssembler::emit_jump(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
......
......@@ -1253,6 +1253,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
}
}
void LiftoffAssembler::emit_i32_signextend_i8(Register dst, Register src) {
movsxbl(dst, src);
}
void LiftoffAssembler::emit_i32_signextend_i16(Register dst, Register src) {
movsxwl(dst, src);
}
void LiftoffAssembler::emit_i64_signextend_i8(LiftoffRegister dst,
LiftoffRegister src) {
movsxbq(dst.gp(), src.gp());
}
void LiftoffAssembler::emit_i64_signextend_i16(LiftoffRegister dst,
LiftoffRegister src) {
movsxwq(dst.gp(), src.gp());
}
void LiftoffAssembler::emit_i64_signextend_i32(LiftoffRegister dst,
LiftoffRegister src) {
movsxlq(dst.gp(), src.gp());
}
void LiftoffAssembler::emit_jump(Label* label) { jmp(label); }
void LiftoffAssembler::emit_jump(Register target) { jmp(target); }
......
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