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_LOONG64
21#include "src/compiler/backend/loong64/instruction-codes-loong64.h"
22#elif V8_TARGET_ARCH_X64
23#include "src/compiler/backend/x64/instruction-codes-x64.h"
24#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
25#include "src/compiler/backend/ppc/instruction-codes-ppc.h"
26#elif V8_TARGET_ARCH_S390
27#include "src/compiler/backend/s390/instruction-codes-s390.h"
28#elif V8_TARGET_ARCH_RISCV64
29#include "src/compiler/backend/riscv64/instruction-codes-riscv64.h"
30#else
31#define TARGET_ARCH_OPCODE_LIST(V)
32#define TARGET_ADDRESSING_MODE_LIST(V)
33#endif
34#include "src/base/bit-field.h"
35#include "src/codegen/atomic-memory-order.h"
36#include "src/compiler/write-barrier-kind.h"
37
38namespace v8 {
39namespace internal {
40namespace compiler {
41
42// Modes for ArchStoreWithWriteBarrier below.
43enum class RecordWriteMode {
44  kValueIsMap,
45  kValueIsPointer,
46  kValueIsEphemeronKey,
47  kValueIsAny,
48};
49
50inline RecordWriteMode WriteBarrierKindToRecordWriteMode(
51    WriteBarrierKind write_barrier_kind) {
52  switch (write_barrier_kind) {
53    case kMapWriteBarrier:
54      return RecordWriteMode::kValueIsMap;
55    case kPointerWriteBarrier:
56      return RecordWriteMode::kValueIsPointer;
57    case kEphemeronKeyWriteBarrier:
58      return RecordWriteMode::kValueIsEphemeronKey;
59    case kFullWriteBarrier:
60      return RecordWriteMode::kValueIsAny;
61    case kNoWriteBarrier:
62    // Should not be passed as argument.
63    default:
64      break;
65  }
66  UNREACHABLE();
67}
68
69// Target-specific opcodes that specify which assembly sequence to emit.
70// Most opcodes specify a single instruction.
71#define COMMON_ARCH_OPCODE_LIST(V)                                         \
72  /* Tail call opcodes are grouped together to make IsTailCall fast */     \
73  /* and Arch call opcodes are grouped together to make */                 \
74  /* IsCallWithDescriptorFlags fast */                                     \
75  V(ArchTailCallCodeObject)                                                \
76  V(ArchTailCallAddress)                                                   \
77  IF_WASM(V, ArchTailCallWasm)                                             \
78  /* Update IsTailCall if further TailCall opcodes are added */            \
79                                                                           \
80  V(ArchCallCodeObject)                                                    \
81  V(ArchCallJSFunction)                                                    \
82  IF_WASM(V, ArchCallWasmFunction)                                         \
83  V(ArchCallBuiltinPointer)                                                \
84  /* Update IsCallWithDescriptorFlags if further Call opcodes are added */ \
85                                                                           \
86  V(ArchPrepareCallCFunction)                                              \
87  V(ArchSaveCallerRegisters)                                               \
88  V(ArchRestoreCallerRegisters)                                            \
89  V(ArchCallCFunction)                                                     \
90  V(ArchPrepareTailCall)                                                   \
91  V(ArchJmp)                                                               \
92  V(ArchBinarySearchSwitch)                                                \
93  V(ArchTableSwitch)                                                       \
94  V(ArchNop)                                                               \
95  V(ArchAbortCSADcheck)                                                    \
96  V(ArchDebugBreak)                                                        \
97  V(ArchComment)                                                           \
98  V(ArchThrowTerminator)                                                   \
99  V(ArchDeoptimize)                                                        \
100  V(ArchRet)                                                               \
101  V(ArchFramePointer)                                                      \
102  V(ArchParentFramePointer)                                                \
103  V(ArchTruncateDoubleToI)                                                 \
104  V(ArchStoreWithWriteBarrier)                                             \
105  V(ArchAtomicStoreWithWriteBarrier)                                       \
106  V(ArchStackSlot)                                                         \
107  V(ArchStackPointerGreaterThan)                                           \
108  V(ArchStackCheckOffset)                                                  \
109  V(AtomicLoadInt8)                                                        \
110  V(AtomicLoadUint8)                                                       \
111  V(AtomicLoadInt16)                                                       \
112  V(AtomicLoadUint16)                                                      \
113  V(AtomicLoadWord32)                                                      \
114  V(AtomicStoreWord8)                                                      \
115  V(AtomicStoreWord16)                                                     \
116  V(AtomicStoreWord32)                                                     \
117  V(AtomicExchangeInt8)                                                    \
118  V(AtomicExchangeUint8)                                                   \
119  V(AtomicExchangeInt16)                                                   \
120  V(AtomicExchangeUint16)                                                  \
121  V(AtomicExchangeWord32)                                                  \
122  V(AtomicCompareExchangeInt8)                                             \
123  V(AtomicCompareExchangeUint8)                                            \
124  V(AtomicCompareExchangeInt16)                                            \
125  V(AtomicCompareExchangeUint16)                                           \
126  V(AtomicCompareExchangeWord32)                                           \
127  V(AtomicAddInt8)                                                         \
128  V(AtomicAddUint8)                                                        \
129  V(AtomicAddInt16)                                                        \
130  V(AtomicAddUint16)                                                       \
131  V(AtomicAddWord32)                                                       \
132  V(AtomicSubInt8)                                                         \
133  V(AtomicSubUint8)                                                        \
134  V(AtomicSubInt16)                                                        \
135  V(AtomicSubUint16)                                                       \
136  V(AtomicSubWord32)                                                       \
137  V(AtomicAndInt8)                                                         \
138  V(AtomicAndUint8)                                                        \
139  V(AtomicAndInt16)                                                        \
140  V(AtomicAndUint16)                                                       \
141  V(AtomicAndWord32)                                                       \
142  V(AtomicOrInt8)                                                          \
143  V(AtomicOrUint8)                                                         \
144  V(AtomicOrInt16)                                                         \
145  V(AtomicOrUint16)                                                        \
146  V(AtomicOrWord32)                                                        \
147  V(AtomicXorInt8)                                                         \
148  V(AtomicXorUint8)                                                        \
149  V(AtomicXorInt16)                                                        \
150  V(AtomicXorUint16)                                                       \
151  V(AtomicXorWord32)                                                       \
152  V(Ieee754Float64Acos)                                                    \
153  V(Ieee754Float64Acosh)                                                   \
154  V(Ieee754Float64Asin)                                                    \
155  V(Ieee754Float64Asinh)                                                   \
156  V(Ieee754Float64Atan)                                                    \
157  V(Ieee754Float64Atanh)                                                   \
158  V(Ieee754Float64Atan2)                                                   \
159  V(Ieee754Float64Cbrt)                                                    \
160  V(Ieee754Float64Cos)                                                     \
161  V(Ieee754Float64Cosh)                                                    \
162  V(Ieee754Float64Exp)                                                     \
163  V(Ieee754Float64Expm1)                                                   \
164  V(Ieee754Float64Log)                                                     \
165  V(Ieee754Float64Log1p)                                                   \
166  V(Ieee754Float64Log10)                                                   \
167  V(Ieee754Float64Log2)                                                    \
168  V(Ieee754Float64Pow)                                                     \
169  V(Ieee754Float64Sin)                                                     \
170  V(Ieee754Float64Sinh)                                                    \
171  V(Ieee754Float64Tan)                                                     \
172  V(Ieee754Float64Tanh)
173
174#define ARCH_OPCODE_LIST(V)  \
175  COMMON_ARCH_OPCODE_LIST(V) \
176  TARGET_ARCH_OPCODE_LIST(V)
177
178enum ArchOpcode {
179#define DECLARE_ARCH_OPCODE(Name) k##Name,
180  ARCH_OPCODE_LIST(DECLARE_ARCH_OPCODE)
181#undef DECLARE_ARCH_OPCODE
182#define COUNT_ARCH_OPCODE(Name) +1
183      kLastArchOpcode = -1 ARCH_OPCODE_LIST(COUNT_ARCH_OPCODE)
184#undef COUNT_ARCH_OPCODE
185};
186
187V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
188                                           const ArchOpcode& ao);
189
190// Addressing modes represent the "shape" of inputs to an instruction.
191// Many instructions support multiple addressing modes. Addressing modes
192// are encoded into the InstructionCode of the instruction and tell the
193// code generator after register allocation which assembler method to call.
194#define ADDRESSING_MODE_LIST(V) \
195  V(None)                       \
196  TARGET_ADDRESSING_MODE_LIST(V)
197
198enum AddressingMode {
199#define DECLARE_ADDRESSING_MODE(Name) kMode_##Name,
200  ADDRESSING_MODE_LIST(DECLARE_ADDRESSING_MODE)
201#undef DECLARE_ADDRESSING_MODE
202#define COUNT_ADDRESSING_MODE(Name) +1
203      kLastAddressingMode = -1 ADDRESSING_MODE_LIST(COUNT_ADDRESSING_MODE)
204#undef COUNT_ADDRESSING_MODE
205};
206
207V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
208                                           const AddressingMode& am);
209
210// The mode of the flags continuation (see below).
211enum FlagsMode {
212  kFlags_none = 0,
213  kFlags_branch = 1,
214  kFlags_deoptimize = 2,
215  kFlags_set = 3,
216  kFlags_trap = 4,
217  kFlags_select = 5,
218};
219
220V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
221                                           const FlagsMode& fm);
222
223// The condition of flags continuation (see below).
224enum FlagsCondition {
225  kEqual,
226  kNotEqual,
227  kSignedLessThan,
228  kSignedGreaterThanOrEqual,
229  kSignedLessThanOrEqual,
230  kSignedGreaterThan,
231  kUnsignedLessThan,
232  kUnsignedGreaterThanOrEqual,
233  kUnsignedLessThanOrEqual,
234  kUnsignedGreaterThan,
235  kFloatLessThanOrUnordered,
236  kFloatGreaterThanOrEqual,
237  kFloatLessThanOrEqual,
238  kFloatGreaterThanOrUnordered,
239  kFloatLessThan,
240  kFloatGreaterThanOrEqualOrUnordered,
241  kFloatLessThanOrEqualOrUnordered,
242  kFloatGreaterThan,
243  kUnorderedEqual,
244  kUnorderedNotEqual,
245  kOverflow,
246  kNotOverflow,
247  kPositiveOrZero,
248  kNegative
249};
250
251static constexpr FlagsCondition kStackPointerGreaterThanCondition =
252    kUnsignedGreaterThan;
253
254inline FlagsCondition NegateFlagsCondition(FlagsCondition condition) {
255  return static_cast<FlagsCondition>(condition ^ 1);
256}
257
258FlagsCondition CommuteFlagsCondition(FlagsCondition condition);
259
260V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
261                                           const FlagsCondition& fc);
262
263enum MemoryAccessMode {
264  kMemoryAccessDirect = 0,
265  kMemoryAccessProtected = 1,
266};
267
268enum class AtomicWidth { kWord32, kWord64 };
269
270inline size_t AtomicWidthSize(AtomicWidth width) {
271  switch (width) {
272    case AtomicWidth::kWord32:
273      return 4;
274    case AtomicWidth::kWord64:
275      return 8;
276  }
277  UNREACHABLE();
278}
279
280// The InstructionCode is an opaque, target-specific integer that encodes
281// what code to emit for an instruction in the code generator. It is not
282// interesting to the register allocator, as the inputs and flags on the
283// instructions specify everything of interest.
284using InstructionCode = uint32_t;
285
286// Helpers for encoding / decoding InstructionCode into the fields needed
287// for code generation. We encode the instruction, addressing mode, and flags
288// continuation into a single InstructionCode which is stored as part of
289// the instruction.
290using ArchOpcodeField = base::BitField<ArchOpcode, 0, 9>;
291static_assert(ArchOpcodeField::is_valid(kLastArchOpcode),
292              "All opcodes must fit in the 9-bit ArchOpcodeField.");
293using AddressingModeField = base::BitField<AddressingMode, 9, 5>;
294static_assert(
295    AddressingModeField::is_valid(kLastAddressingMode),
296    "All addressing modes must fit in the 5-bit AddressingModeField.");
297using FlagsModeField = base::BitField<FlagsMode, 14, 3>;
298using FlagsConditionField = base::BitField<FlagsCondition, 17, 5>;
299using MiscField = base::BitField<int, 22, 10>;
300
301// {MiscField} is used for a variety of things, depending on the opcode.
302// TODO(turbofan): There should be an abstraction that ensures safe encoding and
303// decoding. {HasMemoryAccessMode} and its uses are a small step in that
304// direction.
305
306// LaneSizeField and AccessModeField are helper types to encode/decode a lane
307// size, an access mode, or both inside the overlapping MiscField.
308using LaneSizeField = base::BitField<int, 22, 8>;
309using AccessModeField = base::BitField<MemoryAccessMode, 30, 2>;
310// TODO(turbofan): {HasMemoryAccessMode} is currently only used to guard
311// decoding (in CodeGenerator and InstructionScheduler). Encoding (in
312// InstructionSelector) is not yet guarded. There are in fact instructions for
313// which InstructionSelector does set a MemoryAccessMode but CodeGenerator
314// doesn't care to consume it (e.g. kArm64LdrDecompressTaggedSigned). This is
315// scary. {HasMemoryAccessMode} does not include these instructions, so they can
316// be easily found by guarding encoding.
317inline bool HasMemoryAccessMode(ArchOpcode opcode) {
318#if defined(TARGET_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST)
319  switch (opcode) {
320#define CASE(Name) \
321  case k##Name:    \
322    return true;
323    TARGET_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST(CASE)
324#undef CASE
325    default:
326      return false;
327  }
328#else
329  return false;
330#endif
331}
332
333using DeoptImmedArgsCountField = base::BitField<int, 22, 2>;
334using DeoptFrameStateOffsetField = base::BitField<int, 24, 8>;
335
336// AtomicWidthField overlaps with MiscField and is used for the various Atomic
337// opcodes. Only used on 64bit architectures. All atomic instructions on 32bit
338// architectures are assumed to be 32bit wide.
339using AtomicWidthField = base::BitField<AtomicWidth, 22, 2>;
340
341// AtomicMemoryOrderField overlaps with MiscField and is used for the various
342// Atomic opcodes. This field is not used on all architectures. It is used on
343// architectures where the codegen for kSeqCst and kAcqRel differ only by
344// emitting fences.
345using AtomicMemoryOrderField = base::BitField<AtomicMemoryOrder, 24, 2>;
346using AtomicStoreRecordWriteModeField = base::BitField<RecordWriteMode, 26, 4>;
347
348// ParamField and FPParamField overlap with MiscField, as the latter is never
349// used for Call instructions. These 2 fields represent the general purpose
350// and floating point parameter counts of a direct call into C and are given 5
351// bits each, which allow storing a number up to the current maximum parameter
352// count, which is 20 (see kMaxCParameters defined in macro-assembler.h).
353using ParamField = base::BitField<int, 22, 5>;
354using FPParamField = base::BitField<int, 27, 5>;
355
356// This static assertion serves as an early warning if we are about to exhaust
357// the available opcode space. If we are about to exhaust it, we should start
358// looking into options to compress some opcodes (see
359// https://crbug.com/v8/12093) before we fully run out of available opcodes.
360// Otherwise we risk being unable to land an important security fix or merge
361// back fixes that add new opcodes.
362// It is OK to temporarily reduce the required slack if we have a tracking bug
363// to reduce the number of used opcodes again.
364static_assert(ArchOpcodeField::kMax - kLastArchOpcode >= 16,
365              "We are running close to the number of available opcodes.");
366
367}  // namespace compiler
368}  // namespace internal
369}  // namespace v8
370
371#endif  // V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
372