1 // Copyright 2014 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 #ifndef V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
6 #define V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
7
8 #include <iosfwd>
9
10 #if V8_TARGET_ARCH_ARM
11 #include "src/compiler/backend/arm/instruction-codes-arm.h"
12 #elif V8_TARGET_ARCH_ARM64
13 #include "src/compiler/backend/arm64/instruction-codes-arm64.h"
14 #elif V8_TARGET_ARCH_IA32
15 #include "src/compiler/backend/ia32/instruction-codes-ia32.h"
16 #elif V8_TARGET_ARCH_MIPS
17 #include "src/compiler/backend/mips/instruction-codes-mips.h"
18 #elif V8_TARGET_ARCH_MIPS64
19 #include "src/compiler/backend/mips64/instruction-codes-mips64.h"
20 #elif V8_TARGET_ARCH_X64
21 #include "src/compiler/backend/x64/instruction-codes-x64.h"
22 #elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
23 #include "src/compiler/backend/ppc/instruction-codes-ppc.h"
24 #elif V8_TARGET_ARCH_S390
25 #include "src/compiler/backend/s390/instruction-codes-s390.h"
26 #else
27 #define TARGET_ARCH_OPCODE_LIST(V)
28 #define TARGET_ADDRESSING_MODE_LIST(V)
29 #endif
30 #include "src/base/bit-field.h"
31 #include "src/compiler/write-barrier-kind.h"
32
33 namespace v8 {
34 namespace internal {
35 namespace compiler {
36
37 // Modes for ArchStoreWithWriteBarrier below.
38 enum class RecordWriteMode {
39 kValueIsMap,
40 kValueIsPointer,
41 kValueIsEphemeronKey,
42 kValueIsAny,
43 };
44
WriteBarrierKindToRecordWriteMode(WriteBarrierKind write_barrier_kind)45 inline RecordWriteMode WriteBarrierKindToRecordWriteMode(
46 WriteBarrierKind write_barrier_kind) {
47 switch (write_barrier_kind) {
48 case kMapWriteBarrier:
49 return RecordWriteMode::kValueIsMap;
50 case kPointerWriteBarrier:
51 return RecordWriteMode::kValueIsPointer;
52 case kEphemeronKeyWriteBarrier:
53 return RecordWriteMode::kValueIsEphemeronKey;
54 case kFullWriteBarrier:
55 return RecordWriteMode::kValueIsAny;
56 case kNoWriteBarrier:
57 // Should not be passed as argument.
58 default:
59 break;
60 }
61 UNREACHABLE();
62 }
63
64 // Target-specific opcodes that specify which assembly sequence to emit.
65 // Most opcodes specify a single instruction.
66 #define COMMON_ARCH_OPCODE_LIST(V) \
67 /* Tail call opcodes are grouped together to make IsTailCall fast */ \
68 /* and Arch call opcodes are grouped together to make */ \
69 /* IsCallWithDescriptorFlags fast */ \
70 V(ArchTailCallCodeObjectFromJSFunction) \
71 V(ArchTailCallCodeObject) \
72 V(ArchTailCallAddress) \
73 V(ArchTailCallWasm) \
74 /* Update IsTailCall if further TailCall opcodes are added */ \
75 \
76 V(ArchCallCodeObject) \
77 V(ArchCallJSFunction) \
78 V(ArchCallWasmFunction) \
79 V(ArchCallBuiltinPointer) \
80 /* Update IsCallWithDescriptorFlags if further Call opcodes are added */ \
81 \
82 V(ArchPrepareCallCFunction) \
83 V(ArchSaveCallerRegisters) \
84 V(ArchRestoreCallerRegisters) \
85 V(ArchCallCFunction) \
86 V(ArchPrepareTailCall) \
87 V(ArchJmp) \
88 V(ArchBinarySearchSwitch) \
89 V(ArchTableSwitch) \
90 V(ArchNop) \
91 V(ArchAbortCSAAssert) \
92 V(ArchDebugBreak) \
93 V(ArchComment) \
94 V(ArchThrowTerminator) \
95 V(ArchDeoptimize) \
96 V(ArchRet) \
97 V(ArchFramePointer) \
98 V(ArchParentFramePointer) \
99 V(ArchTruncateDoubleToI) \
100 V(ArchStoreWithWriteBarrier) \
101 V(ArchStackSlot) \
102 V(ArchWordPoisonOnSpeculation) \
103 V(ArchStackPointerGreaterThan) \
104 V(ArchStackCheckOffset) \
105 V(Word32AtomicLoadInt8) \
106 V(Word32AtomicLoadUint8) \
107 V(Word32AtomicLoadInt16) \
108 V(Word32AtomicLoadUint16) \
109 V(Word32AtomicLoadWord32) \
110 V(Word32AtomicStoreWord8) \
111 V(Word32AtomicStoreWord16) \
112 V(Word32AtomicStoreWord32) \
113 V(Word32AtomicExchangeInt8) \
114 V(Word32AtomicExchangeUint8) \
115 V(Word32AtomicExchangeInt16) \
116 V(Word32AtomicExchangeUint16) \
117 V(Word32AtomicExchangeWord32) \
118 V(Word32AtomicCompareExchangeInt8) \
119 V(Word32AtomicCompareExchangeUint8) \
120 V(Word32AtomicCompareExchangeInt16) \
121 V(Word32AtomicCompareExchangeUint16) \
122 V(Word32AtomicCompareExchangeWord32) \
123 V(Word32AtomicAddInt8) \
124 V(Word32AtomicAddUint8) \
125 V(Word32AtomicAddInt16) \
126 V(Word32AtomicAddUint16) \
127 V(Word32AtomicAddWord32) \
128 V(Word32AtomicSubInt8) \
129 V(Word32AtomicSubUint8) \
130 V(Word32AtomicSubInt16) \
131 V(Word32AtomicSubUint16) \
132 V(Word32AtomicSubWord32) \
133 V(Word32AtomicAndInt8) \
134 V(Word32AtomicAndUint8) \
135 V(Word32AtomicAndInt16) \
136 V(Word32AtomicAndUint16) \
137 V(Word32AtomicAndWord32) \
138 V(Word32AtomicOrInt8) \
139 V(Word32AtomicOrUint8) \
140 V(Word32AtomicOrInt16) \
141 V(Word32AtomicOrUint16) \
142 V(Word32AtomicOrWord32) \
143 V(Word32AtomicXorInt8) \
144 V(Word32AtomicXorUint8) \
145 V(Word32AtomicXorInt16) \
146 V(Word32AtomicXorUint16) \
147 V(Word32AtomicXorWord32) \
148 V(Ieee754Float64Acos) \
149 V(Ieee754Float64Acosh) \
150 V(Ieee754Float64Asin) \
151 V(Ieee754Float64Asinh) \
152 V(Ieee754Float64Atan) \
153 V(Ieee754Float64Atanh) \
154 V(Ieee754Float64Atan2) \
155 V(Ieee754Float64Cbrt) \
156 V(Ieee754Float64Cos) \
157 V(Ieee754Float64Cosh) \
158 V(Ieee754Float64Exp) \
159 V(Ieee754Float64Expm1) \
160 V(Ieee754Float64Log) \
161 V(Ieee754Float64Log1p) \
162 V(Ieee754Float64Log10) \
163 V(Ieee754Float64Log2) \
164 V(Ieee754Float64Pow) \
165 V(Ieee754Float64Sin) \
166 V(Ieee754Float64Sinh) \
167 V(Ieee754Float64Tan) \
168 V(Ieee754Float64Tanh)
169
170 #define ARCH_OPCODE_LIST(V) \
171 COMMON_ARCH_OPCODE_LIST(V) \
172 TARGET_ARCH_OPCODE_LIST(V)
173
174 enum ArchOpcode {
175 #define DECLARE_ARCH_OPCODE(Name) k##Name,
176 ARCH_OPCODE_LIST(DECLARE_ARCH_OPCODE)
177 #undef DECLARE_ARCH_OPCODE
178 #define COUNT_ARCH_OPCODE(Name) +1
179 kLastArchOpcode = -1 ARCH_OPCODE_LIST(COUNT_ARCH_OPCODE)
180 #undef COUNT_ARCH_OPCODE
181 };
182
183 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
184 const ArchOpcode& ao);
185
186 // Addressing modes represent the "shape" of inputs to an instruction.
187 // Many instructions support multiple addressing modes. Addressing modes
188 // are encoded into the InstructionCode of the instruction and tell the
189 // code generator after register allocation which assembler method to call.
190 #define ADDRESSING_MODE_LIST(V) \
191 V(None) \
192 TARGET_ADDRESSING_MODE_LIST(V)
193
194 enum AddressingMode {
195 #define DECLARE_ADDRESSING_MODE(Name) kMode_##Name,
196 ADDRESSING_MODE_LIST(DECLARE_ADDRESSING_MODE)
197 #undef DECLARE_ADDRESSING_MODE
198 #define COUNT_ADDRESSING_MODE(Name) +1
199 kLastAddressingMode = -1 ADDRESSING_MODE_LIST(COUNT_ADDRESSING_MODE)
200 #undef COUNT_ADDRESSING_MODE
201 };
202
203 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
204 const AddressingMode& am);
205
206 // The mode of the flags continuation (see below).
207 enum FlagsMode {
208 kFlags_none = 0,
209 kFlags_branch = 1,
210 kFlags_branch_and_poison = 2,
211 kFlags_deoptimize = 3,
212 kFlags_deoptimize_and_poison = 4,
213 kFlags_set = 5,
214 kFlags_trap = 6
215 };
216
217 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
218 const FlagsMode& fm);
219
220 // The condition of flags continuation (see below).
221 enum FlagsCondition {
222 kEqual,
223 kNotEqual,
224 kSignedLessThan,
225 kSignedGreaterThanOrEqual,
226 kSignedLessThanOrEqual,
227 kSignedGreaterThan,
228 kUnsignedLessThan,
229 kUnsignedGreaterThanOrEqual,
230 kUnsignedLessThanOrEqual,
231 kUnsignedGreaterThan,
232 kFloatLessThanOrUnordered,
233 kFloatGreaterThanOrEqual,
234 kFloatLessThanOrEqual,
235 kFloatGreaterThanOrUnordered,
236 kFloatLessThan,
237 kFloatGreaterThanOrEqualOrUnordered,
238 kFloatLessThanOrEqualOrUnordered,
239 kFloatGreaterThan,
240 kUnorderedEqual,
241 kUnorderedNotEqual,
242 kOverflow,
243 kNotOverflow,
244 kPositiveOrZero,
245 kNegative
246 };
247
248 static constexpr FlagsCondition kStackPointerGreaterThanCondition =
249 kUnsignedGreaterThan;
250
NegateFlagsCondition(FlagsCondition condition)251 inline FlagsCondition NegateFlagsCondition(FlagsCondition condition) {
252 return static_cast<FlagsCondition>(condition ^ 1);
253 }
254
255 FlagsCondition CommuteFlagsCondition(FlagsCondition condition);
256
257 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
258 const FlagsCondition& fc);
259
260 enum MemoryAccessMode {
261 kMemoryAccessDirect = 0,
262 kMemoryAccessProtected = 1,
263 kMemoryAccessPoisoned = 2
264 };
265
266 // The InstructionCode is an opaque, target-specific integer that encodes
267 // what code to emit for an instruction in the code generator. It is not
268 // interesting to the register allocator, as the inputs and flags on the
269 // instructions specify everything of interest.
270 using InstructionCode = uint32_t;
271
272 // Helpers for encoding / decoding InstructionCode into the fields needed
273 // for code generation. We encode the instruction, addressing mode, and flags
274 // continuation into a single InstructionCode which is stored as part of
275 // the instruction.
276 using ArchOpcodeField = base::BitField<ArchOpcode, 0, 9>;
277 static_assert(ArchOpcodeField::is_valid(kLastArchOpcode),
278 "All opcodes must fit in the 9-bit ArchOpcodeField.");
279 using AddressingModeField = base::BitField<AddressingMode, 9, 5>;
280 using FlagsModeField = base::BitField<FlagsMode, 14, 3>;
281 using FlagsConditionField = base::BitField<FlagsCondition, 17, 5>;
282 using MiscField = base::BitField<int, 22, 10>;
283
284 } // namespace compiler
285 } // namespace internal
286 } // namespace v8
287
288 #endif // V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
289