Skip to content

Commit

Permalink
Simd i8x16.extract_lane_s instruction implementation.
Browse files Browse the repository at this point in the history
Including:
1. All necessary code for SIMD lanes accessing.
2. i8x16.extract_lane_s implementation.
  • Loading branch information
lizhengxing committed Mar 9, 2018
1 parent ba6b566 commit 4f81159
Show file tree
Hide file tree
Showing 27 changed files with 2,651 additions and 2,364 deletions.
9 changes: 9 additions & 0 deletions src/binary-reader-interp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ class BinaryReaderInterp : public BinaryReaderNop {
wabt::Result OnTernaryExpr(wabt::Opcode opcode) override;
wabt::Result OnUnreachableExpr() override;
wabt::Result EndFunctionBody(Index index) override;
wabt::Result OnSimd1LaneImmExpr(wabt::Opcode opcode, Type type, uint32_t value) override;

wabt::Result EndElemSegmentInitExpr(Index index) override;
wabt::Result OnElemSegmentFunctionIndexCount(Index index,
Expand Down Expand Up @@ -1179,6 +1180,14 @@ wabt::Result BinaryReaderInterp::OnTernaryExpr(wabt::Opcode opcode) {
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::OnSimd1LaneImmExpr(wabt::Opcode opcode, Type type,
uint32_t value) {
CHECK_RESULT(typechecker_.OnSimdLane(opcode, type));
CHECK_RESULT(EmitOpcode(opcode));
CHECK_RESULT(EmitI8(static_cast<uint8_t>(value)));
return wabt::Result::Ok;
}

wabt::Result BinaryReaderInterp::OnAtomicLoadExpr(Opcode opcode,
uint32_t alignment_log2,
Address offset) {
Expand Down
5 changes: 5 additions & 0 deletions src/binary-reader-ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ class BinaryReaderIR : public BinaryReaderNop {
Result OnTernaryExpr(Opcode opcode) override;
Result OnUnreachableExpr() override;
Result EndFunctionBody(Index index) override;
Result OnSimd1LaneImmExpr(Opcode opcode, Type type, uint32_t value) override;

Result OnElemSegmentCount(Index count) override;
Result BeginElemSegment(Index index, Index table_index) override;
Expand Down Expand Up @@ -834,6 +835,10 @@ Result BinaryReaderIR::EndFunctionBody(Index index) {
return Result::Ok;
}

Result BinaryReaderIR::OnSimd1LaneImmExpr(Opcode opcode, Type type, uint32_t value) {
return AppendExpr(MakeUnique<Simd1LaneImmExpr>(opcode, type, value));
}

Result BinaryReaderIR::OnElemSegmentCount(Index count) {
WABT_TRY
module_->elem_segments.reserve(count);
Expand Down
5 changes: 5 additions & 0 deletions src/binary-reader-logging.cc
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,11 @@ Result BinaryReaderLogging::OnTryExpr(Index num_types, Type* sig_types) {
return reader_->OnTryExpr(num_types, sig_types);
}

Result BinaryReaderLogging::OnSimd1LaneImmExpr(Opcode opcode, Type type, uint32_t value) {
LOGF("OnSimdLaneExpr (lane: %d)\n", value);
return reader_->OnSimd1LaneImmExpr(opcode, type, value);
}

Result BinaryReaderLogging::OnDataSegmentData(Index index,
const void* data,
Address size) {
Expand Down
1 change: 1 addition & 0 deletions src/binary-reader-logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Address offset) override;
Result EndFunctionBody(Index index) override;
Result EndCodeSection() override;
Result OnSimd1LaneImmExpr(Opcode opcode, Type type, uint32_t value) override;

Result BeginElemSection(Offset size) override;
Result OnElemSegmentCount(Index count) override;
Expand Down
3 changes: 3 additions & 0 deletions src/binary-reader-nop.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result OnUnreachableExpr() override { return Result::Ok; }
Result EndFunctionBody(Index index) override { return Result::Ok; }
Result EndCodeSection() override { return Result::Ok; }
Result OnSimd1LaneImmExpr(Opcode opcode, Type type, uint32_t value) override {
return Result::Ok;
}

/* Elem section */
Result BeginElemSection(Offset size) override { return Result::Ok; }
Expand Down
9 changes: 9 additions & 0 deletions src/binary-reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,15 @@ Result BinaryReader::ReadFunctionBody(Offset end_offset) {
CALLBACK0(OnOpcodeBare);
break;

case Opcode::I8X16ExtractLaneS: {
ERROR_UNLESS_OPCODE_ENABLED(opcode);
uint8_t dLane;
CHECK_RESULT(ReadU8(&dLane, "Lane idx"));
CALLBACK(OnSimd1LaneImmExpr, opcode, Type::I32, dLane);
CALLBACK(OnOpcodeUint32, dLane);
break;
}

case Opcode::I32TruncSF32:
case Opcode::I32TruncSF64:
case Opcode::I32TruncUF32:
Expand Down
3 changes: 3 additions & 0 deletions src/binary-reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ class BinaryReaderDelegate {
virtual Result EndFunctionBody(Index index) = 0;
virtual Result EndCodeSection() = 0;

/* Simd instructions with Lane Imm operand*/
virtual Result OnSimd1LaneImmExpr(Opcode opcode, Type type, uint32_t value) = 0;

/* Elem section */
virtual Result BeginElemSection(Offset size) = 0;
virtual Result OnElemSegmentCount(Index count) = 0;
Expand Down
6 changes: 6 additions & 0 deletions src/binary-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,12 @@ void BinaryWriter::WriteExpr(const Func* func, const Expr* expr) {
case ExprType::Ternary:
WriteOpcode(stream_, cast<TernaryExpr>(expr)->opcode);
break;
case ExprType::Simd1LaneImm: {
const Opcode opcode = cast<Simd1LaneImmExpr>(expr)->opcode;
WriteOpcode(stream_, opcode);
stream_->WriteU8(static_cast<uint8_t>(cast<Simd1LaneImmExpr>(expr)->val), "Simd Lane literal");
break;
}
case ExprType::Unreachable:
WriteOpcode(stream_, Opcode::Unreachable);
break;
Expand Down
23 changes: 23 additions & 0 deletions src/c-writer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ class CWriter {
void Write(const StoreExpr&);
void Write(const UnaryExpr&);
void Write(const TernaryExpr&);
void Write(const Simd1LaneImmExpr&);

const WriteCOptions* options_ = nullptr;
const Module* module_ = nullptr;
Expand Down Expand Up @@ -1619,6 +1620,11 @@ void CWriter::Write(const ExprList& exprs) {
Write(*cast<TernaryExpr>(&expr));
break;

case ExprType::Simd1LaneImm: {
Write(*cast<Simd1LaneImmExpr>(&expr));
break;
}

case ExprType::Unreachable:
Write("UNREACHABLE;", Newline());
return;
Expand Down Expand Up @@ -2172,6 +2178,23 @@ void CWriter::Write(const TernaryExpr& expr) {
}
}

void CWriter::Write(const Simd1LaneImmExpr& expr) {
Type result_type = expr.opcode.GetResultType();

switch (expr.opcode) {
case Opcode::I8X16ExtractLaneS: {
Write(StackVar(0, result_type), " = ", expr.opcode.GetName(), "(" ,
StackVar(0),", lane Imm: ", expr.val, ");", Newline());
DropTypes(1);
break;
}
default:
WABT_UNREACHABLE;
}

PushType(result_type);
}

void CWriter::WriteCHeader() {
stream_ = h_stream_;
std::string guard = GenerateHeaderGuard();
Expand Down
5 changes: 5 additions & 0 deletions src/expr-visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,11 @@ Result ExprVisitor::HandleDefaultState(Expr* expr) {
CHECK_RESULT(delegate_->OnTernaryExpr(cast<TernaryExpr>(expr)));
break;

case ExprType::Simd1LaneImm: {
CHECK_RESULT(delegate_->OnSimd1LaneImmExpr(cast<Simd1LaneImmExpr>(expr)));
break;
}

case ExprType::Unreachable:
CHECK_RESULT(delegate_->OnUnreachableExpr(cast<UnreachableExpr>(expr)));
break;
Expand Down
2 changes: 2 additions & 0 deletions src/expr-visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class ExprVisitor::Delegate {
virtual Result OnAtomicRmwExpr(AtomicRmwExpr*) = 0;
virtual Result OnAtomicRmwCmpxchgExpr(AtomicRmwCmpxchgExpr*) = 0;
virtual Result OnTernaryExpr(TernaryExpr*) = 0;
virtual Result OnSimd1LaneImmExpr(Simd1LaneImmExpr*) = 0;
};

class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
Expand Down Expand Up @@ -164,6 +165,7 @@ class ExprVisitor::DelegateNop : public ExprVisitor::Delegate {
return Result::Ok;
}
Result OnTernaryExpr(TernaryExpr*) override { return Result::Ok; }
Result OnSimd1LaneImmExpr(Simd1LaneImmExpr*) override { return Result::Ok; }
};

} // namespace wabt
Expand Down
38 changes: 38 additions & 0 deletions src/interp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ template <>
float FromRep<float>(uint32_t x) { return Bitcast<float>(x); }
template <>
double FromRep<double>(uint64_t x) { return Bitcast<double>(x); }
template <>
v128 FromRep<v128>(v128 x) { return Bitcast<v128>(x); }

template <typename T>
struct FloatTraits;
Expand Down Expand Up @@ -1358,6 +1360,24 @@ ValueTypeRep<T> SimdSplat(V lane_data) {
return ToRep(Bitcast<T>(simd_data));
}

// Simd instructions with Lane operand.
// a0: input v128 value. a1: lane index.
// typename T: lane data type.
template <typename R, typename V0, typename V1, typename T>
ValueTypeRep<R> SimdExtractLane(V0 a0, V1 a1) {
// Calculate how many Lanes according to input lane data type.
constexpr int32_t lanes = sizeof(V0)/sizeof(T);

// Define SIMD data array for Simd add by Lanes.
T simd_data_0[lanes];

// Convert intput SIMD data to array.
memcpy(simd_data_0, &a0, sizeof(V0));

return ToRep(static_cast<R>(simd_data_0[a1]));
}


bool Environment::FuncSignaturesAreEqual(Index sig_index_0,
Index sig_index_1) const {
if (sig_index_0 == sig_index_1) {
Expand Down Expand Up @@ -2414,6 +2434,13 @@ Result Thread::Run(int num_instructions) {
break;
}

case Opcode::I8X16ExtractLaneS: {
v128 dLane = static_cast<v128>(Pop<v128>());
uint8_t lane_idx = ReadU8(&pc);
CHECK_TRAP(PushRep<int32_t>(SimdExtractLane<int32_t, v128, uint8_t, int8_t>(dLane, lane_idx)));
break;
}

case Opcode::I8X16Add:
CHECK_TRAP(SimdBinop<v128, uint8_t>(Add<uint32_t>));
break;
Expand Down Expand Up @@ -3475,6 +3502,12 @@ void Thread::Trace(Stream* stream) {
Pick(1).v128_bits.v[3]);
break;

case Opcode::I8X16ExtractLaneS: {
stream->Writef("%s : LaneIdx %d From $0x%08x 0x%08x 0x%08x 0x%08x \n", opcode.GetName(), ReadU8At(pc),\
Top().v128_bits.v[0], Top().v128_bits.v[1], Top().v128_bits.v[2], Top().v128_bits.v[3]);
break;
}

case Opcode::I8X16Add:
case Opcode::I16X8Add:
case Opcode::I32X4Add:
Expand Down Expand Up @@ -4063,6 +4096,11 @@ void Environment::Disassemble(Stream* stream,
stream->Writef("%s %%[-1]\n", opcode.GetName());
break;

case Opcode::I8X16ExtractLaneS: {
stream->Writef("%s (Lane idx %d) \n", opcode.GetName(),ReadU8(&pc));
break;
}

case Opcode::GrowMemory: {
Index memory_index = ReadU32(&pc);
stream->Writef("%s $%" PRIindex ":%%[-1]\n", opcode.GetName(),
Expand Down
1 change: 1 addition & 0 deletions src/ir.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const char* ExprTypeName[] = {
"Select",
"SetGlobal",
"SetLocal",
"Simd1LaneImm",
"Store",
"TeeLocal",
"Ternary",
Expand Down
13 changes: 13 additions & 0 deletions src/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ enum class ExprType {
Select,
SetGlobal,
SetLocal,
Simd1LaneImm,
Store,
TeeLocal,
Ternary,
Expand Down Expand Up @@ -266,6 +267,18 @@ typedef OpcodeExpr<ExprType::Convert> ConvertExpr;
typedef OpcodeExpr<ExprType::Unary> UnaryExpr;
typedef OpcodeExpr<ExprType::Ternary> TernaryExpr;

template <ExprType TypeEnum, typename T>
class SimdLaneExpr : public ExprMixin<TypeEnum> {
public:
SimdLaneExpr(Opcode opcode, Type type, T val, const Location& loc = Location())
: ExprMixin<TypeEnum>(loc), opcode(opcode), type(type), val(val) {}

Opcode opcode;
Type type;
T val;
};
typedef SimdLaneExpr<ExprType::Simd1LaneImm, uint32_t> Simd1LaneImmExpr;

template <ExprType TypeEnum>
class VarExpr : public ExprMixin<TypeEnum> {
public:
Expand Down
1 change: 1 addition & 0 deletions src/opcode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ bool Opcode::IsEnabled(const Features& features) const {
case Opcode::I64X2Splat:
case Opcode::F32X4Splat:
case Opcode::F64X2Splat:
case Opcode::I8X16ExtractLaneS:
case Opcode::I8X16Add:
case Opcode::I16X8Add:
case Opcode::I32X4Add:
Expand Down
1 change: 1 addition & 0 deletions src/opcode.def
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ WABT_OPCODE(V128, I32, ___, ___, 0, 0xfd, 0x05, I32X4Splat, "i32x4.splat")
WABT_OPCODE(V128, I64, ___, ___, 0, 0xfd, 0x06, I64X2Splat, "i64x2.splat")
WABT_OPCODE(V128, F32, ___, ___, 0, 0xfd, 0x07, F32X4Splat, "f32x4.splat")
WABT_OPCODE(V128, F64, ___, ___, 0, 0xfd, 0x08, F64X2Splat, "f64x2.splat")
WABT_OPCODE(I32, V128, ___, ___, 0, 0xfd, 0x09, I8X16ExtractLaneS, "i8x16.extract_lane_s")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x18, I8X16Add, "i8x16.add")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x19, I16X8Add, "i16x8.add")
WABT_OPCODE(V128, V128, V128, ___, 0, 0xfd, 0x1a, I32X4Add, "i32x4.add")
Expand Down
Loading

0 comments on commit 4f81159

Please sign in to comment.