blob: f9e68cea5768ec33be435af87b59e06c6ebe4448 [file] [log] [blame]
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
#define V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_
#include <iosfwd>
#if V8_TARGET_ARCH_ARM
#include "src/compiler/backend/arm/instruction-codes-arm.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/compiler/backend/arm64/instruction-codes-arm64.h"
#elif V8_TARGET_ARCH_IA32
#include "src/compiler/backend/ia32/instruction-codes-ia32.h"
#elif V8_TARGET_ARCH_MIPS
#include "src/compiler/backend/mips/instruction-codes-mips.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/compiler/backend/mips64/instruction-codes-mips64.h"
#elif V8_TARGET_ARCH_X64
#include "src/compiler/backend/x64/instruction-codes-x64.h"
#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64
#include "src/compiler/backend/ppc/instruction-codes-ppc.h"
#elif V8_TARGET_ARCH_S390
#include "src/compiler/backend/s390/instruction-codes-s390.h"
#else
#define TARGET_ARCH_OPCODE_LIST(V)
#define TARGET_ADDRESSING_MODE_LIST(V)
#endif
#include "src/base/bit-field.h"
#include "src/compiler/write-barrier-kind.h"
namespace v8 {
namespace internal {
namespace compiler {
// Modes for ArchStoreWithWriteBarrier below.
enum class RecordWriteMode {
kValueIsMap,
kValueIsPointer,
kValueIsEphemeronKey,
kValueIsAny,
};
inline RecordWriteMode WriteBarrierKindToRecordWriteMode(
WriteBarrierKind write_barrier_kind) {
switch (write_barrier_kind) {
case kMapWriteBarrier:
return RecordWriteMode::kValueIsMap;
case kPointerWriteBarrier:
return RecordWriteMode::kValueIsPointer;
case kEphemeronKeyWriteBarrier:
return RecordWriteMode::kValueIsEphemeronKey;
case kFullWriteBarrier:
return RecordWriteMode::kValueIsAny;
case kNoWriteBarrier:
// Should not be passed as argument.
default:
break;
}
UNREACHABLE();
}
// Target-specific opcodes that specify which assembly sequence to emit.
// Most opcodes specify a single instruction.
#define COMMON_ARCH_OPCODE_LIST(V) \
/* Tail call opcodes are grouped together to make IsTailCall fast */ \
/* and Arch call opcodes are grouped together to make */ \
/* IsCallWithDescriptorFlags fast */ \
V(ArchTailCallCodeObjectFromJSFunction) \
V(ArchTailCallCodeObject) \
V(ArchTailCallAddress) \
V(ArchTailCallWasm) \
/* Update IsTailCall if further TailCall opcodes are added */ \
\
V(ArchCallCodeObject) \
V(ArchCallJSFunction) \
V(ArchCallWasmFunction) \
V(ArchCallBuiltinPointer) \
/* Update IsCallWithDescriptorFlags if further Call opcodes are added */ \
\
V(ArchPrepareCallCFunction) \
V(ArchSaveCallerRegisters) \
V(ArchRestoreCallerRegisters) \
V(ArchCallCFunction) \
V(ArchPrepareTailCall) \
V(ArchJmp) \
V(ArchBinarySearchSwitch) \
V(ArchTableSwitch) \
V(ArchNop) \
V(ArchAbortCSAAssert) \
V(ArchDebugBreak) \
V(ArchComment) \
V(ArchThrowTerminator) \
V(ArchDeoptimize) \
V(ArchRet) \
V(ArchFramePointer) \
V(ArchParentFramePointer) \
V(ArchTruncateDoubleToI) \
V(ArchStoreWithWriteBarrier) \
V(ArchStackSlot) \
V(ArchWordPoisonOnSpeculation) \
V(ArchStackPointerGreaterThan) \
V(ArchStackCheckOffset) \
V(Word32AtomicLoadInt8) \
V(Word32AtomicLoadUint8) \
V(Word32AtomicLoadInt16) \
V(Word32AtomicLoadUint16) \
V(Word32AtomicLoadWord32) \
V(Word32AtomicStoreWord8) \
V(Word32AtomicStoreWord16) \
V(Word32AtomicStoreWord32) \
V(Word32AtomicExchangeInt8) \
V(Word32AtomicExchangeUint8) \
V(Word32AtomicExchangeInt16) \
V(Word32AtomicExchangeUint16) \
V(Word32AtomicExchangeWord32) \
V(Word32AtomicCompareExchangeInt8) \
V(Word32AtomicCompareExchangeUint8) \
V(Word32AtomicCompareExchangeInt16) \
V(Word32AtomicCompareExchangeUint16) \
V(Word32AtomicCompareExchangeWord32) \
V(Word32AtomicAddInt8) \
V(Word32AtomicAddUint8) \
V(Word32AtomicAddInt16) \
V(Word32AtomicAddUint16) \
V(Word32AtomicAddWord32) \
V(Word32AtomicSubInt8) \
V(Word32AtomicSubUint8) \
V(Word32AtomicSubInt16) \
V(Word32AtomicSubUint16) \
V(Word32AtomicSubWord32) \
V(Word32AtomicAndInt8) \
V(Word32AtomicAndUint8) \
V(Word32AtomicAndInt16) \
V(Word32AtomicAndUint16) \
V(Word32AtomicAndWord32) \
V(Word32AtomicOrInt8) \
V(Word32AtomicOrUint8) \
V(Word32AtomicOrInt16) \
V(Word32AtomicOrUint16) \
V(Word32AtomicOrWord32) \
V(Word32AtomicXorInt8) \
V(Word32AtomicXorUint8) \
V(Word32AtomicXorInt16) \
V(Word32AtomicXorUint16) \
V(Word32AtomicXorWord32) \
V(Ieee754Float64Acos) \
V(Ieee754Float64Acosh) \
V(Ieee754Float64Asin) \
V(Ieee754Float64Asinh) \
V(Ieee754Float64Atan) \
V(Ieee754Float64Atanh) \
V(Ieee754Float64Atan2) \
V(Ieee754Float64Cbrt) \
V(Ieee754Float64Cos) \
V(Ieee754Float64Cosh) \
V(Ieee754Float64Exp) \
V(Ieee754Float64Expm1) \
V(Ieee754Float64Log) \
V(Ieee754Float64Log1p) \
V(Ieee754Float64Log10) \
V(Ieee754Float64Log2) \
V(Ieee754Float64Pow) \
V(Ieee754Float64Sin) \
V(Ieee754Float64Sinh) \
V(Ieee754Float64Tan) \
V(Ieee754Float64Tanh)
#define ARCH_OPCODE_LIST(V) \
COMMON_ARCH_OPCODE_LIST(V) \
TARGET_ARCH_OPCODE_LIST(V)
enum ArchOpcode {
#define DECLARE_ARCH_OPCODE(Name) k##Name,
ARCH_OPCODE_LIST(DECLARE_ARCH_OPCODE)
#undef DECLARE_ARCH_OPCODE
#define COUNT_ARCH_OPCODE(Name) +1
kLastArchOpcode = -1 ARCH_OPCODE_LIST(COUNT_ARCH_OPCODE)
#undef COUNT_ARCH_OPCODE
};
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const ArchOpcode& ao);
// Addressing modes represent the "shape" of inputs to an instruction.
// Many instructions support multiple addressing modes. Addressing modes
// are encoded into the InstructionCode of the instruction and tell the
// code generator after register allocation which assembler method to call.
#define ADDRESSING_MODE_LIST(V) \
V(None) \
TARGET_ADDRESSING_MODE_LIST(V)
enum AddressingMode {
#define DECLARE_ADDRESSING_MODE(Name) kMode_##Name,
ADDRESSING_MODE_LIST(DECLARE_ADDRESSING_MODE)
#undef DECLARE_ADDRESSING_MODE
#define COUNT_ADDRESSING_MODE(Name) +1
kLastAddressingMode = -1 ADDRESSING_MODE_LIST(COUNT_ADDRESSING_MODE)
#undef COUNT_ADDRESSING_MODE
};
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const AddressingMode& am);
// The mode of the flags continuation (see below).
enum FlagsMode {
kFlags_none = 0,
kFlags_branch = 1,
kFlags_branch_and_poison = 2,
kFlags_deoptimize = 3,
kFlags_deoptimize_and_poison = 4,
kFlags_set = 5,
kFlags_trap = 6
};
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const FlagsMode& fm);
// The condition of flags continuation (see below).
enum FlagsCondition {
kEqual,
kNotEqual,
kSignedLessThan,
kSignedGreaterThanOrEqual,
kSignedLessThanOrEqual,
kSignedGreaterThan,
kUnsignedLessThan,
kUnsignedGreaterThanOrEqual,
kUnsignedLessThanOrEqual,
kUnsignedGreaterThan,
kFloatLessThanOrUnordered,
kFloatGreaterThanOrEqual,
kFloatLessThanOrEqual,
kFloatGreaterThanOrUnordered,
kFloatLessThan,
kFloatGreaterThanOrEqualOrUnordered,
kFloatLessThanOrEqualOrUnordered,
kFloatGreaterThan,
kUnorderedEqual,
kUnorderedNotEqual,
kOverflow,
kNotOverflow,
kPositiveOrZero,
kNegative
};
static constexpr FlagsCondition kStackPointerGreaterThanCondition =
kUnsignedGreaterThan;
inline FlagsCondition NegateFlagsCondition(FlagsCondition condition) {
return static_cast<FlagsCondition>(condition ^ 1);
}
FlagsCondition CommuteFlagsCondition(FlagsCondition condition);
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const FlagsCondition& fc);
enum MemoryAccessMode {
kMemoryAccessDirect = 0,
kMemoryAccessProtected = 1,
kMemoryAccessPoisoned = 2
};
// The InstructionCode is an opaque, target-specific integer that encodes
// what code to emit for an instruction in the code generator. It is not
// interesting to the register allocator, as the inputs and flags on the
// instructions specify everything of interest.
using InstructionCode = uint32_t;
// Helpers for encoding / decoding InstructionCode into the fields needed
// for code generation. We encode the instruction, addressing mode, and flags
// continuation into a single InstructionCode which is stored as part of
// the instruction.
using ArchOpcodeField = base::BitField<ArchOpcode, 0, 9>;
static_assert(ArchOpcodeField::is_valid(kLastArchOpcode),
"All opcodes must fit in the 9-bit ArchOpcodeField.");
using AddressingModeField = base::BitField<AddressingMode, 9, 5>;
using FlagsModeField = base::BitField<FlagsMode, 14, 3>;
using FlagsConditionField = base::BitField<FlagsCondition, 17, 5>;
using MiscField = base::BitField<int, 22, 10>;
} // namespace compiler
} // namespace internal
} // namespace v8
#endif // V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_