| /* |
| * Copyright 2018 WebAssembly Community Group participants |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "src/interp/interp.h" |
| |
| #include <cinttypes> |
| |
| #include "src/interp/interp-internal.h" |
| |
| namespace wabt { |
| namespace interp { |
| |
| void Thread::Trace(Stream* stream) { |
| const uint8_t* istream = GetIstream(); |
| const uint8_t* pc = &istream[pc_]; |
| |
| stream->Writef("#%u. %4" PRIzd ": V:%-3u| ", call_stack_top_, pc - istream, |
| value_stack_top_); |
| |
| Opcode opcode = ReadOpcode(&pc); |
| assert(!opcode.IsInvalid()); |
| switch (opcode) { |
| case Opcode::Select: |
| case Opcode::SelectT: |
| // TODO(binji): We don't know the type here so we can't display the value |
| // to the user. This used to display the full 64-bit value, but that |
| // will potentially display garbage if the value is 32-bit. |
| stream->Writef("%s %u, %%[-2], %%[-1]\n", opcode.GetName(), Pick(3).i32); |
| break; |
| |
| case Opcode::Br: |
| stream->Writef("%s @%u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| case Opcode::BrIf: |
| stream->Writef("%s @%u, %u\n", opcode.GetName(), ReadU32At(pc), |
| Top().i32); |
| break; |
| |
| case Opcode::BrTable: { |
| const Index num_targets = ReadU32At(pc); |
| const IstreamOffset table_offset = ReadU32At(pc + 4); |
| const uint32_t key = Top().i32; |
| stream->Writef("%s %u, $#%" PRIindex ", table:$%u\n", opcode.GetName(), |
| key, num_targets, table_offset); |
| break; |
| } |
| |
| case Opcode::Nop: |
| case Opcode::Return: |
| case Opcode::Unreachable: |
| case Opcode::Drop: |
| stream->Writef("%s\n", opcode.GetName()); |
| break; |
| |
| case Opcode::MemorySize: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex "\n", opcode.GetName(), memory_index); |
| break; |
| } |
| |
| case Opcode::I32Const: |
| stream->Writef("%s %u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| case Opcode::I64Const: |
| stream->Writef("%s %" PRIu64 "\n", opcode.GetName(), ReadU64At(pc)); |
| break; |
| |
| case Opcode::F32Const: |
| stream->Writef("%s %g\n", opcode.GetName(), |
| Bitcast<float>(ReadU32At(pc))); |
| break; |
| |
| case Opcode::F64Const: |
| stream->Writef("%s %g\n", opcode.GetName(), |
| Bitcast<double>(ReadU64At(pc))); |
| break; |
| |
| case Opcode::LocalGet: |
| case Opcode::GlobalGet: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| case Opcode::LocalSet: |
| case Opcode::GlobalSet: |
| case Opcode::LocalTee: |
| stream->Writef("%s $%u, %u\n", opcode.GetName(), ReadU32At(pc), |
| Top().i32); |
| break; |
| |
| case Opcode::Call: |
| case Opcode::ReturnCall: |
| stream->Writef("%s @%u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| case Opcode::CallIndirect: |
| case Opcode::ReturnCallIndirect: |
| stream->Writef("%s $%u, %u\n", opcode.GetName(), ReadU32At(pc), |
| Top().i32); |
| break; |
| |
| case Opcode::InterpCallHost: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| case Opcode::I32AtomicLoad8U: |
| case Opcode::I32AtomicLoad16U: |
| case Opcode::I32AtomicLoad: |
| case Opcode::I64AtomicLoad8U: |
| case Opcode::I64AtomicLoad16U: |
| case Opcode::I64AtomicLoad32U: |
| case Opcode::I64AtomicLoad: |
| case Opcode::I32Load8S: |
| case Opcode::I32Load8U: |
| case Opcode::I32Load16S: |
| case Opcode::I32Load16U: |
| case Opcode::I64Load8S: |
| case Opcode::I64Load8U: |
| case Opcode::I64Load16S: |
| case Opcode::I64Load16U: |
| case Opcode::I64Load32S: |
| case Opcode::I64Load32U: |
| case Opcode::I32Load: |
| case Opcode::I64Load: |
| case Opcode::F32Load: |
| case Opcode::F64Load: |
| case Opcode::V128Load: |
| case Opcode::I8X16LoadSplat: |
| case Opcode::I16X8LoadSplat: |
| case Opcode::I32X4LoadSplat: |
| case Opcode::I64X2LoadSplat: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u\n", opcode.GetName(), |
| memory_index, Top().i32, ReadU32At(pc)); |
| break; |
| } |
| |
| case Opcode::AtomicNotify: |
| case Opcode::I32AtomicStore: |
| case Opcode::I32AtomicStore8: |
| case Opcode::I32AtomicStore16: |
| case Opcode::I32AtomicRmw8AddU: |
| case Opcode::I32AtomicRmw16AddU: |
| case Opcode::I32AtomicRmwAdd: |
| case Opcode::I32AtomicRmw8SubU: |
| case Opcode::I32AtomicRmw16SubU: |
| case Opcode::I32AtomicRmwSub: |
| case Opcode::I32AtomicRmw8AndU: |
| case Opcode::I32AtomicRmw16AndU: |
| case Opcode::I32AtomicRmwAnd: |
| case Opcode::I32AtomicRmw8OrU: |
| case Opcode::I32AtomicRmw16OrU: |
| case Opcode::I32AtomicRmwOr: |
| case Opcode::I32AtomicRmw8XorU: |
| case Opcode::I32AtomicRmw16XorU: |
| case Opcode::I32AtomicRmwXor: |
| case Opcode::I32AtomicRmw8XchgU: |
| case Opcode::I32AtomicRmw16XchgU: |
| case Opcode::I32AtomicRmwXchg: |
| case Opcode::I32Store8: |
| case Opcode::I32Store16: |
| case Opcode::I32Store: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, %u\n", opcode.GetName(), |
| memory_index, Pick(2).i32, ReadU32At(pc), Pick(1).i32); |
| break; |
| } |
| |
| case Opcode::I32AtomicRmwCmpxchg: |
| case Opcode::I32AtomicRmw8CmpxchgU: |
| case Opcode::I32AtomicRmw16CmpxchgU: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, %u, %u\n", opcode.GetName(), |
| memory_index, Pick(3).i32, ReadU32At(pc), Pick(2).i32, |
| Pick(1).i32); |
| break; |
| } |
| |
| case Opcode::I64AtomicStore8: |
| case Opcode::I64AtomicStore16: |
| case Opcode::I64AtomicStore32: |
| case Opcode::I64AtomicStore: |
| case Opcode::I64AtomicRmw8AddU: |
| case Opcode::I64AtomicRmw16AddU: |
| case Opcode::I64AtomicRmw32AddU: |
| case Opcode::I64AtomicRmwAdd: |
| case Opcode::I64AtomicRmw8SubU: |
| case Opcode::I64AtomicRmw16SubU: |
| case Opcode::I64AtomicRmw32SubU: |
| case Opcode::I64AtomicRmwSub: |
| case Opcode::I64AtomicRmw8AndU: |
| case Opcode::I64AtomicRmw16AndU: |
| case Opcode::I64AtomicRmw32AndU: |
| case Opcode::I64AtomicRmwAnd: |
| case Opcode::I64AtomicRmw8OrU: |
| case Opcode::I64AtomicRmw16OrU: |
| case Opcode::I64AtomicRmw32OrU: |
| case Opcode::I64AtomicRmwOr: |
| case Opcode::I64AtomicRmw8XorU: |
| case Opcode::I64AtomicRmw16XorU: |
| case Opcode::I64AtomicRmw32XorU: |
| case Opcode::I64AtomicRmwXor: |
| case Opcode::I64AtomicRmw8XchgU: |
| case Opcode::I64AtomicRmw16XchgU: |
| case Opcode::I64AtomicRmw32XchgU: |
| case Opcode::I64AtomicRmwXchg: |
| case Opcode::I64Store8: |
| case Opcode::I64Store16: |
| case Opcode::I64Store32: |
| case Opcode::I64Store: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, %" PRIu64 "\n", |
| opcode.GetName(), memory_index, Pick(2).i32, ReadU32At(pc), |
| Pick(1).i64); |
| break; |
| } |
| |
| case Opcode::I32AtomicWait: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, %u, %" PRIu64 "\n", |
| opcode.GetName(), memory_index, Pick(3).i32, ReadU32At(pc), |
| Pick(2).i32, Pick(1).i64); |
| break; |
| } |
| |
| case Opcode::I64AtomicWait: |
| case Opcode::I64AtomicRmwCmpxchg: |
| case Opcode::I64AtomicRmw8CmpxchgU: |
| case Opcode::I64AtomicRmw16CmpxchgU: |
| case Opcode::I64AtomicRmw32CmpxchgU: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, %" PRIu64 ", %" PRIu64 "\n", |
| opcode.GetName(), memory_index, Pick(3).i32, ReadU32At(pc), |
| Pick(2).i64, Pick(1).i64); |
| break; |
| } |
| |
| case Opcode::F32Store: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, %g\n", opcode.GetName(), |
| memory_index, Pick(2).i32, ReadU32At(pc), |
| Bitcast<float>(Pick(1).f32_bits)); |
| break; |
| } |
| |
| case Opcode::F64Store: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, %g\n", opcode.GetName(), |
| memory_index, Pick(2).i32, ReadU32At(pc), |
| Bitcast<double>(Pick(1).f64_bits)); |
| break; |
| } |
| |
| case Opcode::V128Store: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u+$%u, $0x%08x 0x%08x 0x%08x 0x%08x\n", |
| opcode.GetName(), memory_index, Pick(2).i32, ReadU32At(pc), |
| Pick(1).vec128.v[0], Pick(1).vec128.v[1], |
| Pick(1).vec128.v[2], Pick(1).vec128.v[3]); |
| break; |
| } |
| |
| case Opcode::MemoryGrow: { |
| const Index memory_index = ReadU32(&pc); |
| stream->Writef("%s $%" PRIindex ":%u\n", opcode.GetName(), memory_index, |
| Top().i32); |
| break; |
| } |
| |
| case Opcode::I32Add: |
| case Opcode::I32Sub: |
| case Opcode::I32Mul: |
| case Opcode::I32DivS: |
| case Opcode::I32DivU: |
| case Opcode::I32RemS: |
| case Opcode::I32RemU: |
| case Opcode::I32And: |
| case Opcode::I32Or: |
| case Opcode::I32Xor: |
| case Opcode::I32Shl: |
| case Opcode::I32ShrU: |
| case Opcode::I32ShrS: |
| case Opcode::I32Eq: |
| case Opcode::I32Ne: |
| case Opcode::I32LtS: |
| case Opcode::I32LeS: |
| case Opcode::I32LtU: |
| case Opcode::I32LeU: |
| case Opcode::I32GtS: |
| case Opcode::I32GeS: |
| case Opcode::I32GtU: |
| case Opcode::I32GeU: |
| case Opcode::I32Rotr: |
| case Opcode::I32Rotl: |
| stream->Writef("%s %u, %u\n", opcode.GetName(), Pick(2).i32, Pick(1).i32); |
| break; |
| |
| case Opcode::I32Clz: |
| case Opcode::I32Ctz: |
| case Opcode::I32Popcnt: |
| case Opcode::I32Eqz: |
| case Opcode::I32Extend16S: |
| case Opcode::I32Extend8S: |
| case Opcode::I8X16Splat: |
| case Opcode::I16X8Splat: |
| case Opcode::I32X4Splat: |
| stream->Writef("%s %u\n", opcode.GetName(), Top().i32); |
| break; |
| |
| case Opcode::I64Add: |
| case Opcode::I64Sub: |
| case Opcode::I64Mul: |
| case Opcode::I64DivS: |
| case Opcode::I64DivU: |
| case Opcode::I64RemS: |
| case Opcode::I64RemU: |
| case Opcode::I64And: |
| case Opcode::I64Or: |
| case Opcode::I64Xor: |
| case Opcode::I64Shl: |
| case Opcode::I64ShrU: |
| case Opcode::I64ShrS: |
| case Opcode::I64Eq: |
| case Opcode::I64Ne: |
| case Opcode::I64LtS: |
| case Opcode::I64LeS: |
| case Opcode::I64LtU: |
| case Opcode::I64LeU: |
| case Opcode::I64GtS: |
| case Opcode::I64GeS: |
| case Opcode::I64GtU: |
| case Opcode::I64GeU: |
| case Opcode::I64Rotr: |
| case Opcode::I64Rotl: |
| stream->Writef("%s %" PRIu64 ", %" PRIu64 "\n", opcode.GetName(), |
| Pick(2).i64, Pick(1).i64); |
| break; |
| |
| case Opcode::I64Clz: |
| case Opcode::I64Ctz: |
| case Opcode::I64Popcnt: |
| case Opcode::I64Eqz: |
| case Opcode::I64Extend16S: |
| case Opcode::I64Extend32S: |
| case Opcode::I64Extend8S: |
| case Opcode::I64X2Splat: |
| stream->Writef("%s %" PRIu64 "\n", opcode.GetName(), Top().i64); |
| break; |
| |
| case Opcode::F32Add: |
| case Opcode::F32Sub: |
| case Opcode::F32Mul: |
| case Opcode::F32Div: |
| case Opcode::F32Min: |
| case Opcode::F32Max: |
| case Opcode::F32Copysign: |
| case Opcode::F32Eq: |
| case Opcode::F32Ne: |
| case Opcode::F32Lt: |
| case Opcode::F32Le: |
| case Opcode::F32Gt: |
| case Opcode::F32Ge: |
| stream->Writef("%s %g, %g\n", opcode.GetName(), |
| Bitcast<float>(Pick(2).i32), Bitcast<float>(Pick(1).i32)); |
| break; |
| |
| case Opcode::F32Abs: |
| case Opcode::F32Neg: |
| case Opcode::F32Ceil: |
| case Opcode::F32Floor: |
| case Opcode::F32Trunc: |
| case Opcode::F32Nearest: |
| case Opcode::F32Sqrt: |
| case Opcode::F32X4Splat: |
| stream->Writef("%s %g\n", opcode.GetName(), Bitcast<float>(Top().i32)); |
| break; |
| |
| case Opcode::F64Add: |
| case Opcode::F64Sub: |
| case Opcode::F64Mul: |
| case Opcode::F64Div: |
| case Opcode::F64Min: |
| case Opcode::F64Max: |
| case Opcode::F64Copysign: |
| case Opcode::F64Eq: |
| case Opcode::F64Ne: |
| case Opcode::F64Lt: |
| case Opcode::F64Le: |
| case Opcode::F64Gt: |
| case Opcode::F64Ge: |
| stream->Writef("%s %g, %g\n", opcode.GetName(), |
| Bitcast<double>(Pick(2).i64), |
| Bitcast<double>(Pick(1).i64)); |
| break; |
| |
| case Opcode::F64Abs: |
| case Opcode::F64Neg: |
| case Opcode::F64Ceil: |
| case Opcode::F64Floor: |
| case Opcode::F64Trunc: |
| case Opcode::F64Nearest: |
| case Opcode::F64Sqrt: |
| case Opcode::F64X2Splat: |
| stream->Writef("%s %g\n", opcode.GetName(), Bitcast<double>(Top().i64)); |
| break; |
| |
| case Opcode::I32TruncF32S: |
| case Opcode::I32TruncF32U: |
| case Opcode::I64TruncF32S: |
| case Opcode::I64TruncF32U: |
| case Opcode::F64PromoteF32: |
| case Opcode::I32ReinterpretF32: |
| case Opcode::I32TruncSatF32S: |
| case Opcode::I32TruncSatF32U: |
| case Opcode::I64TruncSatF32S: |
| case Opcode::I64TruncSatF32U: |
| stream->Writef("%s %g\n", opcode.GetName(), Bitcast<float>(Top().i32)); |
| break; |
| |
| case Opcode::I32TruncF64S: |
| case Opcode::I32TruncF64U: |
| case Opcode::I64TruncF64S: |
| case Opcode::I64TruncF64U: |
| case Opcode::F32DemoteF64: |
| case Opcode::I64ReinterpretF64: |
| case Opcode::I32TruncSatF64S: |
| case Opcode::I32TruncSatF64U: |
| case Opcode::I64TruncSatF64S: |
| case Opcode::I64TruncSatF64U: |
| stream->Writef("%s %g\n", opcode.GetName(), Bitcast<double>(Top().i64)); |
| break; |
| |
| case Opcode::I32WrapI64: |
| case Opcode::F32ConvertI64S: |
| case Opcode::F32ConvertI64U: |
| case Opcode::F64ConvertI64S: |
| case Opcode::F64ConvertI64U: |
| case Opcode::F64ReinterpretI64: |
| stream->Writef("%s %" PRIu64 "\n", opcode.GetName(), Top().i64); |
| break; |
| |
| case Opcode::I64ExtendI32S: |
| case Opcode::I64ExtendI32U: |
| case Opcode::F32ConvertI32S: |
| case Opcode::F32ConvertI32U: |
| case Opcode::F32ReinterpretI32: |
| case Opcode::F64ConvertI32S: |
| case Opcode::F64ConvertI32U: |
| stream->Writef("%s %u\n", opcode.GetName(), Top().i32); |
| break; |
| |
| case Opcode::InterpAlloca: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| case Opcode::InterpBrUnless: |
| stream->Writef("%s @%u, %u\n", opcode.GetName(), ReadU32At(pc), |
| Top().i32); |
| break; |
| |
| case Opcode::InterpDropKeep: |
| stream->Writef("%s $%u $%u\n", opcode.GetName(), ReadU32At(pc), |
| ReadU32At(pc + 4)); |
| break; |
| |
| case Opcode::V128Const: { |
| stream->Writef("%s i32x4 0x%08x 0x%08x 0x%08x 0x%08x\n", opcode.GetName(), |
| ReadU32At(pc), ReadU32At(pc + 4), ReadU32At(pc + 8), |
| ReadU32At(pc + 12)); |
| break; |
| } |
| |
| case Opcode::I8X16Neg: |
| case Opcode::I16X8Neg: |
| case Opcode::I32X4Neg: |
| case Opcode::I64X2Neg: |
| case Opcode::V128Not: |
| case Opcode::I8X16AnyTrue: |
| case Opcode::I16X8AnyTrue: |
| case Opcode::I32X4AnyTrue: |
| case Opcode::I64X2AnyTrue: |
| case Opcode::I8X16AllTrue: |
| case Opcode::I16X8AllTrue: |
| case Opcode::I32X4AllTrue: |
| case Opcode::I64X2AllTrue: |
| case Opcode::F32X4Neg: |
| case Opcode::F64X2Neg: |
| case Opcode::F32X4Abs: |
| case Opcode::F64X2Abs: |
| case Opcode::F32X4Sqrt: |
| case Opcode::F64X2Sqrt: |
| case Opcode::F32X4ConvertI32X4S: |
| case Opcode::F32X4ConvertI32X4U: |
| case Opcode::F64X2ConvertI64X2S: |
| case Opcode::F64X2ConvertI64X2U: |
| case Opcode::I32X4TruncSatF32X4S: |
| case Opcode::I32X4TruncSatF32X4U: |
| case Opcode::I64X2TruncSatF64X2S: |
| case Opcode::I64X2TruncSatF64X2U: { |
| stream->Writef("%s $0x%08x 0x%08x 0x%08x 0x%08x\n", opcode.GetName(), |
| Top().vec128.v[0], Top().vec128.v[1], |
| Top().vec128.v[2], Top().vec128.v[3]); |
| break; |
| } |
| |
| case Opcode::V128BitSelect: |
| stream->Writef( |
| "%s $0x%08x %08x %08x %08x $0x%08x %08x %08x %08x $0x%08x %08x %08x " |
| "%08x\n", |
| opcode.GetName(), Pick(3).vec128.v[0], Pick(3).vec128.v[1], |
| Pick(3).vec128.v[2], Pick(3).vec128.v[3], |
| Pick(2).vec128.v[0], Pick(2).vec128.v[1], |
| Pick(2).vec128.v[2], Pick(2).vec128.v[3], |
| Pick(1).vec128.v[0], Pick(1).vec128.v[1], |
| Pick(1).vec128.v[2], Pick(1).vec128.v[3]); |
| break; |
| |
| case Opcode::I8X16ExtractLaneS: |
| case Opcode::I8X16ExtractLaneU: |
| case Opcode::I16X8ExtractLaneS: |
| case Opcode::I16X8ExtractLaneU: |
| case Opcode::I32X4ExtractLane: |
| case Opcode::I64X2ExtractLane: |
| case Opcode::F32X4ExtractLane: |
| case Opcode::F64X2ExtractLane: { |
| stream->Writef("%s : LaneIdx %d From $0x%08x 0x%08x 0x%08x 0x%08x\n", |
| opcode.GetName(), ReadU8At(pc), Top().vec128.v[0], |
| Top().vec128.v[1], Top().vec128.v[2], |
| Top().vec128.v[3]); |
| break; |
| } |
| |
| case Opcode::I8X16ReplaceLane: |
| case Opcode::I16X8ReplaceLane: |
| case Opcode::I32X4ReplaceLane: { |
| stream->Writef( |
| "%s : Set %u to LaneIdx %d In $0x%08x 0x%08x 0x%08x 0x%08x\n", |
| opcode.GetName(), Pick(1).i32, ReadU8At(pc), Pick(2).vec128.v[0], |
| Pick(2).vec128.v[1], Pick(2).vec128.v[2], |
| Pick(2).vec128.v[3]); |
| break; |
| } |
| case Opcode::I64X2ReplaceLane: { |
| stream->Writef("%s : Set %" PRIu64 |
| " to LaneIdx %d In $0x%08x 0x%08x 0x%08x 0x%08x\n", |
| opcode.GetName(), Pick(1).i64, ReadU8At(pc), |
| Pick(2).vec128.v[0], Pick(2).vec128.v[1], |
| Pick(2).vec128.v[2], Pick(2).vec128.v[3]); |
| break; |
| } |
| case Opcode::F32X4ReplaceLane: { |
| stream->Writef( |
| "%s : Set %g to LaneIdx %d In $0x%08x 0x%08x 0x%08x 0x%08x\n", |
| opcode.GetName(), Bitcast<float>(Pick(1).f32_bits), ReadU8At(pc), |
| Pick(2).vec128.v[0], Pick(2).vec128.v[1], |
| Pick(2).vec128.v[2], Pick(2).vec128.v[3]); |
| |
| break; |
| } |
| case Opcode::F64X2ReplaceLane: { |
| stream->Writef( |
| "%s : Set %g to LaneIdx %d In $0x%08x 0x%08x 0x%08x 0x%08x\n", |
| opcode.GetName(), Bitcast<double>(Pick(1).f64_bits), ReadU8At(pc), |
| Pick(2).vec128.v[0], Pick(2).vec128.v[1], |
| Pick(2).vec128.v[2], Pick(2).vec128.v[3]); |
| break; |
| } |
| |
| case Opcode::V8X16Shuffle: |
| stream->Writef( |
| "%s $0x%08x %08x %08x %08x $0x%08x %08x %08x %08x : with lane imm: " |
| "$0x%08x %08x %08x %08x\n", |
| opcode.GetName(), Pick(2).vec128.v[0], Pick(2).vec128.v[1], |
| Pick(2).vec128.v[2], Pick(2).vec128.v[3], |
| Pick(1).vec128.v[0], Pick(1).vec128.v[1], |
| Pick(1).vec128.v[2], Pick(1).vec128.v[3], ReadU32At(pc), |
| ReadU32At(pc + 4), ReadU32At(pc + 8), ReadU32At(pc + 12)); |
| break; |
| |
| case Opcode::I8X16Add: |
| case Opcode::I16X8Add: |
| case Opcode::I32X4Add: |
| case Opcode::I64X2Add: |
| case Opcode::I8X16Sub: |
| case Opcode::I16X8Sub: |
| case Opcode::I32X4Sub: |
| case Opcode::I64X2Sub: |
| case Opcode::I8X16Mul: |
| case Opcode::I16X8Mul: |
| case Opcode::I32X4Mul: |
| case Opcode::I8X16AddSaturateS: |
| case Opcode::I8X16AddSaturateU: |
| case Opcode::I16X8AddSaturateS: |
| case Opcode::I16X8AddSaturateU: |
| case Opcode::I8X16SubSaturateS: |
| case Opcode::I8X16SubSaturateU: |
| case Opcode::I16X8SubSaturateS: |
| case Opcode::I16X8SubSaturateU: |
| case Opcode::V128And: |
| case Opcode::V128Or: |
| case Opcode::V128Xor: |
| case Opcode::I8X16Eq: |
| case Opcode::I16X8Eq: |
| case Opcode::I32X4Eq: |
| case Opcode::F32X4Eq: |
| case Opcode::F64X2Eq: |
| case Opcode::I8X16Ne: |
| case Opcode::I16X8Ne: |
| case Opcode::I32X4Ne: |
| case Opcode::F32X4Ne: |
| case Opcode::F64X2Ne: |
| case Opcode::I8X16LtS: |
| case Opcode::I8X16LtU: |
| case Opcode::I16X8LtS: |
| case Opcode::I16X8LtU: |
| case Opcode::I32X4LtS: |
| case Opcode::I32X4LtU: |
| case Opcode::F32X4Lt: |
| case Opcode::F64X2Lt: |
| case Opcode::I8X16LeS: |
| case Opcode::I8X16LeU: |
| case Opcode::I16X8LeS: |
| case Opcode::I16X8LeU: |
| case Opcode::I32X4LeS: |
| case Opcode::I32X4LeU: |
| case Opcode::F32X4Le: |
| case Opcode::F64X2Le: |
| case Opcode::I8X16GtS: |
| case Opcode::I8X16GtU: |
| case Opcode::I16X8GtS: |
| case Opcode::I16X8GtU: |
| case Opcode::I32X4GtS: |
| case Opcode::I32X4GtU: |
| case Opcode::F32X4Gt: |
| case Opcode::F64X2Gt: |
| case Opcode::I8X16GeS: |
| case Opcode::I8X16GeU: |
| case Opcode::I16X8GeS: |
| case Opcode::I16X8GeU: |
| case Opcode::I32X4GeS: |
| case Opcode::I32X4GeU: |
| case Opcode::F32X4Ge: |
| case Opcode::F64X2Ge: |
| case Opcode::F32X4Min: |
| case Opcode::F64X2Min: |
| case Opcode::F32X4Max: |
| case Opcode::F64X2Max: |
| case Opcode::F32X4Add: |
| case Opcode::F64X2Add: |
| case Opcode::F32X4Sub: |
| case Opcode::F64X2Sub: |
| case Opcode::F32X4Div: |
| case Opcode::F64X2Div: |
| case Opcode::F32X4Mul: |
| case Opcode::F64X2Mul: |
| case Opcode::V8X16Swizzle: { |
| stream->Writef("%s $0x%08x %08x %08x %08x $0x%08x %08x %08x %08x\n", |
| opcode.GetName(), Pick(2).vec128.v[0], |
| Pick(2).vec128.v[1], Pick(2).vec128.v[2], |
| Pick(2).vec128.v[3], Pick(1).vec128.v[0], |
| Pick(1).vec128.v[1], Pick(1).vec128.v[2], |
| Pick(1).vec128.v[3]); |
| break; |
| } |
| |
| case Opcode::I8X16Shl: |
| case Opcode::I16X8Shl: |
| case Opcode::I32X4Shl: |
| case Opcode::I64X2Shl: |
| case Opcode::I8X16ShrS: |
| case Opcode::I8X16ShrU: |
| case Opcode::I16X8ShrS: |
| case Opcode::I16X8ShrU: |
| case Opcode::I32X4ShrS: |
| case Opcode::I32X4ShrU: |
| case Opcode::I64X2ShrS: |
| case Opcode::I64X2ShrU: { |
| stream->Writef("%s $0x%08x %08x %08x %08x $0x%08x\n", opcode.GetName(), |
| Pick(2).vec128.v[0], Pick(2).vec128.v[1], |
| Pick(2).vec128.v[2], Pick(2).vec128.v[3], |
| Pick(1).i32); |
| break; |
| } |
| |
| case Opcode::RefNull: |
| stream->Writef("%s\n", opcode.GetName()); |
| break; |
| |
| case Opcode::RefIsNull: |
| stream->Writef("%s %s:%08x\n", opcode.GetName(), |
| RefTypeToString(Pick(1).ref.kind).c_str(), |
| Pick(1).ref.index); |
| break; |
| |
| case Opcode::RefFunc: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| case Opcode::MemoryInit: |
| case Opcode::TableInit: { |
| Index index = ReadU32At(pc); |
| Index segment_index = ReadU32At(pc + 4); |
| stream->Writef("%s $%" PRIindex ", $%" PRIindex "\n", opcode.GetName(), |
| index, segment_index); |
| break; |
| } |
| |
| case Opcode::TableGet: |
| case Opcode::TableSet: |
| case Opcode::TableSize: |
| case Opcode::TableFill: |
| case Opcode::TableGrow: |
| case Opcode::DataDrop: |
| case Opcode::ElemDrop: |
| case Opcode::MemoryCopy: |
| case Opcode::TableCopy: |
| case Opcode::MemoryFill: |
| stream->Writef("%s $%u\n", opcode.GetName(), ReadU32At(pc)); |
| break; |
| |
| // The following opcodes are either never generated or should never be |
| // executed. |
| case Opcode::Block: |
| case Opcode::BrOnExn: |
| case Opcode::Catch: |
| case Opcode::Else: |
| case Opcode::End: |
| case Opcode::If: |
| case Opcode::InterpData: |
| case Opcode::Invalid: |
| case Opcode::Loop: |
| case Opcode::Rethrow: |
| case Opcode::Throw: |
| case Opcode::Try: |
| WABT_UNREACHABLE; |
| break; |
| } |
| } |
| |
| } // namespace interp |
| } // namespace wabt |