// 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 #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(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; static_assert(ArchOpcodeField::is_valid(kLastArchOpcode), "All opcodes must fit in the 9-bit ArchOpcodeField."); using AddressingModeField = base::BitField; using FlagsModeField = base::BitField; using FlagsConditionField = base::BitField; using MiscField = base::BitField; } // namespace compiler } // namespace internal } // namespace v8 #endif // V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_