1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/interpreter/bytecode-decoder.h"
6
7 #include <iomanip>
8
9 #include "src/utils.h"
10
11 namespace v8 {
12 namespace internal {
13 namespace interpreter {
14
15 // static
DecodeRegisterOperand(const uint8_t * operand_start,OperandType operand_type,OperandScale operand_scale)16 Register BytecodeDecoder::DecodeRegisterOperand(const uint8_t* operand_start,
17 OperandType operand_type,
18 OperandScale operand_scale) {
19 DCHECK(Bytecodes::IsRegisterOperandType(operand_type));
20 int32_t operand =
21 DecodeSignedOperand(operand_start, operand_type, operand_scale);
22 return Register::FromOperand(operand);
23 }
24
25 // static
DecodeRegisterListOperand(const uint8_t * operand_start,uint32_t count,OperandType operand_type,OperandScale operand_scale)26 RegisterList BytecodeDecoder::DecodeRegisterListOperand(
27 const uint8_t* operand_start, uint32_t count, OperandType operand_type,
28 OperandScale operand_scale) {
29 Register first_reg =
30 DecodeRegisterOperand(operand_start, operand_type, operand_scale);
31 return RegisterList(first_reg.index(), static_cast<int>(count));
32 }
33
34 // static
DecodeSignedOperand(const uint8_t * operand_start,OperandType operand_type,OperandScale operand_scale)35 int32_t BytecodeDecoder::DecodeSignedOperand(const uint8_t* operand_start,
36 OperandType operand_type,
37 OperandScale operand_scale) {
38 DCHECK(!Bytecodes::IsUnsignedOperandType(operand_type));
39 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
40 case OperandSize::kByte:
41 return static_cast<int8_t>(*operand_start);
42 case OperandSize::kShort:
43 return static_cast<int16_t>(ReadUnalignedUInt16(operand_start));
44 case OperandSize::kQuad:
45 return static_cast<int32_t>(ReadUnalignedUInt32(operand_start));
46 case OperandSize::kNone:
47 UNREACHABLE();
48 }
49 return 0;
50 }
51
52 // static
DecodeUnsignedOperand(const uint8_t * operand_start,OperandType operand_type,OperandScale operand_scale)53 uint32_t BytecodeDecoder::DecodeUnsignedOperand(const uint8_t* operand_start,
54 OperandType operand_type,
55 OperandScale operand_scale) {
56 DCHECK(Bytecodes::IsUnsignedOperandType(operand_type));
57 switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) {
58 case OperandSize::kByte:
59 return *operand_start;
60 case OperandSize::kShort:
61 return ReadUnalignedUInt16(operand_start);
62 case OperandSize::kQuad:
63 return ReadUnalignedUInt32(operand_start);
64 case OperandSize::kNone:
65 UNREACHABLE();
66 }
67 return 0;
68 }
69
70 // static
Decode(std::ostream & os,const uint8_t * bytecode_start,int parameter_count)71 std::ostream& BytecodeDecoder::Decode(std::ostream& os,
72 const uint8_t* bytecode_start,
73 int parameter_count) {
74 Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]);
75 int prefix_offset = 0;
76 OperandScale operand_scale = OperandScale::kSingle;
77 if (Bytecodes::IsPrefixScalingBytecode(bytecode)) {
78 prefix_offset = 1;
79 operand_scale = Bytecodes::PrefixBytecodeToOperandScale(bytecode);
80 bytecode = Bytecodes::FromByte(bytecode_start[1]);
81 }
82
83 // Prepare to print bytecode and operands as hex digits.
84 std::ios saved_format(nullptr);
85 saved_format.copyfmt(saved_format);
86 os.fill('0');
87 os.flags(std::ios::hex);
88
89 int bytecode_size = Bytecodes::Size(bytecode, operand_scale);
90 for (int i = 0; i < prefix_offset + bytecode_size; i++) {
91 os << std::setw(2) << static_cast<uint32_t>(bytecode_start[i]) << ' ';
92 }
93 os.copyfmt(saved_format);
94
95 const int kBytecodeColumnSize = 6;
96 for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) {
97 os << " ";
98 }
99
100 os << Bytecodes::ToString(bytecode, operand_scale) << " ";
101
102 // Operands for the debug break are from the original instruction.
103 if (Bytecodes::IsDebugBreak(bytecode)) return os;
104
105 int number_of_operands = Bytecodes::NumberOfOperands(bytecode);
106 for (int i = 0; i < number_of_operands; i++) {
107 OperandType op_type = Bytecodes::GetOperandType(bytecode, i);
108 int operand_offset =
109 Bytecodes::GetOperandOffset(bytecode, i, operand_scale);
110 const uint8_t* operand_start =
111 &bytecode_start[prefix_offset + operand_offset];
112 switch (op_type) {
113 case interpreter::OperandType::kIdx:
114 case interpreter::OperandType::kUImm:
115 case interpreter::OperandType::kRuntimeId:
116 case interpreter::OperandType::kIntrinsicId:
117 os << "["
118 << DecodeUnsignedOperand(operand_start, op_type, operand_scale)
119 << "]";
120 break;
121 case interpreter::OperandType::kImm:
122 os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale)
123 << "]";
124 break;
125 case interpreter::OperandType::kFlag8:
126 os << "#"
127 << DecodeUnsignedOperand(operand_start, op_type, operand_scale);
128 break;
129 case interpreter::OperandType::kReg:
130 case interpreter::OperandType::kRegOut: {
131 Register reg =
132 DecodeRegisterOperand(operand_start, op_type, operand_scale);
133 os << reg.ToString(parameter_count);
134 break;
135 }
136 case interpreter::OperandType::kRegOutTriple: {
137 RegisterList reg_list =
138 DecodeRegisterListOperand(operand_start, 3, op_type, operand_scale);
139 os << reg_list.first_register().ToString(parameter_count) << "-"
140 << reg_list.last_register().ToString(parameter_count);
141 break;
142 }
143 case interpreter::OperandType::kRegOutPair:
144 case interpreter::OperandType::kRegPair: {
145 RegisterList reg_list =
146 DecodeRegisterListOperand(operand_start, 2, op_type, operand_scale);
147 os << reg_list.first_register().ToString(parameter_count) << "-"
148 << reg_list.last_register().ToString(parameter_count);
149 break;
150 }
151 case interpreter::OperandType::kRegList: {
152 DCHECK_LT(i, number_of_operands - 1);
153 DCHECK_EQ(Bytecodes::GetOperandType(bytecode, i + 1),
154 OperandType::kRegCount);
155 int reg_count_offset =
156 Bytecodes::GetOperandOffset(bytecode, i + 1, operand_scale);
157 const uint8_t* reg_count_operand =
158 &bytecode_start[prefix_offset + reg_count_offset];
159 uint32_t count = DecodeUnsignedOperand(
160 reg_count_operand, OperandType::kRegCount, operand_scale);
161 RegisterList reg_list = DecodeRegisterListOperand(
162 operand_start, count, op_type, operand_scale);
163 os << reg_list.first_register().ToString(parameter_count) << "-"
164 << reg_list.last_register().ToString(parameter_count);
165 i++; // Skip kRegCount.
166 break;
167 }
168 case interpreter::OperandType::kNone:
169 case interpreter::OperandType::kRegCount: // Dealt with in kRegList.
170 UNREACHABLE();
171 break;
172 }
173 if (i != number_of_operands - 1) {
174 os << ", ";
175 }
176 }
177 return os;
178 }
179
180 } // namespace interpreter
181 } // namespace internal
182 } // namespace v8
183