[assembler] Make register definitions constexpr
I originally needed this for the initialization of a constexpr array in the wasm lazy compile builtin, but since it's a bigger change, I now split it off as this separate CL. The style guide recommends constexpr over const. I thus apply the constexprificaton over all headers that I touched anyway. I also remove the ARM64_DEFINE_REG_STATICS hack. It was introduced when merging in arm64 support more than three years ago, and I don't see the purpose for this. Also, some #defines can now be constexpr definitions, which was not possible before according to the comment. R=bmeurer@chromium.org, mstarzinger@chromium.org, ishell@chromium.org Change-Id: I6d743b4462c347d363f99e28007bc9e8c84ae617 Reviewed-on: https://chromium-review.googlesource.com/451277 Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Reviewed-by: Igor Sheludko <ishell@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#43637}
This commit is contained in:
parent
8038f1bd67
commit
e82b7ccd32
@ -114,7 +114,7 @@ struct Register {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kNumRegisters = Code::kAfterLast;
|
||||
|
||||
static Register from_code(int code) {
|
||||
DCHECK(code >= 0);
|
||||
@ -144,13 +144,13 @@ struct Register {
|
||||
// r7: context register
|
||||
// r8: constant pool pointer register if FLAG_enable_embedded_constant_pool.
|
||||
// r9: lithium scratch
|
||||
#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
|
||||
#define DECLARE_REGISTER(R) constexpr Register R = {Register::kCode_##R};
|
||||
GENERAL_REGISTERS(DECLARE_REGISTER)
|
||||
#undef DECLARE_REGISTER
|
||||
const Register no_reg = {Register::kCode_no_reg};
|
||||
constexpr Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
static const bool kSimpleFPAliasing = false;
|
||||
static const bool kSimdMaskRegisters = false;
|
||||
constexpr bool kSimpleFPAliasing = false;
|
||||
constexpr bool kSimdMaskRegisters = false;
|
||||
|
||||
// Single word VFP register.
|
||||
struct SwVfpRegister {
|
||||
@ -162,9 +162,9 @@ struct SwVfpRegister {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kMaxNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kMaxNumRegisters = Code::kAfterLast;
|
||||
|
||||
static const int kSizeInBytes = 4;
|
||||
static constexpr int kSizeInBytes = 4;
|
||||
|
||||
bool is_valid() const { return 0 <= reg_code && reg_code < 32; }
|
||||
bool is(SwVfpRegister reg) const { return reg_code == reg.reg_code; }
|
||||
@ -201,7 +201,7 @@ struct DwVfpRegister {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kMaxNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kMaxNumRegisters = Code::kAfterLast;
|
||||
|
||||
inline static int NumRegisters();
|
||||
|
||||
@ -209,7 +209,7 @@ struct DwVfpRegister {
|
||||
// hold 0.0, that does not fit in the immediate field of vmov instructions.
|
||||
// d14: 0.0
|
||||
// d15: scratch register.
|
||||
static const int kSizeInBytes = 8;
|
||||
static constexpr int kSizeInBytes = 8;
|
||||
|
||||
bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
|
||||
bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
|
||||
@ -242,10 +242,9 @@ typedef DwVfpRegister DoubleRegister;
|
||||
// Double word VFP register d0-15.
|
||||
struct LowDwVfpRegister {
|
||||
public:
|
||||
static const int kMaxNumLowRegisters = 16;
|
||||
operator DwVfpRegister() const {
|
||||
DwVfpRegister r = { reg_code };
|
||||
return r;
|
||||
static constexpr int kMaxNumLowRegisters = 16;
|
||||
constexpr operator DwVfpRegister() const {
|
||||
return DwVfpRegister { reg_code };
|
||||
}
|
||||
static LowDwVfpRegister from_code(int code) {
|
||||
LowDwVfpRegister r = { code };
|
||||
@ -282,7 +281,7 @@ struct LowDwVfpRegister {
|
||||
|
||||
// Quad word NEON register.
|
||||
struct QwNeonRegister {
|
||||
static const int kMaxNumRegisters = 16;
|
||||
static constexpr int kMaxNumRegisters = 16;
|
||||
|
||||
static QwNeonRegister from_code(int code) {
|
||||
QwNeonRegister r = { code };
|
||||
@ -328,102 +327,100 @@ typedef QwNeonRegister Simd128Register;
|
||||
|
||||
// Support for the VFP registers s0 to s31 (d0 to d15).
|
||||
// Note that "s(N):s(N+1)" is the same as "d(N/2)".
|
||||
const SwVfpRegister s0 = { 0 };
|
||||
const SwVfpRegister s1 = { 1 };
|
||||
const SwVfpRegister s2 = { 2 };
|
||||
const SwVfpRegister s3 = { 3 };
|
||||
const SwVfpRegister s4 = { 4 };
|
||||
const SwVfpRegister s5 = { 5 };
|
||||
const SwVfpRegister s6 = { 6 };
|
||||
const SwVfpRegister s7 = { 7 };
|
||||
const SwVfpRegister s8 = { 8 };
|
||||
const SwVfpRegister s9 = { 9 };
|
||||
const SwVfpRegister s10 = { 10 };
|
||||
const SwVfpRegister s11 = { 11 };
|
||||
const SwVfpRegister s12 = { 12 };
|
||||
const SwVfpRegister s13 = { 13 };
|
||||
const SwVfpRegister s14 = { 14 };
|
||||
const SwVfpRegister s15 = { 15 };
|
||||
const SwVfpRegister s16 = { 16 };
|
||||
const SwVfpRegister s17 = { 17 };
|
||||
const SwVfpRegister s18 = { 18 };
|
||||
const SwVfpRegister s19 = { 19 };
|
||||
const SwVfpRegister s20 = { 20 };
|
||||
const SwVfpRegister s21 = { 21 };
|
||||
const SwVfpRegister s22 = { 22 };
|
||||
const SwVfpRegister s23 = { 23 };
|
||||
const SwVfpRegister s24 = { 24 };
|
||||
const SwVfpRegister s25 = { 25 };
|
||||
const SwVfpRegister s26 = { 26 };
|
||||
const SwVfpRegister s27 = { 27 };
|
||||
const SwVfpRegister s28 = { 28 };
|
||||
const SwVfpRegister s29 = { 29 };
|
||||
const SwVfpRegister s30 = { 30 };
|
||||
const SwVfpRegister s31 = { 31 };
|
||||
constexpr SwVfpRegister s0 = { 0 };
|
||||
constexpr SwVfpRegister s1 = { 1 };
|
||||
constexpr SwVfpRegister s2 = { 2 };
|
||||
constexpr SwVfpRegister s3 = { 3 };
|
||||
constexpr SwVfpRegister s4 = { 4 };
|
||||
constexpr SwVfpRegister s5 = { 5 };
|
||||
constexpr SwVfpRegister s6 = { 6 };
|
||||
constexpr SwVfpRegister s7 = { 7 };
|
||||
constexpr SwVfpRegister s8 = { 8 };
|
||||
constexpr SwVfpRegister s9 = { 9 };
|
||||
constexpr SwVfpRegister s10 = { 10 };
|
||||
constexpr SwVfpRegister s11 = { 11 };
|
||||
constexpr SwVfpRegister s12 = { 12 };
|
||||
constexpr SwVfpRegister s13 = { 13 };
|
||||
constexpr SwVfpRegister s14 = { 14 };
|
||||
constexpr SwVfpRegister s15 = { 15 };
|
||||
constexpr SwVfpRegister s16 = { 16 };
|
||||
constexpr SwVfpRegister s17 = { 17 };
|
||||
constexpr SwVfpRegister s18 = { 18 };
|
||||
constexpr SwVfpRegister s19 = { 19 };
|
||||
constexpr SwVfpRegister s20 = { 20 };
|
||||
constexpr SwVfpRegister s21 = { 21 };
|
||||
constexpr SwVfpRegister s22 = { 22 };
|
||||
constexpr SwVfpRegister s23 = { 23 };
|
||||
constexpr SwVfpRegister s24 = { 24 };
|
||||
constexpr SwVfpRegister s25 = { 25 };
|
||||
constexpr SwVfpRegister s26 = { 26 };
|
||||
constexpr SwVfpRegister s27 = { 27 };
|
||||
constexpr SwVfpRegister s28 = { 28 };
|
||||
constexpr SwVfpRegister s29 = { 29 };
|
||||
constexpr SwVfpRegister s30 = { 30 };
|
||||
constexpr SwVfpRegister s31 = { 31 };
|
||||
|
||||
const DwVfpRegister no_dreg = { -1 };
|
||||
const LowDwVfpRegister d0 = { 0 };
|
||||
const LowDwVfpRegister d1 = { 1 };
|
||||
const LowDwVfpRegister d2 = { 2 };
|
||||
const LowDwVfpRegister d3 = { 3 };
|
||||
const LowDwVfpRegister d4 = { 4 };
|
||||
const LowDwVfpRegister d5 = { 5 };
|
||||
const LowDwVfpRegister d6 = { 6 };
|
||||
const LowDwVfpRegister d7 = { 7 };
|
||||
const LowDwVfpRegister d8 = { 8 };
|
||||
const LowDwVfpRegister d9 = { 9 };
|
||||
const LowDwVfpRegister d10 = { 10 };
|
||||
const LowDwVfpRegister d11 = { 11 };
|
||||
const LowDwVfpRegister d12 = { 12 };
|
||||
const LowDwVfpRegister d13 = { 13 };
|
||||
const LowDwVfpRegister d14 = { 14 };
|
||||
const LowDwVfpRegister d15 = { 15 };
|
||||
const DwVfpRegister d16 = { 16 };
|
||||
const DwVfpRegister d17 = { 17 };
|
||||
const DwVfpRegister d18 = { 18 };
|
||||
const DwVfpRegister d19 = { 19 };
|
||||
const DwVfpRegister d20 = { 20 };
|
||||
const DwVfpRegister d21 = { 21 };
|
||||
const DwVfpRegister d22 = { 22 };
|
||||
const DwVfpRegister d23 = { 23 };
|
||||
const DwVfpRegister d24 = { 24 };
|
||||
const DwVfpRegister d25 = { 25 };
|
||||
const DwVfpRegister d26 = { 26 };
|
||||
const DwVfpRegister d27 = { 27 };
|
||||
const DwVfpRegister d28 = { 28 };
|
||||
const DwVfpRegister d29 = { 29 };
|
||||
const DwVfpRegister d30 = { 30 };
|
||||
const DwVfpRegister d31 = { 31 };
|
||||
constexpr DwVfpRegister no_dreg = { -1 };
|
||||
constexpr LowDwVfpRegister d0 = { 0 };
|
||||
constexpr LowDwVfpRegister d1 = { 1 };
|
||||
constexpr LowDwVfpRegister d2 = { 2 };
|
||||
constexpr LowDwVfpRegister d3 = { 3 };
|
||||
constexpr LowDwVfpRegister d4 = { 4 };
|
||||
constexpr LowDwVfpRegister d5 = { 5 };
|
||||
constexpr LowDwVfpRegister d6 = { 6 };
|
||||
constexpr LowDwVfpRegister d7 = { 7 };
|
||||
constexpr LowDwVfpRegister d8 = { 8 };
|
||||
constexpr LowDwVfpRegister d9 = { 9 };
|
||||
constexpr LowDwVfpRegister d10 = { 10 };
|
||||
constexpr LowDwVfpRegister d11 = { 11 };
|
||||
constexpr LowDwVfpRegister d12 = { 12 };
|
||||
constexpr LowDwVfpRegister d13 = { 13 };
|
||||
constexpr LowDwVfpRegister d14 = { 14 };
|
||||
constexpr LowDwVfpRegister d15 = { 15 };
|
||||
constexpr DwVfpRegister d16 = { 16 };
|
||||
constexpr DwVfpRegister d17 = { 17 };
|
||||
constexpr DwVfpRegister d18 = { 18 };
|
||||
constexpr DwVfpRegister d19 = { 19 };
|
||||
constexpr DwVfpRegister d20 = { 20 };
|
||||
constexpr DwVfpRegister d21 = { 21 };
|
||||
constexpr DwVfpRegister d22 = { 22 };
|
||||
constexpr DwVfpRegister d23 = { 23 };
|
||||
constexpr DwVfpRegister d24 = { 24 };
|
||||
constexpr DwVfpRegister d25 = { 25 };
|
||||
constexpr DwVfpRegister d26 = { 26 };
|
||||
constexpr DwVfpRegister d27 = { 27 };
|
||||
constexpr DwVfpRegister d28 = { 28 };
|
||||
constexpr DwVfpRegister d29 = { 29 };
|
||||
constexpr DwVfpRegister d30 = { 30 };
|
||||
constexpr DwVfpRegister d31 = { 31 };
|
||||
|
||||
const QwNeonRegister q0 = { 0 };
|
||||
const QwNeonRegister q1 = { 1 };
|
||||
const QwNeonRegister q2 = { 2 };
|
||||
const QwNeonRegister q3 = { 3 };
|
||||
const QwNeonRegister q4 = { 4 };
|
||||
const QwNeonRegister q5 = { 5 };
|
||||
const QwNeonRegister q6 = { 6 };
|
||||
const QwNeonRegister q7 = { 7 };
|
||||
const QwNeonRegister q8 = { 8 };
|
||||
const QwNeonRegister q9 = { 9 };
|
||||
const QwNeonRegister q10 = { 10 };
|
||||
const QwNeonRegister q11 = { 11 };
|
||||
const QwNeonRegister q12 = { 12 };
|
||||
const QwNeonRegister q13 = { 13 };
|
||||
const QwNeonRegister q14 = { 14 };
|
||||
const QwNeonRegister q15 = { 15 };
|
||||
constexpr QwNeonRegister q0 = { 0 };
|
||||
constexpr QwNeonRegister q1 = { 1 };
|
||||
constexpr QwNeonRegister q2 = { 2 };
|
||||
constexpr QwNeonRegister q3 = { 3 };
|
||||
constexpr QwNeonRegister q4 = { 4 };
|
||||
constexpr QwNeonRegister q5 = { 5 };
|
||||
constexpr QwNeonRegister q6 = { 6 };
|
||||
constexpr QwNeonRegister q7 = { 7 };
|
||||
constexpr QwNeonRegister q8 = { 8 };
|
||||
constexpr QwNeonRegister q9 = { 9 };
|
||||
constexpr QwNeonRegister q10 = { 10 };
|
||||
constexpr QwNeonRegister q11 = { 11 };
|
||||
constexpr QwNeonRegister q12 = { 12 };
|
||||
constexpr QwNeonRegister q13 = { 13 };
|
||||
constexpr QwNeonRegister q14 = { 14 };
|
||||
constexpr QwNeonRegister q15 = { 15 };
|
||||
|
||||
|
||||
// Aliases for double registers. Defined using #define instead of
|
||||
// "static const DwVfpRegister&" because Clang complains otherwise when a
|
||||
// compilation unit that includes this header doesn't use the variables.
|
||||
#define kFirstCalleeSavedDoubleReg d8
|
||||
#define kLastCalleeSavedDoubleReg d15
|
||||
// Aliases for double registers.
|
||||
constexpr LowDwVfpRegister kFirstCalleeSavedDoubleReg = d8;
|
||||
constexpr LowDwVfpRegister kLastCalleeSavedDoubleReg = d15;
|
||||
// kDoubleRegZero and kScratchDoubleReg must pair to form kScratchQuadReg. SIMD
|
||||
// code depends on kDoubleRegZero before kScratchDoubleReg.
|
||||
#define kDoubleRegZero d14
|
||||
#define kScratchDoubleReg d15
|
||||
constexpr LowDwVfpRegister kDoubleRegZero = d14;
|
||||
constexpr LowDwVfpRegister kScratchDoubleReg = d15;
|
||||
// After using kScratchQuadReg, kDoubleRegZero must be reset to 0.
|
||||
#define kScratchQuadReg q7
|
||||
constexpr QwNeonRegister kScratchQuadReg = q7;
|
||||
|
||||
// Coprocessor register
|
||||
struct CRegister {
|
||||
@ -443,24 +440,24 @@ struct CRegister {
|
||||
};
|
||||
|
||||
|
||||
const CRegister no_creg = { -1 };
|
||||
constexpr CRegister no_creg = { -1 };
|
||||
|
||||
const CRegister cr0 = { 0 };
|
||||
const CRegister cr1 = { 1 };
|
||||
const CRegister cr2 = { 2 };
|
||||
const CRegister cr3 = { 3 };
|
||||
const CRegister cr4 = { 4 };
|
||||
const CRegister cr5 = { 5 };
|
||||
const CRegister cr6 = { 6 };
|
||||
const CRegister cr7 = { 7 };
|
||||
const CRegister cr8 = { 8 };
|
||||
const CRegister cr9 = { 9 };
|
||||
const CRegister cr10 = { 10 };
|
||||
const CRegister cr11 = { 11 };
|
||||
const CRegister cr12 = { 12 };
|
||||
const CRegister cr13 = { 13 };
|
||||
const CRegister cr14 = { 14 };
|
||||
const CRegister cr15 = { 15 };
|
||||
constexpr CRegister cr0 = { 0 };
|
||||
constexpr CRegister cr1 = { 1 };
|
||||
constexpr CRegister cr2 = { 2 };
|
||||
constexpr CRegister cr3 = { 3 };
|
||||
constexpr CRegister cr4 = { 4 };
|
||||
constexpr CRegister cr5 = { 5 };
|
||||
constexpr CRegister cr6 = { 6 };
|
||||
constexpr CRegister cr7 = { 7 };
|
||||
constexpr CRegister cr8 = { 8 };
|
||||
constexpr CRegister cr9 = { 9 };
|
||||
constexpr CRegister cr10 = { 10 };
|
||||
constexpr CRegister cr11 = { 11 };
|
||||
constexpr CRegister cr12 = { 12 };
|
||||
constexpr CRegister cr13 = { 13 };
|
||||
constexpr CRegister cr14 = { 14 };
|
||||
constexpr CRegister cr15 = { 15 };
|
||||
|
||||
|
||||
// Coprocessor number
|
||||
@ -671,8 +668,8 @@ class NeonListOperand BASE_EMBEDDED {
|
||||
struct VmovIndex {
|
||||
unsigned char index;
|
||||
};
|
||||
const VmovIndex VmovIndexLo = { 0 };
|
||||
const VmovIndex VmovIndexHi = { 1 };
|
||||
constexpr VmovIndex VmovIndexLo = { 0 };
|
||||
constexpr VmovIndex VmovIndexHi = { 1 };
|
||||
|
||||
class Assembler : public AssemblerBase {
|
||||
public:
|
||||
@ -760,24 +757,24 @@ class Assembler : public AssemblerBase {
|
||||
// Here we are patching the address in the constant pool, not the actual call
|
||||
// instruction. The address in the constant pool is the same size as a
|
||||
// pointer.
|
||||
static const int kSpecialTargetSize = kPointerSize;
|
||||
static constexpr int kSpecialTargetSize = kPointerSize;
|
||||
|
||||
// Size of an instruction.
|
||||
static const int kInstrSize = sizeof(Instr);
|
||||
static constexpr int kInstrSize = sizeof(Instr);
|
||||
|
||||
// Distance between start of patched debug break slot and the emitted address
|
||||
// to jump to.
|
||||
// Patched debug break slot code is:
|
||||
// ldr ip, [pc, #0] @ emited address and start
|
||||
// blx ip
|
||||
static const int kPatchDebugBreakSlotAddressOffset = 2 * kInstrSize;
|
||||
static constexpr int kPatchDebugBreakSlotAddressOffset = 2 * kInstrSize;
|
||||
|
||||
// Difference between address of current opcode and value read from pc
|
||||
// register.
|
||||
static const int kPcLoadDelta = 8;
|
||||
static constexpr int kPcLoadDelta = 8;
|
||||
|
||||
static const int kDebugBreakSlotInstructions = 4;
|
||||
static const int kDebugBreakSlotLength =
|
||||
static constexpr int kDebugBreakSlotInstructions = 4;
|
||||
static constexpr int kDebugBreakSlotLength =
|
||||
kDebugBreakSlotInstructions * kInstrSize;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -1592,12 +1589,14 @@ class Assembler : public AssemblerBase {
|
||||
// reach +/-4KB for integer PC-relative loads and +/-1KB for floating-point
|
||||
// PC-relative loads, thereby defining a maximum distance between the
|
||||
// instruction and the accessed constant.
|
||||
static const int kMaxDistToIntPool = 4*KB;
|
||||
static const int kMaxDistToFPPool = 1*KB;
|
||||
static constexpr int kMaxDistToIntPool = 4 * KB;
|
||||
static constexpr int kMaxDistToFPPool = 1 * KB;
|
||||
// All relocations could be integer, it therefore acts as the limit.
|
||||
static const int kMinNumPendingConstants = 4;
|
||||
static const int kMaxNumPending32Constants = kMaxDistToIntPool / kInstrSize;
|
||||
static const int kMaxNumPending64Constants = kMaxDistToFPPool / kInstrSize;
|
||||
static constexpr int kMinNumPendingConstants = 4;
|
||||
static constexpr int kMaxNumPending32Constants =
|
||||
kMaxDistToIntPool / kInstrSize;
|
||||
static constexpr int kMaxNumPending64Constants =
|
||||
kMaxDistToFPPool / kInstrSize;
|
||||
|
||||
// Postpone the generation of the constant pool for the specified number of
|
||||
// instructions.
|
||||
@ -1700,7 +1699,7 @@ class Assembler : public AssemblerBase {
|
||||
// the generated instructions. This is so that multi-instruction sequences do
|
||||
// not have to check for overflow. The same is true for writes of large
|
||||
// relocation info entries.
|
||||
static const int kGap = 32;
|
||||
static constexpr int kGap = 32;
|
||||
|
||||
// Constant pool generation
|
||||
// Pools are emitted in the instruction stream, preferably after unconditional
|
||||
@ -1716,8 +1715,8 @@ class Assembler : public AssemblerBase {
|
||||
// expensive. By default we only check again once a number of instructions
|
||||
// has been generated. That also means that the sizing of the buffers is not
|
||||
// an exact science, and that we rely on some slop to not overrun buffers.
|
||||
static const int kCheckPoolIntervalInst = 32;
|
||||
static const int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
|
||||
static constexpr int kCheckPoolIntervalInst = 32;
|
||||
static constexpr int kCheckPoolInterval = kCheckPoolIntervalInst * kInstrSize;
|
||||
|
||||
|
||||
// Emission of the constant pool may be blocked in some code sequences.
|
||||
@ -1731,7 +1730,7 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
// Relocation info generation
|
||||
// Each relocation is encoded as a variable size value
|
||||
static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
RelocInfoWriter reloc_info_writer;
|
||||
|
||||
// ConstantPoolEntry records are used during code generation as temporary
|
||||
@ -1785,7 +1784,7 @@ class Assembler : public AssemblerBase {
|
||||
friend class EnsureSpace;
|
||||
};
|
||||
|
||||
static const int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize;
|
||||
constexpr int kNoCodeAgeSequenceLength = 3 * Assembler::kInstrSize;
|
||||
|
||||
class EnsureSpace BASE_EMBEDDED {
|
||||
public:
|
||||
|
@ -28,7 +28,6 @@
|
||||
|
||||
#if V8_TARGET_ARCH_ARM64
|
||||
|
||||
#define ARM64_DEFINE_REG_STATICS
|
||||
#include "src/arm64/assembler-arm64.h"
|
||||
|
||||
#include "src/arm64/assembler-arm64-inl.h"
|
||||
|
@ -63,8 +63,7 @@ namespace internal {
|
||||
R(d25) R(d26) R(d27) R(d28)
|
||||
// clang-format on
|
||||
|
||||
static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
|
||||
|
||||
constexpr int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
|
||||
|
||||
// Some CPURegister methods can return Register and FPRegister types, so we
|
||||
// need to declare them in advance.
|
||||
@ -90,6 +89,11 @@ struct CPURegister {
|
||||
kNoRegister
|
||||
};
|
||||
|
||||
constexpr CPURegister() : CPURegister(0, 0, CPURegister::kNoRegister) {}
|
||||
|
||||
constexpr CPURegister(int reg_code, int reg_size, RegisterType reg_type)
|
||||
: reg_code(reg_code), reg_size(reg_size), reg_type(reg_type) {}
|
||||
|
||||
static CPURegister Create(int code, int size, RegisterType type) {
|
||||
CPURegister r = {code, size, type};
|
||||
return r;
|
||||
@ -138,25 +142,9 @@ struct Register : public CPURegister {
|
||||
return Register(CPURegister::Create(code, size, CPURegister::kRegister));
|
||||
}
|
||||
|
||||
Register() {
|
||||
reg_code = 0;
|
||||
reg_size = 0;
|
||||
reg_type = CPURegister::kNoRegister;
|
||||
}
|
||||
constexpr Register() : CPURegister() {}
|
||||
|
||||
explicit Register(const CPURegister& r) {
|
||||
reg_code = r.reg_code;
|
||||
reg_size = r.reg_size;
|
||||
reg_type = r.reg_type;
|
||||
DCHECK(IsValidOrNone());
|
||||
}
|
||||
|
||||
Register(const Register& r) { // NOLINT(runtime/explicit)
|
||||
reg_code = r.reg_code;
|
||||
reg_size = r.reg_size;
|
||||
reg_type = r.reg_type;
|
||||
DCHECK(IsValidOrNone());
|
||||
}
|
||||
constexpr explicit Register(const CPURegister& r) : CPURegister(r) {}
|
||||
|
||||
bool IsValid() const {
|
||||
DCHECK(IsRegister() || IsNone());
|
||||
@ -170,7 +158,7 @@ struct Register : public CPURegister {
|
||||
// These memebers are necessary for compilation.
|
||||
// A few of them may be unused for now.
|
||||
|
||||
static const int kNumRegisters = kNumberOfRegisters;
|
||||
static constexpr int kNumRegisters = kNumberOfRegisters;
|
||||
STATIC_ASSERT(kNumRegisters == Code::kAfterLast);
|
||||
static int NumRegisters() { return kNumRegisters; }
|
||||
|
||||
@ -197,8 +185,8 @@ struct Register : public CPURegister {
|
||||
// End of V8 compatibility section -----------------------
|
||||
};
|
||||
|
||||
static const bool kSimpleFPAliasing = true;
|
||||
static const bool kSimdMaskRegisters = false;
|
||||
constexpr bool kSimpleFPAliasing = true;
|
||||
constexpr bool kSimdMaskRegisters = false;
|
||||
|
||||
struct FPRegister : public CPURegister {
|
||||
enum Code {
|
||||
@ -214,25 +202,9 @@ struct FPRegister : public CPURegister {
|
||||
CPURegister::Create(code, size, CPURegister::kFPRegister));
|
||||
}
|
||||
|
||||
FPRegister() {
|
||||
reg_code = 0;
|
||||
reg_size = 0;
|
||||
reg_type = CPURegister::kNoRegister;
|
||||
}
|
||||
constexpr FPRegister() : CPURegister() {}
|
||||
|
||||
explicit FPRegister(const CPURegister& r) {
|
||||
reg_code = r.reg_code;
|
||||
reg_size = r.reg_size;
|
||||
reg_type = r.reg_type;
|
||||
DCHECK(IsValidOrNone());
|
||||
}
|
||||
|
||||
FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit)
|
||||
reg_code = r.reg_code;
|
||||
reg_size = r.reg_size;
|
||||
reg_type = r.reg_type;
|
||||
DCHECK(IsValidOrNone());
|
||||
}
|
||||
constexpr explicit FPRegister(const CPURegister& r) : CPURegister(r) {}
|
||||
|
||||
bool IsValid() const {
|
||||
DCHECK(IsFPRegister() || IsNone());
|
||||
@ -243,7 +215,7 @@ struct FPRegister : public CPURegister {
|
||||
static FPRegister DRegFromCode(unsigned code);
|
||||
|
||||
// Start of V8 compatibility section ---------------------
|
||||
static const int kMaxNumRegisters = kNumberOfFPRegisters;
|
||||
static constexpr int kMaxNumRegisters = kNumberOfFPRegisters;
|
||||
STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast);
|
||||
|
||||
// Crankshaft can use all the FP registers except:
|
||||
@ -261,54 +233,41 @@ struct FPRegister : public CPURegister {
|
||||
STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register));
|
||||
STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister));
|
||||
|
||||
|
||||
#if defined(ARM64_DEFINE_REG_STATICS)
|
||||
#define INITIALIZE_REGISTER(register_class, name, code, size, type) \
|
||||
const CPURegister init_##register_class##_##name = {code, size, type}; \
|
||||
const register_class& name = *reinterpret_cast<const register_class*>( \
|
||||
&init_##register_class##_##name)
|
||||
#define ALIAS_REGISTER(register_class, alias, name) \
|
||||
const register_class& alias = *reinterpret_cast<const register_class*>( \
|
||||
&init_##register_class##_##name)
|
||||
#else
|
||||
#define INITIALIZE_REGISTER(register_class, name, code, size, type) \
|
||||
extern const register_class& name
|
||||
#define DEFINE_REGISTER(register_class, name, code, size, type) \
|
||||
constexpr register_class name { CPURegister(code, size, type) }
|
||||
#define ALIAS_REGISTER(register_class, alias, name) \
|
||||
extern const register_class& alias
|
||||
#endif // defined(ARM64_DEFINE_REG_STATICS)
|
||||
constexpr register_class alias = name
|
||||
|
||||
// No*Reg is used to indicate an unused argument, or an error case. Note that
|
||||
// these all compare equal (using the Is() method). The Register and FPRegister
|
||||
// variants are provided for convenience.
|
||||
INITIALIZE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister);
|
||||
INITIALIZE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister);
|
||||
INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister);
|
||||
DEFINE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister);
|
||||
DEFINE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister);
|
||||
DEFINE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister);
|
||||
|
||||
// v8 compatibility.
|
||||
INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
|
||||
DEFINE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
|
||||
|
||||
#define DEFINE_REGISTERS(N) \
|
||||
INITIALIZE_REGISTER(Register, w##N, N, \
|
||||
kWRegSizeInBits, CPURegister::kRegister); \
|
||||
INITIALIZE_REGISTER(Register, x##N, N, \
|
||||
kXRegSizeInBits, CPURegister::kRegister);
|
||||
#define DEFINE_REGISTERS(N) \
|
||||
DEFINE_REGISTER(Register, w##N, N, kWRegSizeInBits, CPURegister::kRegister); \
|
||||
DEFINE_REGISTER(Register, x##N, N, kXRegSizeInBits, CPURegister::kRegister);
|
||||
GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS)
|
||||
#undef DEFINE_REGISTERS
|
||||
|
||||
INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
|
||||
CPURegister::kRegister);
|
||||
INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
|
||||
CPURegister::kRegister);
|
||||
DEFINE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
|
||||
CPURegister::kRegister);
|
||||
DEFINE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
|
||||
CPURegister::kRegister);
|
||||
|
||||
#define DEFINE_FPREGISTERS(N) \
|
||||
INITIALIZE_REGISTER(FPRegister, s##N, N, \
|
||||
kSRegSizeInBits, CPURegister::kFPRegister); \
|
||||
INITIALIZE_REGISTER(FPRegister, d##N, N, \
|
||||
kDRegSizeInBits, CPURegister::kFPRegister);
|
||||
#define DEFINE_FPREGISTERS(N) \
|
||||
DEFINE_REGISTER(FPRegister, s##N, N, kSRegSizeInBits, \
|
||||
CPURegister::kFPRegister); \
|
||||
DEFINE_REGISTER(FPRegister, d##N, N, kDRegSizeInBits, \
|
||||
CPURegister::kFPRegister);
|
||||
GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
|
||||
#undef DEFINE_FPREGISTERS
|
||||
|
||||
#undef INITIALIZE_REGISTER
|
||||
#undef DEFINE_REGISTER
|
||||
|
||||
// Registers aliases.
|
||||
ALIAS_REGISTER(Register, ip0, x16);
|
||||
@ -566,8 +525,8 @@ class Immediate {
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Operands.
|
||||
const int kSmiShift = kSmiTagSize + kSmiShiftSize;
|
||||
const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
|
||||
constexpr int kSmiShift = kSmiTagSize + kSmiShiftSize;
|
||||
constexpr uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
|
||||
|
||||
// Represents an operand in a machine instruction.
|
||||
class Operand {
|
||||
@ -836,7 +795,7 @@ class Assembler : public AssemblerBase {
|
||||
RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
|
||||
|
||||
// All addresses in the constant pool are the same size as pointers.
|
||||
static const int kSpecialTargetSize = kPointerSize;
|
||||
static constexpr int kSpecialTargetSize = kPointerSize;
|
||||
|
||||
// The sizes of the call sequences emitted by MacroAssembler::Call.
|
||||
// Wherever possible, use MacroAssembler::CallSize instead of these constants,
|
||||
@ -851,8 +810,8 @@ class Assembler : public AssemblerBase {
|
||||
// With relocation:
|
||||
// ldr temp, =target
|
||||
// blr temp
|
||||
static const int kCallSizeWithoutRelocation = 4 * kInstructionSize;
|
||||
static const int kCallSizeWithRelocation = 2 * kInstructionSize;
|
||||
static constexpr int kCallSizeWithoutRelocation = 4 * kInstructionSize;
|
||||
static constexpr int kCallSizeWithRelocation = 2 * kInstructionSize;
|
||||
|
||||
// Size of the generated code in bytes
|
||||
uint64_t SizeOfGeneratedCode() const {
|
||||
@ -884,12 +843,12 @@ class Assembler : public AssemblerBase {
|
||||
return SizeOfCodeGeneratedSince(label) / kInstructionSize;
|
||||
}
|
||||
|
||||
static const int kPatchDebugBreakSlotAddressOffset = 0;
|
||||
static constexpr int kPatchDebugBreakSlotAddressOffset = 0;
|
||||
|
||||
// Number of instructions necessary to be able to later patch it to a call.
|
||||
static const int kDebugBreakSlotInstructions = 5;
|
||||
static const int kDebugBreakSlotLength =
|
||||
kDebugBreakSlotInstructions * kInstructionSize;
|
||||
static constexpr int kDebugBreakSlotInstructions = 5;
|
||||
static constexpr int kDebugBreakSlotLength =
|
||||
kDebugBreakSlotInstructions * kInstructionSize;
|
||||
|
||||
// Prevent contant pool emission until EndBlockConstPool is called.
|
||||
// Call to this function can be nested but must be followed by an equal
|
||||
@ -1847,7 +1806,7 @@ class Assembler : public AssemblerBase {
|
||||
// The maximum code size generated for a veneer. Currently one branch
|
||||
// instruction. This is for code size checking purposes, and can be extended
|
||||
// in the future for example if we decide to add nops between the veneers.
|
||||
static const int kMaxVeneerCodeSize = 1 * kInstructionSize;
|
||||
static constexpr int kMaxVeneerCodeSize = 1 * kInstructionSize;
|
||||
|
||||
void RecordVeneerPool(int location_offset, int size);
|
||||
// Emits veneers for branches that are approaching their maximum range.
|
||||
@ -2000,7 +1959,7 @@ class Assembler : public AssemblerBase {
|
||||
// suitable for fields that take instruction offsets.
|
||||
inline int LinkAndGetInstructionOffsetTo(Label* label);
|
||||
|
||||
static const int kStartOfLabelLinkChain = 0;
|
||||
static constexpr int kStartOfLabelLinkChain = 0;
|
||||
|
||||
// Verify that a label's link chain is intact.
|
||||
void CheckLabelLinkChain(Label const * label);
|
||||
@ -2061,17 +2020,17 @@ class Assembler : public AssemblerBase {
|
||||
// expensive. By default we only check again once a number of instructions
|
||||
// has been generated. That also means that the sizing of the buffers is not
|
||||
// an exact science, and that we rely on some slop to not overrun buffers.
|
||||
static const int kCheckConstPoolInterval = 128;
|
||||
static constexpr int kCheckConstPoolInterval = 128;
|
||||
|
||||
// Distance to first use after a which a pool will be emitted. Pool entries
|
||||
// are accessed with pc relative load therefore this cannot be more than
|
||||
// 1 * MB. Since constant pool emission checks are interval based this value
|
||||
// is an approximation.
|
||||
static const int kApproxMaxDistToConstPool = 64 * KB;
|
||||
static constexpr int kApproxMaxDistToConstPool = 64 * KB;
|
||||
|
||||
// Number of pool entries after which a pool will be emitted. Since constant
|
||||
// pool emission checks are interval based this value is an approximation.
|
||||
static const int kApproxMaxPoolEntryCount = 512;
|
||||
static constexpr int kApproxMaxPoolEntryCount = 512;
|
||||
|
||||
// Emission of the constant pool may be blocked in some code sequences.
|
||||
int const_pool_blocked_nesting_; // Block emission if this is not zero.
|
||||
@ -2082,7 +2041,7 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
// Relocation info generation
|
||||
// Each relocation is encoded as a variable size value
|
||||
static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
RelocInfoWriter reloc_info_writer;
|
||||
// Internal reference positions, required for (potential) patching in
|
||||
// GrowBuffer(); contains only those internal references whose labels
|
||||
@ -2121,7 +2080,7 @@ class Assembler : public AssemblerBase {
|
||||
// not have to check for overflow. The same is true for writes of large
|
||||
// relocation info entries, and debug strings encoded in the instruction
|
||||
// stream.
|
||||
static const int kGap = 128;
|
||||
static constexpr int kGap = 128;
|
||||
|
||||
public:
|
||||
class FarBranchInfo {
|
||||
@ -2151,13 +2110,13 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
// We generate a veneer for a branch if we reach within this distance of the
|
||||
// limit of the range.
|
||||
static const int kVeneerDistanceMargin = 1 * KB;
|
||||
static constexpr int kVeneerDistanceMargin = 1 * KB;
|
||||
// The factor of 2 is a finger in the air guess. With a default margin of
|
||||
// 1KB, that leaves us an addional 256 instructions to avoid generating a
|
||||
// protective branch.
|
||||
static const int kVeneerNoProtectionFactor = 2;
|
||||
static const int kVeneerDistanceCheckMargin =
|
||||
kVeneerNoProtectionFactor * kVeneerDistanceMargin;
|
||||
static constexpr int kVeneerNoProtectionFactor = 2;
|
||||
static constexpr int kVeneerDistanceCheckMargin =
|
||||
kVeneerNoProtectionFactor * kVeneerDistanceMargin;
|
||||
int unresolved_branches_first_limit() const {
|
||||
DCHECK(!unresolved_branches_.empty());
|
||||
return unresolved_branches_.begin()->first;
|
||||
@ -2221,8 +2180,8 @@ class PatchingAssembler : public Assembler {
|
||||
}
|
||||
|
||||
// See definition of PatchAdrFar() for details.
|
||||
static const int kAdrFarPatchableNNops = 2;
|
||||
static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 2;
|
||||
static constexpr int kAdrFarPatchableNNops = 2;
|
||||
static constexpr int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 2;
|
||||
void PatchAdrFar(int64_t target_offset);
|
||||
};
|
||||
|
||||
|
@ -116,7 +116,7 @@ struct Register {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kNumRegisters = Code::kAfterLast;
|
||||
|
||||
static Register from_code(int code) {
|
||||
DCHECK(code >= 0);
|
||||
@ -141,14 +141,13 @@ struct Register {
|
||||
int reg_code;
|
||||
};
|
||||
|
||||
#define DEFINE_REGISTER(R) constexpr Register R = {Register::kCode_##R};
|
||||
GENERAL_REGISTERS(DEFINE_REGISTER)
|
||||
#undef DEFINE_REGISTER
|
||||
constexpr Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
|
||||
GENERAL_REGISTERS(DECLARE_REGISTER)
|
||||
#undef DECLARE_REGISTER
|
||||
const Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
static const bool kSimpleFPAliasing = true;
|
||||
static const bool kSimdMaskRegisters = false;
|
||||
constexpr bool kSimpleFPAliasing = true;
|
||||
constexpr bool kSimdMaskRegisters = false;
|
||||
|
||||
struct XMMRegister {
|
||||
enum Code {
|
||||
@ -159,7 +158,7 @@ struct XMMRegister {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kMaxNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kMaxNumRegisters = Code::kAfterLast;
|
||||
|
||||
static XMMRegister from_code(int code) {
|
||||
XMMRegister result = {code};
|
||||
@ -184,11 +183,11 @@ typedef XMMRegister DoubleRegister;
|
||||
|
||||
typedef XMMRegister Simd128Register;
|
||||
|
||||
#define DECLARE_REGISTER(R) \
|
||||
const DoubleRegister R = {DoubleRegister::kCode_##R};
|
||||
DOUBLE_REGISTERS(DECLARE_REGISTER)
|
||||
#undef DECLARE_REGISTER
|
||||
const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
|
||||
#define DEFINE_REGISTER(R) \
|
||||
constexpr DoubleRegister R = {DoubleRegister::kCode_##R};
|
||||
DOUBLE_REGISTERS(DEFINE_REGISTER)
|
||||
#undef DEFINE_REGISTER
|
||||
constexpr DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
|
||||
|
||||
enum Condition {
|
||||
// any value < 0 is considered no_condition
|
||||
@ -469,7 +468,7 @@ class Assembler : public AssemblerBase {
|
||||
// (There is a 15 byte limit on ia32 instruction length that rules out some
|
||||
// otherwise valid instructions.)
|
||||
// This allows for a single, fast space check per instruction.
|
||||
static const int kGap = 32;
|
||||
static constexpr int kGap = 32;
|
||||
|
||||
public:
|
||||
// Create an assembler. Instructions and relocation information are emitted
|
||||
@ -521,35 +520,34 @@ class Assembler : public AssemblerBase {
|
||||
Isolate* isolate, Address pc, Address target,
|
||||
RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
|
||||
|
||||
static const int kSpecialTargetSize = kPointerSize;
|
||||
static constexpr int kSpecialTargetSize = kPointerSize;
|
||||
|
||||
// Distance between the address of the code target in the call instruction
|
||||
// and the return address
|
||||
static const int kCallTargetAddressOffset = kPointerSize;
|
||||
static constexpr int kCallTargetAddressOffset = kPointerSize;
|
||||
|
||||
static const int kCallInstructionLength = 5;
|
||||
static constexpr int kCallInstructionLength = 5;
|
||||
|
||||
// The debug break slot must be able to contain a call instruction.
|
||||
static const int kDebugBreakSlotLength = kCallInstructionLength;
|
||||
static constexpr int kDebugBreakSlotLength = kCallInstructionLength;
|
||||
|
||||
// Distance between start of patched debug break slot and the emitted address
|
||||
// to jump to.
|
||||
static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32.
|
||||
static constexpr int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32.
|
||||
|
||||
// One byte opcode for test al, 0xXX.
|
||||
static const byte kTestAlByte = 0xA8;
|
||||
static constexpr byte kTestAlByte = 0xA8;
|
||||
// One byte opcode for nop.
|
||||
static const byte kNopByte = 0x90;
|
||||
static constexpr byte kNopByte = 0x90;
|
||||
|
||||
// One byte opcode for a short unconditional jump.
|
||||
static const byte kJmpShortOpcode = 0xEB;
|
||||
static constexpr byte kJmpShortOpcode = 0xEB;
|
||||
// One byte prefix for a short conditional jump.
|
||||
static const byte kJccShortPrefix = 0x70;
|
||||
static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
|
||||
static const byte kJcShortOpcode = kJccShortPrefix | carry;
|
||||
static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
|
||||
static const byte kJzShortOpcode = kJccShortPrefix | zero;
|
||||
|
||||
static constexpr byte kJccShortPrefix = 0x70;
|
||||
static constexpr byte kJncShortOpcode = kJccShortPrefix | not_carry;
|
||||
static constexpr byte kJcShortOpcode = kJccShortPrefix | carry;
|
||||
static constexpr byte kJnzShortOpcode = kJccShortPrefix | not_zero;
|
||||
static constexpr byte kJzShortOpcode = kJccShortPrefix | zero;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Code generation
|
||||
@ -1466,7 +1464,7 @@ class Assembler : public AssemblerBase {
|
||||
}
|
||||
|
||||
// Avoid overflows for displacements etc.
|
||||
static const int kMaximalBufferSize = 512*MB;
|
||||
static constexpr int kMaximalBufferSize = 512 * MB;
|
||||
|
||||
byte byte_at(int pos) { return buffer_[pos]; }
|
||||
void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
|
||||
|
@ -97,7 +97,7 @@ namespace internal {
|
||||
// Implementation of Register and FPURegister.
|
||||
|
||||
struct Register {
|
||||
static const int kCpRegister = 23; // cp (s7) is the 23rd register.
|
||||
static constexpr int kCpRegister = 23; // cp (s7) is the 23rd register.
|
||||
|
||||
enum Code {
|
||||
#define REGISTER_CODE(R) kCode_##R,
|
||||
@ -107,24 +107,23 @@ struct Register {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kNumRegisters = Code::kAfterLast;
|
||||
|
||||
#if defined(V8_TARGET_LITTLE_ENDIAN)
|
||||
static const int kMantissaOffset = 0;
|
||||
static const int kExponentOffset = 4;
|
||||
static constexpr int kMantissaOffset = 0;
|
||||
static constexpr int kExponentOffset = 4;
|
||||
#elif defined(V8_TARGET_BIG_ENDIAN)
|
||||
static const int kMantissaOffset = 4;
|
||||
static const int kExponentOffset = 0;
|
||||
static constexpr int kMantissaOffset = 4;
|
||||
static constexpr int kExponentOffset = 0;
|
||||
#else
|
||||
#error Unknown endianness
|
||||
#endif
|
||||
|
||||
|
||||
static Register from_code(int code) {
|
||||
DCHECK(code >= 0);
|
||||
DCHECK(code < kNumRegisters);
|
||||
Register r = {code};
|
||||
return r;
|
||||
DCHECK_LE(0, code);
|
||||
DCHECK_GT(kNumRegisters, code);
|
||||
return Register{code};
|
||||
}
|
||||
bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
|
||||
bool is(Register reg) const { return reg_code == reg.reg_code; }
|
||||
@ -144,18 +143,17 @@ struct Register {
|
||||
// s7: context register
|
||||
// s3: lithium scratch
|
||||
// s4: lithium scratch2
|
||||
#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
|
||||
#define DECLARE_REGISTER(R) constexpr Register R = {Register::kCode_##R};
|
||||
GENERAL_REGISTERS(DECLARE_REGISTER)
|
||||
#undef DECLARE_REGISTER
|
||||
const Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
constexpr Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
int ToNumber(Register reg);
|
||||
|
||||
Register ToRegister(int num);
|
||||
|
||||
static const bool kSimpleFPAliasing = true;
|
||||
static const bool kSimdMaskRegisters = false;
|
||||
constexpr bool kSimpleFPAliasing = true;
|
||||
constexpr bool kSimdMaskRegisters = false;
|
||||
|
||||
// Coprocessor register.
|
||||
struct FPURegister {
|
||||
@ -167,7 +165,7 @@ struct FPURegister {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kMaxNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kMaxNumRegisters = Code::kAfterLast;
|
||||
|
||||
inline static int NumRegisters();
|
||||
|
||||
@ -236,54 +234,51 @@ typedef FPURegister DoubleRegister;
|
||||
// TODO(mips) Define SIMD registers.
|
||||
typedef FPURegister Simd128Register;
|
||||
|
||||
const DoubleRegister no_freg = {-1};
|
||||
constexpr DoubleRegister no_freg = {-1};
|
||||
|
||||
const DoubleRegister f0 = {0}; // Return value in hard float mode.
|
||||
const DoubleRegister f1 = {1};
|
||||
const DoubleRegister f2 = {2};
|
||||
const DoubleRegister f3 = {3};
|
||||
const DoubleRegister f4 = {4};
|
||||
const DoubleRegister f5 = {5};
|
||||
const DoubleRegister f6 = {6};
|
||||
const DoubleRegister f7 = {7};
|
||||
const DoubleRegister f8 = {8};
|
||||
const DoubleRegister f9 = {9};
|
||||
const DoubleRegister f10 = {10};
|
||||
const DoubleRegister f11 = {11};
|
||||
const DoubleRegister f12 = {12}; // Arg 0 in hard float mode.
|
||||
const DoubleRegister f13 = {13};
|
||||
const DoubleRegister f14 = {14}; // Arg 1 in hard float mode.
|
||||
const DoubleRegister f15 = {15};
|
||||
const DoubleRegister f16 = {16};
|
||||
const DoubleRegister f17 = {17};
|
||||
const DoubleRegister f18 = {18};
|
||||
const DoubleRegister f19 = {19};
|
||||
const DoubleRegister f20 = {20};
|
||||
const DoubleRegister f21 = {21};
|
||||
const DoubleRegister f22 = {22};
|
||||
const DoubleRegister f23 = {23};
|
||||
const DoubleRegister f24 = {24};
|
||||
const DoubleRegister f25 = {25};
|
||||
const DoubleRegister f26 = {26};
|
||||
const DoubleRegister f27 = {27};
|
||||
const DoubleRegister f28 = {28};
|
||||
const DoubleRegister f29 = {29};
|
||||
const DoubleRegister f30 = {30};
|
||||
const DoubleRegister f31 = {31};
|
||||
constexpr DoubleRegister f0 = {0}; // Return value in hard float mode.
|
||||
constexpr DoubleRegister f1 = {1};
|
||||
constexpr DoubleRegister f2 = {2};
|
||||
constexpr DoubleRegister f3 = {3};
|
||||
constexpr DoubleRegister f4 = {4};
|
||||
constexpr DoubleRegister f5 = {5};
|
||||
constexpr DoubleRegister f6 = {6};
|
||||
constexpr DoubleRegister f7 = {7};
|
||||
constexpr DoubleRegister f8 = {8};
|
||||
constexpr DoubleRegister f9 = {9};
|
||||
constexpr DoubleRegister f10 = {10};
|
||||
constexpr DoubleRegister f11 = {11};
|
||||
constexpr DoubleRegister f12 = {12}; // Arg 0 in hard float mode.
|
||||
constexpr DoubleRegister f13 = {13};
|
||||
constexpr DoubleRegister f14 = {14}; // Arg 1 in hard float mode.
|
||||
constexpr DoubleRegister f15 = {15};
|
||||
constexpr DoubleRegister f16 = {16};
|
||||
constexpr DoubleRegister f17 = {17};
|
||||
constexpr DoubleRegister f18 = {18};
|
||||
constexpr DoubleRegister f19 = {19};
|
||||
constexpr DoubleRegister f20 = {20};
|
||||
constexpr DoubleRegister f21 = {21};
|
||||
constexpr DoubleRegister f22 = {22};
|
||||
constexpr DoubleRegister f23 = {23};
|
||||
constexpr DoubleRegister f24 = {24};
|
||||
constexpr DoubleRegister f25 = {25};
|
||||
constexpr DoubleRegister f26 = {26};
|
||||
constexpr DoubleRegister f27 = {27};
|
||||
constexpr DoubleRegister f28 = {28};
|
||||
constexpr DoubleRegister f29 = {29};
|
||||
constexpr DoubleRegister f30 = {30};
|
||||
constexpr DoubleRegister f31 = {31};
|
||||
|
||||
// Register aliases.
|
||||
// cp is assumed to be a callee saved register.
|
||||
// Defined using #define instead of "static const Register&" because Clang
|
||||
// complains otherwise when a compilation unit that includes this header
|
||||
// doesn't use the variables.
|
||||
#define kRootRegister s6
|
||||
#define cp s7
|
||||
#define kLithiumScratchReg s3
|
||||
#define kLithiumScratchReg2 s4
|
||||
#define kLithiumScratchDouble f30
|
||||
#define kDoubleRegZero f28
|
||||
constexpr Register kRootRegister = s6;
|
||||
constexpr Register cp = s7;
|
||||
constexpr Register kLithiumScratchReg = s3;
|
||||
constexpr Register kLithiumScratchReg2 = s4;
|
||||
constexpr DoubleRegister kLithiumScratchDouble = f30;
|
||||
constexpr DoubleRegister kDoubleRegZero = f28;
|
||||
// Used on mips32r6 for compare operations.
|
||||
#define kDoubleCompareReg f26
|
||||
constexpr DoubleRegister kDoubleCompareReg = f26;
|
||||
|
||||
// FPU (coprocessor 1) control registers.
|
||||
// Currently only FCSR (#31) is implemented.
|
||||
@ -306,8 +301,8 @@ struct FPUControlRegister {
|
||||
int reg_code;
|
||||
};
|
||||
|
||||
const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
|
||||
const FPUControlRegister FCSR = { kFCSRRegister };
|
||||
constexpr FPUControlRegister no_fpucreg = {kInvalidFPUControlRegister};
|
||||
constexpr FPUControlRegister FCSR = {kFCSRRegister};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Machine instruction Operands.
|
||||
@ -502,10 +497,10 @@ class Assembler : public AssemblerBase {
|
||||
RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
|
||||
|
||||
// Size of an instruction.
|
||||
static const int kInstrSize = sizeof(Instr);
|
||||
static constexpr int kInstrSize = sizeof(Instr);
|
||||
|
||||
// Difference between address of current opcode and target address offset.
|
||||
static const int kBranchPCOffset = 4;
|
||||
static constexpr int kBranchPCOffset = 4;
|
||||
|
||||
// Here we are patching the address in the LUI/ORI instruction pair.
|
||||
// These values are used in the serialization process and must be zero for
|
||||
@ -513,48 +508,48 @@ class Assembler : public AssemblerBase {
|
||||
// are split across two consecutive instructions and don't exist separately
|
||||
// in the code, so the serializer should not step forwards in memory after
|
||||
// a target is resolved and written.
|
||||
static const int kSpecialTargetSize = 0;
|
||||
static constexpr int kSpecialTargetSize = 0;
|
||||
|
||||
// Number of consecutive instructions used to store 32bit constant. This
|
||||
// constant is used in RelocInfo::target_address_address() function to tell
|
||||
// serializer address of the instruction that follows LUI/ORI instruction
|
||||
// pair.
|
||||
static const int kInstructionsFor32BitConstant = 2;
|
||||
static constexpr int kInstructionsFor32BitConstant = 2;
|
||||
|
||||
// Distance between the instruction referring to the address of the call
|
||||
// target and the return address.
|
||||
#ifdef _MIPS_ARCH_MIPS32R6
|
||||
static const int kCallTargetAddressOffset = 3 * kInstrSize;
|
||||
static constexpr int kCallTargetAddressOffset = 3 * kInstrSize;
|
||||
#else
|
||||
static const int kCallTargetAddressOffset = 4 * kInstrSize;
|
||||
static constexpr int kCallTargetAddressOffset = 4 * kInstrSize;
|
||||
#endif
|
||||
|
||||
// Distance between start of patched debug break slot and the emitted address
|
||||
// to jump to.
|
||||
static const int kPatchDebugBreakSlotAddressOffset = 4 * kInstrSize;
|
||||
static constexpr int kPatchDebugBreakSlotAddressOffset = 4 * kInstrSize;
|
||||
|
||||
// Difference between address of current opcode and value read from pc
|
||||
// register.
|
||||
static const int kPcLoadDelta = 4;
|
||||
static constexpr int kPcLoadDelta = 4;
|
||||
|
||||
#ifdef _MIPS_ARCH_MIPS32R6
|
||||
static const int kDebugBreakSlotInstructions = 3;
|
||||
static constexpr int kDebugBreakSlotInstructions = 3;
|
||||
#else
|
||||
static const int kDebugBreakSlotInstructions = 4;
|
||||
static constexpr int kDebugBreakSlotInstructions = 4;
|
||||
#endif
|
||||
static const int kDebugBreakSlotLength =
|
||||
static constexpr int kDebugBreakSlotLength =
|
||||
kDebugBreakSlotInstructions * kInstrSize;
|
||||
|
||||
// Max offset for instructions with 16-bit offset field
|
||||
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
|
||||
static constexpr int kMaxBranchOffset = (1 << (18 - 1)) - 1;
|
||||
|
||||
// Max offset for compact branch instructions with 26-bit offset field
|
||||
static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1;
|
||||
static constexpr int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1;
|
||||
|
||||
#ifdef _MIPS_ARCH_MIPS32R6
|
||||
static const int kTrampolineSlotsSize = 2 * kInstrSize;
|
||||
static constexpr int kTrampolineSlotsSize = 2 * kInstrSize;
|
||||
#else
|
||||
static const int kTrampolineSlotsSize = 4 * kInstrSize;
|
||||
static constexpr int kTrampolineSlotsSize = 4 * kInstrSize;
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@ -1263,21 +1258,21 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
// Buffer size and constant pool distance are checked together at regular
|
||||
// intervals of kBufferCheckInterval emitted bytes.
|
||||
static const int kBufferCheckInterval = 1*KB/2;
|
||||
static constexpr int kBufferCheckInterval = 1 * KB / 2;
|
||||
|
||||
// Code generation.
|
||||
// The relocation writer's position is at least kGap bytes below the end of
|
||||
// the generated instructions. This is so that multi-instruction sequences do
|
||||
// not have to check for overflow. The same is true for writes of large
|
||||
// relocation info entries.
|
||||
static const int kGap = 32;
|
||||
|
||||
static constexpr int kGap = 32;
|
||||
|
||||
// Repeated checking whether the trampoline pool should be emitted is rather
|
||||
// expensive. By default we only check again once a number of instructions
|
||||
// has been generated.
|
||||
static const int kCheckConstIntervalInst = 32;
|
||||
static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
|
||||
static constexpr int kCheckConstIntervalInst = 32;
|
||||
static constexpr int kCheckConstInterval =
|
||||
kCheckConstIntervalInst * kInstrSize;
|
||||
|
||||
int next_buffer_check_; // pc offset of next buffer check.
|
||||
|
||||
@ -1293,7 +1288,7 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
// Relocation information generation.
|
||||
// Each relocation is encoded as a variable size value.
|
||||
static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
RelocInfoWriter reloc_info_writer;
|
||||
|
||||
// The bound position, before this we cannot do instruction elimination.
|
||||
@ -1447,7 +1442,7 @@ class Assembler : public AssemblerBase {
|
||||
// branch instruction generation, where we use jump instructions rather
|
||||
// than regular branch instructions.
|
||||
bool trampoline_emitted_;
|
||||
static const int kInvalidSlotPos = -1;
|
||||
static constexpr int kInvalidSlotPos = -1;
|
||||
|
||||
// Internal reference positions, required for unbounded internal reference
|
||||
// labels.
|
||||
|
@ -13,20 +13,20 @@ namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
// Give alias names to registers for calling conventions.
|
||||
const Register kReturnRegister0 = {Register::kCode_v0};
|
||||
const Register kReturnRegister1 = {Register::kCode_v1};
|
||||
const Register kReturnRegister2 = {Register::kCode_a0};
|
||||
const Register kJSFunctionRegister = {Register::kCode_a1};
|
||||
const Register kContextRegister = {Register::kCpRegister};
|
||||
const Register kAllocateSizeRegister = {Register::kCode_a0};
|
||||
const Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
|
||||
const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t4};
|
||||
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t5};
|
||||
const Register kInterpreterDispatchTableRegister = {Register::kCode_t6};
|
||||
const Register kJavaScriptCallArgCountRegister = {Register::kCode_a0};
|
||||
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_a3};
|
||||
const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
|
||||
const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
|
||||
constexpr Register kReturnRegister0 = {Register::kCode_v0};
|
||||
constexpr Register kReturnRegister1 = {Register::kCode_v1};
|
||||
constexpr Register kReturnRegister2 = {Register::kCode_a0};
|
||||
constexpr Register kJSFunctionRegister = {Register::kCode_a1};
|
||||
constexpr Register kContextRegister = {Register::kCpRegister};
|
||||
constexpr Register kAllocateSizeRegister = {Register::kCode_a0};
|
||||
constexpr Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
|
||||
constexpr Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t4};
|
||||
constexpr Register kInterpreterBytecodeArrayRegister = {Register::kCode_t5};
|
||||
constexpr Register kInterpreterDispatchTableRegister = {Register::kCode_t6};
|
||||
constexpr Register kJavaScriptCallArgCountRegister = {Register::kCode_a0};
|
||||
constexpr Register kJavaScriptCallNewTargetRegister = {Register::kCode_a3};
|
||||
constexpr Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
|
||||
constexpr Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
|
||||
|
||||
// Forward declaration.
|
||||
class JumpTarget;
|
||||
@ -210,9 +210,9 @@ class MacroAssembler: public Assembler {
|
||||
|
||||
// Number of instructions needed for calculation of switch table entry address
|
||||
#ifdef _MIPS_ARCH_MIPS32R6
|
||||
static const int kSwitchTablePrologueSize = 5;
|
||||
static constexpr int kSwitchTablePrologueSize = 5;
|
||||
#else
|
||||
static const int kSwitchTablePrologueSize = 10;
|
||||
static constexpr int kSwitchTablePrologueSize = 10;
|
||||
#endif
|
||||
// GetLabelFunction must be lambda '[](size_t index) -> Label*' or a
|
||||
// functor/function with 'Label *func(size_t index)' declaration.
|
||||
@ -1632,8 +1632,8 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
|
||||
|
||||
template<typename Field>
|
||||
void DecodeFieldToSmi(Register dst, Register src) {
|
||||
static const int shift = Field::kShift;
|
||||
static const int mask = Field::kMask >> shift << kSmiTagSize;
|
||||
constexpr int shift = Field::kShift;
|
||||
constexpr int mask = Field::kMask >> shift << kSmiTagSize;
|
||||
STATIC_ASSERT((mask & (0x80000000u >> (kSmiTagSize - 1))) == 0);
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
if (shift < kSmiTagSize) {
|
||||
|
@ -97,14 +97,14 @@ namespace internal {
|
||||
// Implementation of Register and FPURegister.
|
||||
|
||||
struct Register {
|
||||
static const int kCpRegister = 23; // cp (s7) is the 23rd register.
|
||||
static constexpr int kCpRegister = 23; // cp (s7) is the 23rd register.
|
||||
|
||||
#if defined(V8_TARGET_LITTLE_ENDIAN)
|
||||
static const int kMantissaOffset = 0;
|
||||
static const int kExponentOffset = 4;
|
||||
static constexpr int kMantissaOffset = 0;
|
||||
static constexpr int kExponentOffset = 4;
|
||||
#elif defined(V8_TARGET_BIG_ENDIAN)
|
||||
static const int kMantissaOffset = 4;
|
||||
static const int kExponentOffset = 0;
|
||||
static constexpr int kMantissaOffset = 4;
|
||||
static constexpr int kExponentOffset = 0;
|
||||
#else
|
||||
#error Unknown endianness
|
||||
#endif
|
||||
@ -117,7 +117,7 @@ struct Register {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kNumRegisters = Code::kAfterLast;
|
||||
|
||||
static Register from_code(int code) {
|
||||
DCHECK(code >= 0);
|
||||
@ -132,10 +132,7 @@ struct Register {
|
||||
DCHECK(is_valid());
|
||||
return reg_code;
|
||||
}
|
||||
int bit() const {
|
||||
DCHECK(is_valid());
|
||||
return 1 << reg_code;
|
||||
}
|
||||
constexpr int bit() const { return DCHECK(is_valid()), 1 << reg_code; }
|
||||
|
||||
// Unfortunately we can't make this private in a struct.
|
||||
int reg_code;
|
||||
@ -144,18 +141,17 @@ struct Register {
|
||||
// s7: context register
|
||||
// s3: lithium scratch
|
||||
// s4: lithium scratch2
|
||||
#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
|
||||
#define DECLARE_REGISTER(R) constexpr Register R = {Register::kCode_##R};
|
||||
GENERAL_REGISTERS(DECLARE_REGISTER)
|
||||
#undef DECLARE_REGISTER
|
||||
const Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
constexpr Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
int ToNumber(Register reg);
|
||||
|
||||
Register ToRegister(int num);
|
||||
|
||||
static const bool kSimpleFPAliasing = true;
|
||||
static const bool kSimdMaskRegisters = false;
|
||||
constexpr bool kSimpleFPAliasing = true;
|
||||
constexpr bool kSimdMaskRegisters = false;
|
||||
|
||||
// Coprocessor register.
|
||||
struct FPURegister {
|
||||
@ -167,7 +163,7 @@ struct FPURegister {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kMaxNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kMaxNumRegisters = Code::kAfterLast;
|
||||
|
||||
inline static int NumRegisters();
|
||||
|
||||
@ -200,10 +196,7 @@ struct FPURegister {
|
||||
DCHECK(is_valid());
|
||||
return reg_code;
|
||||
}
|
||||
int bit() const {
|
||||
DCHECK(is_valid());
|
||||
return 1 << reg_code;
|
||||
}
|
||||
constexpr int bit() const { return DCHECK(is_valid()), 1 << reg_code; }
|
||||
|
||||
static FPURegister from_code(int code) {
|
||||
FPURegister r = {code};
|
||||
@ -238,55 +231,52 @@ typedef FPURegister DoubleRegister;
|
||||
// TODO(mips64) Define SIMD registers.
|
||||
typedef FPURegister Simd128Register;
|
||||
|
||||
const DoubleRegister no_freg = {-1};
|
||||
constexpr DoubleRegister no_freg = {-1};
|
||||
|
||||
const DoubleRegister f0 = {0}; // Return value in hard float mode.
|
||||
const DoubleRegister f1 = {1};
|
||||
const DoubleRegister f2 = {2};
|
||||
const DoubleRegister f3 = {3};
|
||||
const DoubleRegister f4 = {4};
|
||||
const DoubleRegister f5 = {5};
|
||||
const DoubleRegister f6 = {6};
|
||||
const DoubleRegister f7 = {7};
|
||||
const DoubleRegister f8 = {8};
|
||||
const DoubleRegister f9 = {9};
|
||||
const DoubleRegister f10 = {10};
|
||||
const DoubleRegister f11 = {11};
|
||||
const DoubleRegister f12 = {12}; // Arg 0 in hard float mode.
|
||||
const DoubleRegister f13 = {13};
|
||||
const DoubleRegister f14 = {14}; // Arg 1 in hard float mode.
|
||||
const DoubleRegister f15 = {15};
|
||||
const DoubleRegister f16 = {16};
|
||||
const DoubleRegister f17 = {17};
|
||||
const DoubleRegister f18 = {18};
|
||||
const DoubleRegister f19 = {19};
|
||||
const DoubleRegister f20 = {20};
|
||||
const DoubleRegister f21 = {21};
|
||||
const DoubleRegister f22 = {22};
|
||||
const DoubleRegister f23 = {23};
|
||||
const DoubleRegister f24 = {24};
|
||||
const DoubleRegister f25 = {25};
|
||||
const DoubleRegister f26 = {26};
|
||||
const DoubleRegister f27 = {27};
|
||||
const DoubleRegister f28 = {28};
|
||||
const DoubleRegister f29 = {29};
|
||||
const DoubleRegister f30 = {30};
|
||||
const DoubleRegister f31 = {31};
|
||||
constexpr DoubleRegister f0 = {0}; // Return value in hard float mode.
|
||||
constexpr DoubleRegister f1 = {1};
|
||||
constexpr DoubleRegister f2 = {2};
|
||||
constexpr DoubleRegister f3 = {3};
|
||||
constexpr DoubleRegister f4 = {4};
|
||||
constexpr DoubleRegister f5 = {5};
|
||||
constexpr DoubleRegister f6 = {6};
|
||||
constexpr DoubleRegister f7 = {7};
|
||||
constexpr DoubleRegister f8 = {8};
|
||||
constexpr DoubleRegister f9 = {9};
|
||||
constexpr DoubleRegister f10 = {10};
|
||||
constexpr DoubleRegister f11 = {11};
|
||||
constexpr DoubleRegister f12 = {12}; // Arg 0 in hard float mode.
|
||||
constexpr DoubleRegister f13 = {13};
|
||||
constexpr DoubleRegister f14 = {14}; // Arg 1 in hard float mode.
|
||||
constexpr DoubleRegister f15 = {15};
|
||||
constexpr DoubleRegister f16 = {16};
|
||||
constexpr DoubleRegister f17 = {17};
|
||||
constexpr DoubleRegister f18 = {18};
|
||||
constexpr DoubleRegister f19 = {19};
|
||||
constexpr DoubleRegister f20 = {20};
|
||||
constexpr DoubleRegister f21 = {21};
|
||||
constexpr DoubleRegister f22 = {22};
|
||||
constexpr DoubleRegister f23 = {23};
|
||||
constexpr DoubleRegister f24 = {24};
|
||||
constexpr DoubleRegister f25 = {25};
|
||||
constexpr DoubleRegister f26 = {26};
|
||||
constexpr DoubleRegister f27 = {27};
|
||||
constexpr DoubleRegister f28 = {28};
|
||||
constexpr DoubleRegister f29 = {29};
|
||||
constexpr DoubleRegister f30 = {30};
|
||||
constexpr DoubleRegister f31 = {31};
|
||||
|
||||
// Register aliases.
|
||||
// cp is assumed to be a callee saved register.
|
||||
// Defined using #define instead of "static const Register&" because Clang
|
||||
// complains otherwise when a compilation unit that includes this header
|
||||
// doesn't use the variables.
|
||||
#define kRootRegister s6
|
||||
#define cp s7
|
||||
#define kLithiumScratchReg s3
|
||||
#define kLithiumScratchReg2 s4
|
||||
#define kLithiumScratchDouble f30
|
||||
#define kDoubleRegZero f28
|
||||
constexpr Register kRootRegister = s6;
|
||||
constexpr Register cp = s7;
|
||||
constexpr Register kLithiumScratchReg = s3;
|
||||
constexpr Register kLithiumScratchReg2 = s4;
|
||||
constexpr DoubleRegister kLithiumScratchDouble = f30;
|
||||
constexpr DoubleRegister kDoubleRegZero = f28;
|
||||
// Used on mips64r6 for compare operations.
|
||||
// We use the last non-callee saved odd register for N64 ABI
|
||||
#define kDoubleCompareReg f23
|
||||
constexpr DoubleRegister kDoubleCompareReg = f23;
|
||||
|
||||
// FPU (coprocessor 1) control registers.
|
||||
// Currently only FCSR (#31) is implemented.
|
||||
@ -297,10 +287,7 @@ struct FPUControlRegister {
|
||||
DCHECK(is_valid());
|
||||
return reg_code;
|
||||
}
|
||||
int bit() const {
|
||||
DCHECK(is_valid());
|
||||
return 1 << reg_code;
|
||||
}
|
||||
constexpr int bit() const { return DCHECK(is_valid()), 1 << reg_code; }
|
||||
void setcode(int f) {
|
||||
reg_code = f;
|
||||
DCHECK(is_valid());
|
||||
@ -309,13 +296,13 @@ struct FPUControlRegister {
|
||||
int reg_code;
|
||||
};
|
||||
|
||||
const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
|
||||
const FPUControlRegister FCSR = { kFCSRRegister };
|
||||
constexpr FPUControlRegister no_fpucreg = {kInvalidFPUControlRegister};
|
||||
constexpr FPUControlRegister FCSR = {kFCSRRegister};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Machine instruction Operands.
|
||||
const int kSmiShift = kSmiTagSize + kSmiShiftSize;
|
||||
const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
|
||||
constexpr int kSmiShift = kSmiTagSize + kSmiShiftSize;
|
||||
constexpr uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
|
||||
// Class Operand represents a shifter operand in data processing instructions.
|
||||
class Operand BASE_EMBEDDED {
|
||||
public:
|
||||
@ -509,10 +496,10 @@ class Assembler : public AssemblerBase {
|
||||
RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
|
||||
|
||||
// Size of an instruction.
|
||||
static const int kInstrSize = sizeof(Instr);
|
||||
static constexpr int kInstrSize = sizeof(Instr);
|
||||
|
||||
// Difference between address of current opcode and target address offset.
|
||||
static const int kBranchPCOffset = 4;
|
||||
static constexpr int kBranchPCOffset = 4;
|
||||
|
||||
// Here we are patching the address in the LUI/ORI instruction pair.
|
||||
// These values are used in the serialization process and must be zero for
|
||||
@ -520,46 +507,46 @@ class Assembler : public AssemblerBase {
|
||||
// are split across two consecutive instructions and don't exist separately
|
||||
// in the code, so the serializer should not step forwards in memory after
|
||||
// a target is resolved and written.
|
||||
static const int kSpecialTargetSize = 0;
|
||||
static constexpr int kSpecialTargetSize = 0;
|
||||
|
||||
// Number of consecutive instructions used to store 32bit/64bit constant.
|
||||
// This constant was used in RelocInfo::target_address_address() function
|
||||
// to tell serializer address of the instruction that follows
|
||||
// LUI/ORI instruction pair.
|
||||
static const int kInstructionsFor32BitConstant = 2;
|
||||
static const int kInstructionsFor64BitConstant = 4;
|
||||
static constexpr int kInstructionsFor32BitConstant = 2;
|
||||
static constexpr int kInstructionsFor64BitConstant = 4;
|
||||
|
||||
// Distance between the instruction referring to the address of the call
|
||||
// target and the return address.
|
||||
#ifdef _MIPS_ARCH_MIPS64R6
|
||||
static const int kCallTargetAddressOffset = 5 * kInstrSize;
|
||||
static constexpr int kCallTargetAddressOffset = 5 * kInstrSize;
|
||||
#else
|
||||
static const int kCallTargetAddressOffset = 6 * kInstrSize;
|
||||
static constexpr int kCallTargetAddressOffset = 6 * kInstrSize;
|
||||
#endif
|
||||
|
||||
// Distance between start of patched debug break slot and the emitted address
|
||||
// to jump to.
|
||||
static const int kPatchDebugBreakSlotAddressOffset = 6 * kInstrSize;
|
||||
static constexpr int kPatchDebugBreakSlotAddressOffset = 6 * kInstrSize;
|
||||
|
||||
// Difference between address of current opcode and value read from pc
|
||||
// register.
|
||||
static const int kPcLoadDelta = 4;
|
||||
static constexpr int kPcLoadDelta = 4;
|
||||
|
||||
#ifdef _MIPS_ARCH_MIPS64R6
|
||||
static const int kDebugBreakSlotInstructions = 5;
|
||||
static constexpr int kDebugBreakSlotInstructions = 5;
|
||||
#else
|
||||
static const int kDebugBreakSlotInstructions = 6;
|
||||
static constexpr int kDebugBreakSlotInstructions = 6;
|
||||
#endif
|
||||
static const int kDebugBreakSlotLength =
|
||||
static constexpr int kDebugBreakSlotLength =
|
||||
kDebugBreakSlotInstructions * kInstrSize;
|
||||
|
||||
// Max offset for instructions with 16-bit offset field
|
||||
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
|
||||
static constexpr int kMaxBranchOffset = (1 << (18 - 1)) - 1;
|
||||
|
||||
// Max offset for compact branch instructions with 26-bit offset field
|
||||
static const int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1;
|
||||
static constexpr int kMaxCompactBranchOffset = (1 << (28 - 1)) - 1;
|
||||
|
||||
static const int kTrampolineSlotsSize = 2 * kInstrSize;
|
||||
static constexpr int kTrampolineSlotsSize = 2 * kInstrSize;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Code generation.
|
||||
@ -1313,21 +1300,21 @@ class Assembler : public AssemblerBase {
|
||||
private:
|
||||
// Buffer size and constant pool distance are checked together at regular
|
||||
// intervals of kBufferCheckInterval emitted bytes.
|
||||
static const int kBufferCheckInterval = 1*KB/2;
|
||||
static constexpr int kBufferCheckInterval = 1 * KB / 2;
|
||||
|
||||
// Code generation.
|
||||
// The relocation writer's position is at least kGap bytes below the end of
|
||||
// the generated instructions. This is so that multi-instruction sequences do
|
||||
// not have to check for overflow. The same is true for writes of large
|
||||
// relocation info entries.
|
||||
static const int kGap = 32;
|
||||
|
||||
static constexpr int kGap = 32;
|
||||
|
||||
// Repeated checking whether the trampoline pool should be emitted is rather
|
||||
// expensive. By default we only check again once a number of instructions
|
||||
// has been generated.
|
||||
static const int kCheckConstIntervalInst = 32;
|
||||
static const int kCheckConstInterval = kCheckConstIntervalInst * kInstrSize;
|
||||
static constexpr int kCheckConstIntervalInst = 32;
|
||||
static constexpr int kCheckConstInterval =
|
||||
kCheckConstIntervalInst * kInstrSize;
|
||||
|
||||
int next_buffer_check_; // pc offset of next buffer check.
|
||||
|
||||
@ -1343,7 +1330,7 @@ class Assembler : public AssemblerBase {
|
||||
|
||||
// Relocation information generation.
|
||||
// Each relocation is encoded as a variable size value.
|
||||
static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
|
||||
RelocInfoWriter reloc_info_writer;
|
||||
|
||||
// The bound position, before this we cannot do instruction elimination.
|
||||
@ -1497,7 +1484,7 @@ class Assembler : public AssemblerBase {
|
||||
// branch instruction generation, where we use jump instructions rather
|
||||
// than regular branch instructions.
|
||||
bool trampoline_emitted_;
|
||||
static const int kInvalidSlotPos = -1;
|
||||
static constexpr int kInvalidSlotPos = -1;
|
||||
|
||||
// Internal reference positions, required for unbounded internal reference
|
||||
// labels.
|
||||
|
@ -80,7 +80,7 @@ namespace internal {
|
||||
V(r15)
|
||||
|
||||
// The length of pushq(rbp), movp(rbp, rsp), Push(rsi) and Push(rdi).
|
||||
static const int kNoCodeAgeSequenceLength = kPointerSize == kInt64Size ? 6 : 17;
|
||||
constexpr int kNoCodeAgeSequenceLength = kPointerSize == kInt64Size ? 6 : 17;
|
||||
|
||||
// CPU Registers.
|
||||
//
|
||||
@ -112,7 +112,7 @@ struct Register {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kNumRegisters = Code::kAfterLast;
|
||||
|
||||
static Register from_code(int code) {
|
||||
DCHECK(code >= 0);
|
||||
@ -144,25 +144,23 @@ struct Register {
|
||||
int reg_code;
|
||||
};
|
||||
|
||||
|
||||
#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
|
||||
#define DECLARE_REGISTER(R) constexpr Register R = {Register::kCode_##R};
|
||||
GENERAL_REGISTERS(DECLARE_REGISTER)
|
||||
#undef DECLARE_REGISTER
|
||||
const Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
constexpr Register no_reg = {Register::kCode_no_reg};
|
||||
|
||||
#ifdef _WIN64
|
||||
// Windows calling convention
|
||||
const Register arg_reg_1 = {Register::kCode_rcx};
|
||||
const Register arg_reg_2 = {Register::kCode_rdx};
|
||||
const Register arg_reg_3 = {Register::kCode_r8};
|
||||
const Register arg_reg_4 = {Register::kCode_r9};
|
||||
constexpr Register arg_reg_1 = {Register::kCode_rcx};
|
||||
constexpr Register arg_reg_2 = {Register::kCode_rdx};
|
||||
constexpr Register arg_reg_3 = {Register::kCode_r8};
|
||||
constexpr Register arg_reg_4 = {Register::kCode_r9};
|
||||
#else
|
||||
// AMD64 calling convention
|
||||
const Register arg_reg_1 = {Register::kCode_rdi};
|
||||
const Register arg_reg_2 = {Register::kCode_rsi};
|
||||
const Register arg_reg_3 = {Register::kCode_rdx};
|
||||
const Register arg_reg_4 = {Register::kCode_rcx};
|
||||
constexpr Register arg_reg_1 = {Register::kCode_rdi};
|
||||
constexpr Register arg_reg_2 = {Register::kCode_rsi};
|
||||
constexpr Register arg_reg_3 = {Register::kCode_rdx};
|
||||
constexpr Register arg_reg_4 = {Register::kCode_rcx};
|
||||
#endif // _WIN64
|
||||
|
||||
|
||||
@ -204,8 +202,8 @@ const Register arg_reg_4 = {Register::kCode_rcx};
|
||||
V(xmm13) \
|
||||
V(xmm14)
|
||||
|
||||
static const bool kSimpleFPAliasing = true;
|
||||
static const bool kSimdMaskRegisters = false;
|
||||
constexpr bool kSimpleFPAliasing = true;
|
||||
constexpr bool kSimdMaskRegisters = false;
|
||||
|
||||
struct XMMRegister {
|
||||
enum Code {
|
||||
@ -216,7 +214,7 @@ struct XMMRegister {
|
||||
kCode_no_reg = -1
|
||||
};
|
||||
|
||||
static const int kMaxNumRegisters = Code::kAfterLast;
|
||||
static constexpr int kMaxNumRegisters = Code::kAfterLast;
|
||||
|
||||
static XMMRegister from_code(int code) {
|
||||
XMMRegister result = {code};
|
||||
@ -249,10 +247,10 @@ typedef XMMRegister DoubleRegister;
|
||||
typedef XMMRegister Simd128Register;
|
||||
|
||||
#define DECLARE_REGISTER(R) \
|
||||
const DoubleRegister R = {DoubleRegister::kCode_##R};
|
||||
constexpr DoubleRegister R = {DoubleRegister::kCode_##R};
|
||||
DOUBLE_REGISTERS(DECLARE_REGISTER)
|
||||
#undef DECLARE_REGISTER
|
||||
const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
|
||||
constexpr DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
|
||||
|
||||
enum Condition {
|
||||
// any value < 0 is considered no_condition
|
||||
@ -471,7 +469,7 @@ class Assembler : public AssemblerBase {
|
||||
// (There is a 15 byte limit on x64 instruction length that rules out some
|
||||
// otherwise valid instructions.)
|
||||
// This allows for a single, fast space check per instruction.
|
||||
static const int kGap = 32;
|
||||
static constexpr int kGap = 32;
|
||||
|
||||
public:
|
||||
// Create an assembler. Instructions and relocation information are emitted
|
||||
@ -538,42 +536,42 @@ class Assembler : public AssemblerBase {
|
||||
inline Handle<Code> code_target_object_handle_at(Address pc);
|
||||
inline Address runtime_entry_at(Address pc);
|
||||
// Number of bytes taken up by the branch target in the code.
|
||||
static const int kSpecialTargetSize = 4; // Use 32-bit displacement.
|
||||
static constexpr int kSpecialTargetSize = 4; // 32-bit displacement.
|
||||
// Distance between the address of the code target in the call instruction
|
||||
// and the return address pushed on the stack.
|
||||
static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
|
||||
static constexpr int kCallTargetAddressOffset = 4; // 32-bit displacement.
|
||||
// The length of call(kScratchRegister).
|
||||
static const int kCallScratchRegisterInstructionLength = 3;
|
||||
static constexpr int kCallScratchRegisterInstructionLength = 3;
|
||||
// The length of call(Immediate32).
|
||||
static const int kShortCallInstructionLength = 5;
|
||||
static constexpr int kShortCallInstructionLength = 5;
|
||||
// The length of movq(kScratchRegister, address).
|
||||
static const int kMoveAddressIntoScratchRegisterInstructionLength =
|
||||
static constexpr int kMoveAddressIntoScratchRegisterInstructionLength =
|
||||
2 + kPointerSize;
|
||||
// The length of movq(kScratchRegister, address) and call(kScratchRegister).
|
||||
static const int kCallSequenceLength =
|
||||
static constexpr int kCallSequenceLength =
|
||||
kMoveAddressIntoScratchRegisterInstructionLength +
|
||||
kCallScratchRegisterInstructionLength;
|
||||
|
||||
// The debug break slot must be able to contain an indirect call sequence.
|
||||
static const int kDebugBreakSlotLength = kCallSequenceLength;
|
||||
static constexpr int kDebugBreakSlotLength = kCallSequenceLength;
|
||||
// Distance between start of patched debug break slot and the emitted address
|
||||
// to jump to.
|
||||
static const int kPatchDebugBreakSlotAddressOffset =
|
||||
static constexpr int kPatchDebugBreakSlotAddressOffset =
|
||||
kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
|
||||
|
||||
// One byte opcode for test eax,0xXXXXXXXX.
|
||||
static const byte kTestEaxByte = 0xA9;
|
||||
static constexpr byte kTestEaxByte = 0xA9;
|
||||
// One byte opcode for test al, 0xXX.
|
||||
static const byte kTestAlByte = 0xA8;
|
||||
static constexpr byte kTestAlByte = 0xA8;
|
||||
// One byte opcode for nop.
|
||||
static const byte kNopByte = 0x90;
|
||||
static constexpr byte kNopByte = 0x90;
|
||||
|
||||
// One byte prefix for a short conditional jump.
|
||||
static const byte kJccShortPrefix = 0x70;
|
||||
static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
|
||||
static const byte kJcShortOpcode = kJccShortPrefix | carry;
|
||||
static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
|
||||
static const byte kJzShortOpcode = kJccShortPrefix | zero;
|
||||
static constexpr byte kJccShortPrefix = 0x70;
|
||||
static constexpr byte kJncShortOpcode = kJccShortPrefix | not_carry;
|
||||
static constexpr byte kJcShortOpcode = kJccShortPrefix | carry;
|
||||
static constexpr byte kJnzShortOpcode = kJccShortPrefix | not_zero;
|
||||
static constexpr byte kJzShortOpcode = kJccShortPrefix | zero;
|
||||
|
||||
// VEX prefix encodings.
|
||||
enum SIMDPrefix { kNone = 0x0, k66 = 0x1, kF3 = 0x2, kF2 = 0x3 };
|
||||
@ -2019,7 +2017,7 @@ class Assembler : public AssemblerBase {
|
||||
static bool IsNop(Address addr);
|
||||
|
||||
// Avoid overflows for displacements etc.
|
||||
static const int kMaximalBufferSize = 512*MB;
|
||||
static constexpr int kMaximalBufferSize = 512 * MB;
|
||||
|
||||
byte byte_at(int pos) { return buffer_[pos]; }
|
||||
void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
|
||||
|
Loading…
Reference in New Issue
Block a user