Commit e6b50eb0 authored by Deepti Gandluri's avatar Deepti Gandluri Committed by V8 LUCI CQ

[wasm-simd] Update new relaxed SIMD opcodes

Add new opcode numbers for relaxed-simd opcodes as in:
https://github.com/WebAssembly/relaxed-simd/pull/61, and updates
for decoded opcodes larger than two bytes.

Bug: v8:12284
Change-Id: I0bff22812243a39599bfeee3c0bc69171dd3c7d2
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3625835Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Deepti Gandluri <gdeepti@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80432}
parent 0e05d1b7
......@@ -154,15 +154,17 @@ class Decoder {
// Prefixed opcodes all use LEB128 encoding.
index = read_u32v<validate>(pc + 1, length, "prefixed opcode index");
*length += 1; // Prefix byte.
// Only support opcodes that go up to 0xFF (when decoded). Anything
// bigger will need 1 more byte, and the '<< 8' below will be wrong.
if (validate && V8_UNLIKELY(index > 0xff)) {
// Only support opcodes that go up to 0xFFF (when decoded). Anything
// bigger will need more than 2 bytes, and the '<< 12' below will be wrong.
if (validate && V8_UNLIKELY(index > 0xfff)) {
errorf(pc, "Invalid prefixed opcode %d", index);
// If size validation fails.
index = 0;
*length = 0;
}
if (index > 0xff) return static_cast<WasmOpcode>((*pc) << 12 | index);
return static_cast<WasmOpcode>((*pc) << 8 | index);
}
......
......@@ -581,6 +581,13 @@ constexpr bool WasmOpcodes::IsRelaxedSimdOpcode(WasmOpcode opcode) {
}
}
constexpr byte WasmOpcodes::ExtractPrefix(WasmOpcode opcode) {
// If the decoded opcode exceeds two bytes, shift an additional
// byte. For decoded opcodes that exceed 3 bytes, this would
// need to be fixed.
return (opcode > 0xffff) ? opcode >> 12 : opcode >> 8;
}
namespace impl {
#define DECLARE_SIG_ENUM(name, ...) kSigEnum_##name,
......@@ -618,11 +625,17 @@ constexpr WasmOpcodeSig GetAsmJsOpcodeSigIndex(byte opcode) {
constexpr WasmOpcodeSig GetSimdOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_SIMD_0_OPERAND_OPCODE(CASE) FOREACH_SIMD_MEM_OPCODE(CASE)
return FOREACH_SIMD_MVP_0_OPERAND_OPCODE(CASE) FOREACH_SIMD_MEM_OPCODE(CASE)
FOREACH_SIMD_MEM_1_OPERAND_OPCODE(CASE) kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetRelaxedSimdOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_RELAXED_SIMD_OPCODE(CASE) kSigEnum_None;
#undef CASE
}
constexpr WasmOpcodeSig GetAtomicOpcodeSigIndex(byte opcode) {
#define CASE(name, opc, sig) opcode == (opc & 0xFF) ? kSigEnum_##sig:
return FOREACH_ATOMIC_OPCODE(CASE) FOREACH_ATOMIC_0_OPERAND_OPCODE(CASE)
......@@ -644,6 +657,8 @@ constexpr std::array<WasmOpcodeSig, 256> kSimpleAsmjsExprSigTable =
base::make_array<256>(GetAsmJsOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kSimdExprSigTable =
base::make_array<256>(GetSimdOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kRelaxedSimdExprSigTable =
base::make_array<256>(GetRelaxedSimdOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kAtomicExprSigTable =
base::make_array<256>(GetAtomicOpcodeSigIndex);
constexpr std::array<WasmOpcodeSig, 256> kNumericExprSigTable =
......@@ -652,11 +667,14 @@ constexpr std::array<WasmOpcodeSig, 256> kNumericExprSigTable =
} // namespace impl
constexpr const FunctionSig* WasmOpcodes::Signature(WasmOpcode opcode) {
switch (opcode >> 8) {
switch (ExtractPrefix(opcode)) {
case 0:
return impl::kCachedSigs[impl::kShortSigTable[opcode]];
case kSimdPrefix:
case kSimdPrefix: {
if (IsRelaxedSimdOpcode(opcode))
return impl::kCachedSigs[impl::kRelaxedSimdExprSigTable[opcode & 0xFF]];
return impl::kCachedSigs[impl::kSimdExprSigTable[opcode & 0xFF]];
}
case kAtomicPrefix:
return impl::kCachedSigs[impl::kAtomicExprSigTable[opcode & 0xFF]];
case kNumericPrefix:
......
......@@ -523,24 +523,24 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(F64x2ConvertLowI32x4S, 0xfdfe, s_s) \
V(F64x2ConvertLowI32x4U, 0xfdff, s_s)
#define FOREACH_RELAXED_SIMD_OPCODE(V) \
V(I8x16RelaxedSwizzle, 0xfda2, s_ss) \
V(I8x16RelaxedLaneSelect, 0xfdb2, s_sss) \
V(I16x8RelaxedLaneSelect, 0xfdb3, s_sss) \
V(I32x4RelaxedLaneSelect, 0xfdd2, s_sss) \
V(I64x2RelaxedLaneSelect, 0xfdd3, s_sss) \
V(F32x4Qfma, 0xfdaf, s_sss) \
V(F32x4Qfms, 0xfdb0, s_sss) \
V(F64x2Qfma, 0xfdcf, s_sss) \
V(F64x2Qfms, 0xfdd0, s_sss) \
V(F32x4RelaxedMin, 0xfdb4, s_ss) \
V(F32x4RelaxedMax, 0xfde2, s_ss) \
V(F64x2RelaxedMin, 0xfdd4, s_ss) \
V(F64x2RelaxedMax, 0xfdee, s_ss) \
V(I32x4RelaxedTruncF32x4S, 0xfda5, s_s) \
V(I32x4RelaxedTruncF32x4U, 0xfda6, s_s) \
V(I32x4RelaxedTruncF64x2SZero, 0xfdc5, s_s) \
V(I32x4RelaxedTruncF64x2UZero, 0xfdc6, s_s)
#define FOREACH_RELAXED_SIMD_OPCODE(V) \
V(I8x16RelaxedSwizzle, 0xfd100, s_ss) \
V(I32x4RelaxedTruncF32x4S, 0xfd101, s_s) \
V(I32x4RelaxedTruncF32x4U, 0xfd102, s_s) \
V(I32x4RelaxedTruncF64x2SZero, 0xfd103, s_s) \
V(I32x4RelaxedTruncF64x2UZero, 0xfd104, s_s) \
V(F32x4Qfma, 0xfd105, s_sss) \
V(F32x4Qfms, 0xfd106, s_sss) \
V(F64x2Qfma, 0xfd107, s_sss) \
V(F64x2Qfms, 0xfd108, s_sss) \
V(I8x16RelaxedLaneSelect, 0xfd109, s_sss) \
V(I16x8RelaxedLaneSelect, 0xfd10a, s_sss) \
V(I32x4RelaxedLaneSelect, 0xfd10b, s_sss) \
V(I64x2RelaxedLaneSelect, 0xfd10c, s_sss) \
V(F32x4RelaxedMin, 0xfd10d, s_ss) \
V(F32x4RelaxedMax, 0xfd10e, s_ss) \
V(F64x2RelaxedMin, 0xfd10f, s_ss) \
V(F64x2RelaxedMax, 0xfd110, s_ss)
#define FOREACH_SIMD_1_OPERAND_1_PARAM_OPCODE(V) \
V(I8x16ExtractLaneS, 0xfd15, _) \
......@@ -838,6 +838,13 @@ class V8_EXPORT_PRIVATE WasmOpcodes {
static constexpr bool IsBreakable(WasmOpcode);
static constexpr MessageTemplate TrapReasonToMessageId(TrapReason);
// Prefixed opcodes are encoded as 1 prefix byte, followed by LEB encoded
// opcode bytes. With the addition of relaxed SIMD opcodes, the decoded
// length of opcode bytes exceeds two bytes. This method, and other mehtods
// that operate on prefixed opcodes, handle upto 3 byte opcodes, when
// opcodes exceed a decoded length of 3 bytes, this code, and elsewhere
// that assumes 3-bytes to be the maximum opcode length should be updated.
static constexpr byte ExtractPrefix(WasmOpcode);
static inline const char* TrapReasonMessage(TrapReason);
};
......
......@@ -304,6 +304,13 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
}
}
// This method handles upcodes with decoded length of 3-bytes
// update is we exceed that opcode length. (More details in
// wasm-opcodes.h)
inline uint16_t ExtractPrefixedOpcodeBytes(WasmOpcode opcode) {
return (opcode > 0xffff) ? opcode & 0x0fff : opcode & 0xff;
}
} // namespace wasm
} // namespace internal
} // namespace v8
......@@ -915,7 +922,7 @@ inline WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
//------------------------------------------------------------------------------
#define TO_BYTE(val) static_cast<byte>(val)
// Encode all simd ops as a 2-byte LEB.
#define WASM_SIMD_OP(op) kSimdPrefix, U32V_2(op & 0xff)
#define WASM_SIMD_OP(op) kSimdPrefix, U32V_2(ExtractPrefixedOpcodeBytes(op))
#define WASM_SIMD_OPN(op, ...) __VA_ARGS__, WASM_SIMD_OP(op)
#define WASM_SIMD_SPLAT(Type, ...) __VA_ARGS__, WASM_SIMD_OP(kExpr##Type##Splat)
#define WASM_SIMD_UNOP(op, x) x, WASM_SIMD_OP(op)
......
......@@ -4667,9 +4667,9 @@ class WasmOpcodeLengthTest : public TestWithZone {
// Helper to check for prefixed opcodes, which can have multiple bytes.
void ExpectLengthPrefixed(unsigned operands, WasmOpcode opcode) {
uint8_t prefix = (opcode >> 8) & 0xff;
uint8_t prefix = WasmOpcodes::ExtractPrefix(opcode);
DCHECK(WasmOpcodes::IsPrefixOpcode(static_cast<WasmOpcode>(prefix)));
uint8_t index = opcode & 0xff;
uint16_t index = ExtractPrefixedOpcodeBytes(opcode);
uint8_t encoded[2] = {0, 0};
uint8_t* p = encoded;
unsigned len = static_cast<unsigned>(LEBHelper::sizeof_u32v(index));
......
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