11cb0ef41Sopenharmony_ci// Copyright 2014 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <iosfwd> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_ARM 111cb0ef41Sopenharmony_ci#include "src/compiler/backend/arm/instruction-codes-arm.h" 121cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_ARM64 131cb0ef41Sopenharmony_ci#include "src/compiler/backend/arm64/instruction-codes-arm64.h" 141cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_IA32 151cb0ef41Sopenharmony_ci#include "src/compiler/backend/ia32/instruction-codes-ia32.h" 161cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_MIPS 171cb0ef41Sopenharmony_ci#include "src/compiler/backend/mips/instruction-codes-mips.h" 181cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_MIPS64 191cb0ef41Sopenharmony_ci#include "src/compiler/backend/mips64/instruction-codes-mips64.h" 201cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_LOONG64 211cb0ef41Sopenharmony_ci#include "src/compiler/backend/loong64/instruction-codes-loong64.h" 221cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_X64 231cb0ef41Sopenharmony_ci#include "src/compiler/backend/x64/instruction-codes-x64.h" 241cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 251cb0ef41Sopenharmony_ci#include "src/compiler/backend/ppc/instruction-codes-ppc.h" 261cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_S390 271cb0ef41Sopenharmony_ci#include "src/compiler/backend/s390/instruction-codes-s390.h" 281cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_RISCV64 291cb0ef41Sopenharmony_ci#include "src/compiler/backend/riscv64/instruction-codes-riscv64.h" 301cb0ef41Sopenharmony_ci#else 311cb0ef41Sopenharmony_ci#define TARGET_ARCH_OPCODE_LIST(V) 321cb0ef41Sopenharmony_ci#define TARGET_ADDRESSING_MODE_LIST(V) 331cb0ef41Sopenharmony_ci#endif 341cb0ef41Sopenharmony_ci#include "src/base/bit-field.h" 351cb0ef41Sopenharmony_ci#include "src/codegen/atomic-memory-order.h" 361cb0ef41Sopenharmony_ci#include "src/compiler/write-barrier-kind.h" 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_cinamespace v8 { 391cb0ef41Sopenharmony_cinamespace internal { 401cb0ef41Sopenharmony_cinamespace compiler { 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci// Modes for ArchStoreWithWriteBarrier below. 431cb0ef41Sopenharmony_cienum class RecordWriteMode { 441cb0ef41Sopenharmony_ci kValueIsMap, 451cb0ef41Sopenharmony_ci kValueIsPointer, 461cb0ef41Sopenharmony_ci kValueIsEphemeronKey, 471cb0ef41Sopenharmony_ci kValueIsAny, 481cb0ef41Sopenharmony_ci}; 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ciinline RecordWriteMode WriteBarrierKindToRecordWriteMode( 511cb0ef41Sopenharmony_ci WriteBarrierKind write_barrier_kind) { 521cb0ef41Sopenharmony_ci switch (write_barrier_kind) { 531cb0ef41Sopenharmony_ci case kMapWriteBarrier: 541cb0ef41Sopenharmony_ci return RecordWriteMode::kValueIsMap; 551cb0ef41Sopenharmony_ci case kPointerWriteBarrier: 561cb0ef41Sopenharmony_ci return RecordWriteMode::kValueIsPointer; 571cb0ef41Sopenharmony_ci case kEphemeronKeyWriteBarrier: 581cb0ef41Sopenharmony_ci return RecordWriteMode::kValueIsEphemeronKey; 591cb0ef41Sopenharmony_ci case kFullWriteBarrier: 601cb0ef41Sopenharmony_ci return RecordWriteMode::kValueIsAny; 611cb0ef41Sopenharmony_ci case kNoWriteBarrier: 621cb0ef41Sopenharmony_ci // Should not be passed as argument. 631cb0ef41Sopenharmony_ci default: 641cb0ef41Sopenharmony_ci break; 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci UNREACHABLE(); 671cb0ef41Sopenharmony_ci} 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci// Target-specific opcodes that specify which assembly sequence to emit. 701cb0ef41Sopenharmony_ci// Most opcodes specify a single instruction. 711cb0ef41Sopenharmony_ci#define COMMON_ARCH_OPCODE_LIST(V) \ 721cb0ef41Sopenharmony_ci /* Tail call opcodes are grouped together to make IsTailCall fast */ \ 731cb0ef41Sopenharmony_ci /* and Arch call opcodes are grouped together to make */ \ 741cb0ef41Sopenharmony_ci /* IsCallWithDescriptorFlags fast */ \ 751cb0ef41Sopenharmony_ci V(ArchTailCallCodeObject) \ 761cb0ef41Sopenharmony_ci V(ArchTailCallAddress) \ 771cb0ef41Sopenharmony_ci IF_WASM(V, ArchTailCallWasm) \ 781cb0ef41Sopenharmony_ci /* Update IsTailCall if further TailCall opcodes are added */ \ 791cb0ef41Sopenharmony_ci \ 801cb0ef41Sopenharmony_ci V(ArchCallCodeObject) \ 811cb0ef41Sopenharmony_ci V(ArchCallJSFunction) \ 821cb0ef41Sopenharmony_ci IF_WASM(V, ArchCallWasmFunction) \ 831cb0ef41Sopenharmony_ci V(ArchCallBuiltinPointer) \ 841cb0ef41Sopenharmony_ci /* Update IsCallWithDescriptorFlags if further Call opcodes are added */ \ 851cb0ef41Sopenharmony_ci \ 861cb0ef41Sopenharmony_ci V(ArchPrepareCallCFunction) \ 871cb0ef41Sopenharmony_ci V(ArchSaveCallerRegisters) \ 881cb0ef41Sopenharmony_ci V(ArchRestoreCallerRegisters) \ 891cb0ef41Sopenharmony_ci V(ArchCallCFunction) \ 901cb0ef41Sopenharmony_ci V(ArchPrepareTailCall) \ 911cb0ef41Sopenharmony_ci V(ArchJmp) \ 921cb0ef41Sopenharmony_ci V(ArchBinarySearchSwitch) \ 931cb0ef41Sopenharmony_ci V(ArchTableSwitch) \ 941cb0ef41Sopenharmony_ci V(ArchNop) \ 951cb0ef41Sopenharmony_ci V(ArchAbortCSADcheck) \ 961cb0ef41Sopenharmony_ci V(ArchDebugBreak) \ 971cb0ef41Sopenharmony_ci V(ArchComment) \ 981cb0ef41Sopenharmony_ci V(ArchThrowTerminator) \ 991cb0ef41Sopenharmony_ci V(ArchDeoptimize) \ 1001cb0ef41Sopenharmony_ci V(ArchRet) \ 1011cb0ef41Sopenharmony_ci V(ArchFramePointer) \ 1021cb0ef41Sopenharmony_ci V(ArchParentFramePointer) \ 1031cb0ef41Sopenharmony_ci V(ArchTruncateDoubleToI) \ 1041cb0ef41Sopenharmony_ci V(ArchStoreWithWriteBarrier) \ 1051cb0ef41Sopenharmony_ci V(ArchAtomicStoreWithWriteBarrier) \ 1061cb0ef41Sopenharmony_ci V(ArchStackSlot) \ 1071cb0ef41Sopenharmony_ci V(ArchStackPointerGreaterThan) \ 1081cb0ef41Sopenharmony_ci V(ArchStackCheckOffset) \ 1091cb0ef41Sopenharmony_ci V(AtomicLoadInt8) \ 1101cb0ef41Sopenharmony_ci V(AtomicLoadUint8) \ 1111cb0ef41Sopenharmony_ci V(AtomicLoadInt16) \ 1121cb0ef41Sopenharmony_ci V(AtomicLoadUint16) \ 1131cb0ef41Sopenharmony_ci V(AtomicLoadWord32) \ 1141cb0ef41Sopenharmony_ci V(AtomicStoreWord8) \ 1151cb0ef41Sopenharmony_ci V(AtomicStoreWord16) \ 1161cb0ef41Sopenharmony_ci V(AtomicStoreWord32) \ 1171cb0ef41Sopenharmony_ci V(AtomicExchangeInt8) \ 1181cb0ef41Sopenharmony_ci V(AtomicExchangeUint8) \ 1191cb0ef41Sopenharmony_ci V(AtomicExchangeInt16) \ 1201cb0ef41Sopenharmony_ci V(AtomicExchangeUint16) \ 1211cb0ef41Sopenharmony_ci V(AtomicExchangeWord32) \ 1221cb0ef41Sopenharmony_ci V(AtomicCompareExchangeInt8) \ 1231cb0ef41Sopenharmony_ci V(AtomicCompareExchangeUint8) \ 1241cb0ef41Sopenharmony_ci V(AtomicCompareExchangeInt16) \ 1251cb0ef41Sopenharmony_ci V(AtomicCompareExchangeUint16) \ 1261cb0ef41Sopenharmony_ci V(AtomicCompareExchangeWord32) \ 1271cb0ef41Sopenharmony_ci V(AtomicAddInt8) \ 1281cb0ef41Sopenharmony_ci V(AtomicAddUint8) \ 1291cb0ef41Sopenharmony_ci V(AtomicAddInt16) \ 1301cb0ef41Sopenharmony_ci V(AtomicAddUint16) \ 1311cb0ef41Sopenharmony_ci V(AtomicAddWord32) \ 1321cb0ef41Sopenharmony_ci V(AtomicSubInt8) \ 1331cb0ef41Sopenharmony_ci V(AtomicSubUint8) \ 1341cb0ef41Sopenharmony_ci V(AtomicSubInt16) \ 1351cb0ef41Sopenharmony_ci V(AtomicSubUint16) \ 1361cb0ef41Sopenharmony_ci V(AtomicSubWord32) \ 1371cb0ef41Sopenharmony_ci V(AtomicAndInt8) \ 1381cb0ef41Sopenharmony_ci V(AtomicAndUint8) \ 1391cb0ef41Sopenharmony_ci V(AtomicAndInt16) \ 1401cb0ef41Sopenharmony_ci V(AtomicAndUint16) \ 1411cb0ef41Sopenharmony_ci V(AtomicAndWord32) \ 1421cb0ef41Sopenharmony_ci V(AtomicOrInt8) \ 1431cb0ef41Sopenharmony_ci V(AtomicOrUint8) \ 1441cb0ef41Sopenharmony_ci V(AtomicOrInt16) \ 1451cb0ef41Sopenharmony_ci V(AtomicOrUint16) \ 1461cb0ef41Sopenharmony_ci V(AtomicOrWord32) \ 1471cb0ef41Sopenharmony_ci V(AtomicXorInt8) \ 1481cb0ef41Sopenharmony_ci V(AtomicXorUint8) \ 1491cb0ef41Sopenharmony_ci V(AtomicXorInt16) \ 1501cb0ef41Sopenharmony_ci V(AtomicXorUint16) \ 1511cb0ef41Sopenharmony_ci V(AtomicXorWord32) \ 1521cb0ef41Sopenharmony_ci V(Ieee754Float64Acos) \ 1531cb0ef41Sopenharmony_ci V(Ieee754Float64Acosh) \ 1541cb0ef41Sopenharmony_ci V(Ieee754Float64Asin) \ 1551cb0ef41Sopenharmony_ci V(Ieee754Float64Asinh) \ 1561cb0ef41Sopenharmony_ci V(Ieee754Float64Atan) \ 1571cb0ef41Sopenharmony_ci V(Ieee754Float64Atanh) \ 1581cb0ef41Sopenharmony_ci V(Ieee754Float64Atan2) \ 1591cb0ef41Sopenharmony_ci V(Ieee754Float64Cbrt) \ 1601cb0ef41Sopenharmony_ci V(Ieee754Float64Cos) \ 1611cb0ef41Sopenharmony_ci V(Ieee754Float64Cosh) \ 1621cb0ef41Sopenharmony_ci V(Ieee754Float64Exp) \ 1631cb0ef41Sopenharmony_ci V(Ieee754Float64Expm1) \ 1641cb0ef41Sopenharmony_ci V(Ieee754Float64Log) \ 1651cb0ef41Sopenharmony_ci V(Ieee754Float64Log1p) \ 1661cb0ef41Sopenharmony_ci V(Ieee754Float64Log10) \ 1671cb0ef41Sopenharmony_ci V(Ieee754Float64Log2) \ 1681cb0ef41Sopenharmony_ci V(Ieee754Float64Pow) \ 1691cb0ef41Sopenharmony_ci V(Ieee754Float64Sin) \ 1701cb0ef41Sopenharmony_ci V(Ieee754Float64Sinh) \ 1711cb0ef41Sopenharmony_ci V(Ieee754Float64Tan) \ 1721cb0ef41Sopenharmony_ci V(Ieee754Float64Tanh) 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci#define ARCH_OPCODE_LIST(V) \ 1751cb0ef41Sopenharmony_ci COMMON_ARCH_OPCODE_LIST(V) \ 1761cb0ef41Sopenharmony_ci TARGET_ARCH_OPCODE_LIST(V) 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_cienum ArchOpcode { 1791cb0ef41Sopenharmony_ci#define DECLARE_ARCH_OPCODE(Name) k##Name, 1801cb0ef41Sopenharmony_ci ARCH_OPCODE_LIST(DECLARE_ARCH_OPCODE) 1811cb0ef41Sopenharmony_ci#undef DECLARE_ARCH_OPCODE 1821cb0ef41Sopenharmony_ci#define COUNT_ARCH_OPCODE(Name) +1 1831cb0ef41Sopenharmony_ci kLastArchOpcode = -1 ARCH_OPCODE_LIST(COUNT_ARCH_OPCODE) 1841cb0ef41Sopenharmony_ci#undef COUNT_ARCH_OPCODE 1851cb0ef41Sopenharmony_ci}; 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 1881cb0ef41Sopenharmony_ci const ArchOpcode& ao); 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci// Addressing modes represent the "shape" of inputs to an instruction. 1911cb0ef41Sopenharmony_ci// Many instructions support multiple addressing modes. Addressing modes 1921cb0ef41Sopenharmony_ci// are encoded into the InstructionCode of the instruction and tell the 1931cb0ef41Sopenharmony_ci// code generator after register allocation which assembler method to call. 1941cb0ef41Sopenharmony_ci#define ADDRESSING_MODE_LIST(V) \ 1951cb0ef41Sopenharmony_ci V(None) \ 1961cb0ef41Sopenharmony_ci TARGET_ADDRESSING_MODE_LIST(V) 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_cienum AddressingMode { 1991cb0ef41Sopenharmony_ci#define DECLARE_ADDRESSING_MODE(Name) kMode_##Name, 2001cb0ef41Sopenharmony_ci ADDRESSING_MODE_LIST(DECLARE_ADDRESSING_MODE) 2011cb0ef41Sopenharmony_ci#undef DECLARE_ADDRESSING_MODE 2021cb0ef41Sopenharmony_ci#define COUNT_ADDRESSING_MODE(Name) +1 2031cb0ef41Sopenharmony_ci kLastAddressingMode = -1 ADDRESSING_MODE_LIST(COUNT_ADDRESSING_MODE) 2041cb0ef41Sopenharmony_ci#undef COUNT_ADDRESSING_MODE 2051cb0ef41Sopenharmony_ci}; 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 2081cb0ef41Sopenharmony_ci const AddressingMode& am); 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci// The mode of the flags continuation (see below). 2111cb0ef41Sopenharmony_cienum FlagsMode { 2121cb0ef41Sopenharmony_ci kFlags_none = 0, 2131cb0ef41Sopenharmony_ci kFlags_branch = 1, 2141cb0ef41Sopenharmony_ci kFlags_deoptimize = 2, 2151cb0ef41Sopenharmony_ci kFlags_set = 3, 2161cb0ef41Sopenharmony_ci kFlags_trap = 4, 2171cb0ef41Sopenharmony_ci kFlags_select = 5, 2181cb0ef41Sopenharmony_ci}; 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 2211cb0ef41Sopenharmony_ci const FlagsMode& fm); 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci// The condition of flags continuation (see below). 2241cb0ef41Sopenharmony_cienum FlagsCondition { 2251cb0ef41Sopenharmony_ci kEqual, 2261cb0ef41Sopenharmony_ci kNotEqual, 2271cb0ef41Sopenharmony_ci kSignedLessThan, 2281cb0ef41Sopenharmony_ci kSignedGreaterThanOrEqual, 2291cb0ef41Sopenharmony_ci kSignedLessThanOrEqual, 2301cb0ef41Sopenharmony_ci kSignedGreaterThan, 2311cb0ef41Sopenharmony_ci kUnsignedLessThan, 2321cb0ef41Sopenharmony_ci kUnsignedGreaterThanOrEqual, 2331cb0ef41Sopenharmony_ci kUnsignedLessThanOrEqual, 2341cb0ef41Sopenharmony_ci kUnsignedGreaterThan, 2351cb0ef41Sopenharmony_ci kFloatLessThanOrUnordered, 2361cb0ef41Sopenharmony_ci kFloatGreaterThanOrEqual, 2371cb0ef41Sopenharmony_ci kFloatLessThanOrEqual, 2381cb0ef41Sopenharmony_ci kFloatGreaterThanOrUnordered, 2391cb0ef41Sopenharmony_ci kFloatLessThan, 2401cb0ef41Sopenharmony_ci kFloatGreaterThanOrEqualOrUnordered, 2411cb0ef41Sopenharmony_ci kFloatLessThanOrEqualOrUnordered, 2421cb0ef41Sopenharmony_ci kFloatGreaterThan, 2431cb0ef41Sopenharmony_ci kUnorderedEqual, 2441cb0ef41Sopenharmony_ci kUnorderedNotEqual, 2451cb0ef41Sopenharmony_ci kOverflow, 2461cb0ef41Sopenharmony_ci kNotOverflow, 2471cb0ef41Sopenharmony_ci kPositiveOrZero, 2481cb0ef41Sopenharmony_ci kNegative 2491cb0ef41Sopenharmony_ci}; 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_cistatic constexpr FlagsCondition kStackPointerGreaterThanCondition = 2521cb0ef41Sopenharmony_ci kUnsignedGreaterThan; 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ciinline FlagsCondition NegateFlagsCondition(FlagsCondition condition) { 2551cb0ef41Sopenharmony_ci return static_cast<FlagsCondition>(condition ^ 1); 2561cb0ef41Sopenharmony_ci} 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ciFlagsCondition CommuteFlagsCondition(FlagsCondition condition); 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 2611cb0ef41Sopenharmony_ci const FlagsCondition& fc); 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_cienum MemoryAccessMode { 2641cb0ef41Sopenharmony_ci kMemoryAccessDirect = 0, 2651cb0ef41Sopenharmony_ci kMemoryAccessProtected = 1, 2661cb0ef41Sopenharmony_ci}; 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_cienum class AtomicWidth { kWord32, kWord64 }; 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ciinline size_t AtomicWidthSize(AtomicWidth width) { 2711cb0ef41Sopenharmony_ci switch (width) { 2721cb0ef41Sopenharmony_ci case AtomicWidth::kWord32: 2731cb0ef41Sopenharmony_ci return 4; 2741cb0ef41Sopenharmony_ci case AtomicWidth::kWord64: 2751cb0ef41Sopenharmony_ci return 8; 2761cb0ef41Sopenharmony_ci } 2771cb0ef41Sopenharmony_ci UNREACHABLE(); 2781cb0ef41Sopenharmony_ci} 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci// The InstructionCode is an opaque, target-specific integer that encodes 2811cb0ef41Sopenharmony_ci// what code to emit for an instruction in the code generator. It is not 2821cb0ef41Sopenharmony_ci// interesting to the register allocator, as the inputs and flags on the 2831cb0ef41Sopenharmony_ci// instructions specify everything of interest. 2841cb0ef41Sopenharmony_ciusing InstructionCode = uint32_t; 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci// Helpers for encoding / decoding InstructionCode into the fields needed 2871cb0ef41Sopenharmony_ci// for code generation. We encode the instruction, addressing mode, and flags 2881cb0ef41Sopenharmony_ci// continuation into a single InstructionCode which is stored as part of 2891cb0ef41Sopenharmony_ci// the instruction. 2901cb0ef41Sopenharmony_ciusing ArchOpcodeField = base::BitField<ArchOpcode, 0, 9>; 2911cb0ef41Sopenharmony_cistatic_assert(ArchOpcodeField::is_valid(kLastArchOpcode), 2921cb0ef41Sopenharmony_ci "All opcodes must fit in the 9-bit ArchOpcodeField."); 2931cb0ef41Sopenharmony_ciusing AddressingModeField = base::BitField<AddressingMode, 9, 5>; 2941cb0ef41Sopenharmony_cistatic_assert( 2951cb0ef41Sopenharmony_ci AddressingModeField::is_valid(kLastAddressingMode), 2961cb0ef41Sopenharmony_ci "All addressing modes must fit in the 5-bit AddressingModeField."); 2971cb0ef41Sopenharmony_ciusing FlagsModeField = base::BitField<FlagsMode, 14, 3>; 2981cb0ef41Sopenharmony_ciusing FlagsConditionField = base::BitField<FlagsCondition, 17, 5>; 2991cb0ef41Sopenharmony_ciusing MiscField = base::BitField<int, 22, 10>; 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci// {MiscField} is used for a variety of things, depending on the opcode. 3021cb0ef41Sopenharmony_ci// TODO(turbofan): There should be an abstraction that ensures safe encoding and 3031cb0ef41Sopenharmony_ci// decoding. {HasMemoryAccessMode} and its uses are a small step in that 3041cb0ef41Sopenharmony_ci// direction. 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci// LaneSizeField and AccessModeField are helper types to encode/decode a lane 3071cb0ef41Sopenharmony_ci// size, an access mode, or both inside the overlapping MiscField. 3081cb0ef41Sopenharmony_ciusing LaneSizeField = base::BitField<int, 22, 8>; 3091cb0ef41Sopenharmony_ciusing AccessModeField = base::BitField<MemoryAccessMode, 30, 2>; 3101cb0ef41Sopenharmony_ci// TODO(turbofan): {HasMemoryAccessMode} is currently only used to guard 3111cb0ef41Sopenharmony_ci// decoding (in CodeGenerator and InstructionScheduler). Encoding (in 3121cb0ef41Sopenharmony_ci// InstructionSelector) is not yet guarded. There are in fact instructions for 3131cb0ef41Sopenharmony_ci// which InstructionSelector does set a MemoryAccessMode but CodeGenerator 3141cb0ef41Sopenharmony_ci// doesn't care to consume it (e.g. kArm64LdrDecompressTaggedSigned). This is 3151cb0ef41Sopenharmony_ci// scary. {HasMemoryAccessMode} does not include these instructions, so they can 3161cb0ef41Sopenharmony_ci// be easily found by guarding encoding. 3171cb0ef41Sopenharmony_ciinline bool HasMemoryAccessMode(ArchOpcode opcode) { 3181cb0ef41Sopenharmony_ci#if defined(TARGET_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST) 3191cb0ef41Sopenharmony_ci switch (opcode) { 3201cb0ef41Sopenharmony_ci#define CASE(Name) \ 3211cb0ef41Sopenharmony_ci case k##Name: \ 3221cb0ef41Sopenharmony_ci return true; 3231cb0ef41Sopenharmony_ci TARGET_ARCH_OPCODE_WITH_MEMORY_ACCESS_MODE_LIST(CASE) 3241cb0ef41Sopenharmony_ci#undef CASE 3251cb0ef41Sopenharmony_ci default: 3261cb0ef41Sopenharmony_ci return false; 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci#else 3291cb0ef41Sopenharmony_ci return false; 3301cb0ef41Sopenharmony_ci#endif 3311cb0ef41Sopenharmony_ci} 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ciusing DeoptImmedArgsCountField = base::BitField<int, 22, 2>; 3341cb0ef41Sopenharmony_ciusing DeoptFrameStateOffsetField = base::BitField<int, 24, 8>; 3351cb0ef41Sopenharmony_ci 3361cb0ef41Sopenharmony_ci// AtomicWidthField overlaps with MiscField and is used for the various Atomic 3371cb0ef41Sopenharmony_ci// opcodes. Only used on 64bit architectures. All atomic instructions on 32bit 3381cb0ef41Sopenharmony_ci// architectures are assumed to be 32bit wide. 3391cb0ef41Sopenharmony_ciusing AtomicWidthField = base::BitField<AtomicWidth, 22, 2>; 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci// AtomicMemoryOrderField overlaps with MiscField and is used for the various 3421cb0ef41Sopenharmony_ci// Atomic opcodes. This field is not used on all architectures. It is used on 3431cb0ef41Sopenharmony_ci// architectures where the codegen for kSeqCst and kAcqRel differ only by 3441cb0ef41Sopenharmony_ci// emitting fences. 3451cb0ef41Sopenharmony_ciusing AtomicMemoryOrderField = base::BitField<AtomicMemoryOrder, 24, 2>; 3461cb0ef41Sopenharmony_ciusing AtomicStoreRecordWriteModeField = base::BitField<RecordWriteMode, 26, 4>; 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci// ParamField and FPParamField overlap with MiscField, as the latter is never 3491cb0ef41Sopenharmony_ci// used for Call instructions. These 2 fields represent the general purpose 3501cb0ef41Sopenharmony_ci// and floating point parameter counts of a direct call into C and are given 5 3511cb0ef41Sopenharmony_ci// bits each, which allow storing a number up to the current maximum parameter 3521cb0ef41Sopenharmony_ci// count, which is 20 (see kMaxCParameters defined in macro-assembler.h). 3531cb0ef41Sopenharmony_ciusing ParamField = base::BitField<int, 22, 5>; 3541cb0ef41Sopenharmony_ciusing FPParamField = base::BitField<int, 27, 5>; 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ci// This static assertion serves as an early warning if we are about to exhaust 3571cb0ef41Sopenharmony_ci// the available opcode space. If we are about to exhaust it, we should start 3581cb0ef41Sopenharmony_ci// looking into options to compress some opcodes (see 3591cb0ef41Sopenharmony_ci// https://crbug.com/v8/12093) before we fully run out of available opcodes. 3601cb0ef41Sopenharmony_ci// Otherwise we risk being unable to land an important security fix or merge 3611cb0ef41Sopenharmony_ci// back fixes that add new opcodes. 3621cb0ef41Sopenharmony_ci// It is OK to temporarily reduce the required slack if we have a tracking bug 3631cb0ef41Sopenharmony_ci// to reduce the number of used opcodes again. 3641cb0ef41Sopenharmony_cistatic_assert(ArchOpcodeField::kMax - kLastArchOpcode >= 16, 3651cb0ef41Sopenharmony_ci "We are running close to the number of available opcodes."); 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci} // namespace compiler 3681cb0ef41Sopenharmony_ci} // namespace internal 3691cb0ef41Sopenharmony_ci} // namespace v8 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci#endif // V8_COMPILER_BACKEND_INSTRUCTION_CODES_H_ 372