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, ...@@ -259,6 +259,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true; 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(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); } void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
......
...@@ -774,6 +774,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -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(Label* label) { B(label); }
void LiftoffAssembler::emit_jump(Register target) { Br(target); } void LiftoffAssembler::emit_jump(Register target) { Br(target); }
......
...@@ -121,6 +121,11 @@ inline void SpillRegisters(LiftoffAssembler* assm, Regs... regs) { ...@@ -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 DoubleRegister kScratchDoubleReg = xmm7;
constexpr int kSubSpSize = 6; // 6 bytes for "sub esp, <imm32>" constexpr int kSubSpSize = 6; // 6 bytes for "sub esp, <imm32>"
...@@ -247,8 +252,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr, ...@@ -247,8 +252,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
break; break;
case LoadType::kI64Load8S: case LoadType::kI64Load8S:
movsx_b(dst.low_gp(), src_op); movsx_b(dst.low_gp(), src_op);
mov(dst.high_gp(), dst.low_gp()); liftoff::SignExtendI32ToI64(this, dst);
sar(dst.high_gp(), 31);
break; break;
case LoadType::kI32Load16U: case LoadType::kI32Load16U:
movzx_w(dst.gp(), src_op); movzx_w(dst.gp(), src_op);
...@@ -262,8 +266,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr, ...@@ -262,8 +266,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
break; break;
case LoadType::kI64Load16S: case LoadType::kI64Load16S:
movsx_w(dst.low_gp(), src_op); movsx_w(dst.low_gp(), src_op);
mov(dst.high_gp(), dst.low_gp()); liftoff::SignExtendI32ToI64(this, dst);
sar(dst.high_gp(), 31);
break; break;
case LoadType::kI32Load: case LoadType::kI32Load:
mov(dst.gp(), src_op); mov(dst.gp(), src_op);
...@@ -274,8 +277,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr, ...@@ -274,8 +277,7 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
break; break;
case LoadType::kI64Load32S: case LoadType::kI64Load32S:
mov(dst.low_gp(), src_op); mov(dst.low_gp(), src_op);
mov(dst.high_gp(), dst.low_gp()); liftoff::SignExtendI32ToI64(this, dst);
sar(dst.high_gp(), 31);
break; break;
case LoadType::kI64Load: { case LoadType::kI64Load: {
// Compute the operand for the load of the upper half. // Compute the operand for the load of the upper half.
...@@ -1311,7 +1313,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -1311,7 +1313,7 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true; return true;
case kExprI64SConvertI32: case kExprI64SConvertI32:
if (dst.low_gp() != src.gp()) mov(dst.low_gp(), src.gp()); 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); sar(dst.high_gp(), 31);
return true; return true;
case kExprI64UConvertI32: case kExprI64UConvertI32:
...@@ -1363,6 +1365,32 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -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(Label* label) { jmp(label); }
void LiftoffAssembler::emit_jump(Register target) { jmp(target); } void LiftoffAssembler::emit_jump(Register target) { jmp(target); }
......
...@@ -521,10 +521,15 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -521,10 +521,15 @@ class LiftoffAssembler : public TurboAssembler {
inline bool emit_f64_nearest_int(DoubleRegister dst, DoubleRegister src); inline bool emit_f64_nearest_int(DoubleRegister dst, DoubleRegister src);
inline void emit_f64_sqrt(DoubleRegister dst, DoubleRegister src); inline void emit_f64_sqrt(DoubleRegister dst, DoubleRegister src);
// type conversions.
inline bool emit_type_conversion(WasmOpcode opcode, LiftoffRegister dst, inline bool emit_type_conversion(WasmOpcode opcode, LiftoffRegister dst,
LiftoffRegister src, Label* trap = nullptr); 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(Label*);
inline void emit_jump(Register); inline void emit_jump(Register);
......
...@@ -637,6 +637,20 @@ class LiftoffCompiler { ...@@ -637,6 +637,20 @@ class LiftoffCompiler {
__ emit_##fn(dst.gp(), src.gp()); \ __ emit_##fn(dst.gp(), src.gp()); \
}); \ }); \
break; 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) \ #define CASE_FLOAT_UNOP(opcode, type, fn) \
case WasmOpcode::kExpr##opcode: \ case WasmOpcode::kExpr##opcode: \
EmitUnOp<kWasm##type, kWasm##type>( \ EmitUnOp<kWasm##type, kWasm##type>( \
...@@ -705,6 +719,11 @@ class LiftoffCompiler { ...@@ -705,6 +719,11 @@ class LiftoffCompiler {
&ExternalReference::wasm_uint64_to_float64, kNoTrap) &ExternalReference::wasm_uint64_to_float64, kNoTrap)
CASE_TYPE_CONVERSION(F64ConvertF32, F64, F32, nullptr, kNoTrap) CASE_TYPE_CONVERSION(F64ConvertF32, F64, F32, nullptr, kNoTrap)
CASE_TYPE_CONVERSION(F64ReinterpretI64, F64, I64, 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: case kExprI32Popcnt:
EmitI32UnOpWithCFallback(&LiftoffAssembler::emit_i32_popcnt, EmitI32UnOpWithCFallback(&LiftoffAssembler::emit_i32_popcnt,
&ExternalReference::wasm_word32_popcnt); &ExternalReference::wasm_word32_popcnt);
...@@ -719,6 +738,8 @@ class LiftoffCompiler { ...@@ -719,6 +738,8 @@ class LiftoffCompiler {
return unsupported(decoder, WasmOpcodes::OpcodeName(opcode)); return unsupported(decoder, WasmOpcodes::OpcodeName(opcode));
} }
#undef CASE_I32_UNOP #undef CASE_I32_UNOP
#undef CASE_I32_SIGN_EXTENSION
#undef CASE_I64_SIGN_EXTENSION
#undef CASE_FLOAT_UNOP #undef CASE_FLOAT_UNOP
#undef CASE_FLOAT_UNOP_WITH_CFALLBACK #undef CASE_FLOAT_UNOP_WITH_CFALLBACK
#undef CASE_TYPE_CONVERSION #undef CASE_TYPE_CONVERSION
......
...@@ -1072,6 +1072,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -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) { void LiftoffAssembler::emit_jump(Label* label) {
TurboAssembler::Branch(label); TurboAssembler::Branch(label);
} }
......
...@@ -962,6 +962,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -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) { void LiftoffAssembler::emit_jump(Label* label) {
TurboAssembler::Branch(label); TurboAssembler::Branch(label);
} }
......
...@@ -272,6 +272,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -272,6 +272,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true; 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(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); } void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
......
...@@ -272,6 +272,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -272,6 +272,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
return true; 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(Label* label) { BAILOUT("emit_jump"); }
void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); } void LiftoffAssembler::emit_jump(Register target) { BAILOUT("emit_jump"); }
......
...@@ -1253,6 +1253,29 @@ bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode, ...@@ -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(Label* label) { jmp(label); }
void LiftoffAssembler::emit_jump(Register target) { jmp(target); } 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