| Index: src/mips64/assembler-mips64.h
|
| diff --git a/src/mips64/assembler-mips64.h b/src/mips64/assembler-mips64.h
|
| index 775fab394660fdcba0036ba82da72f4f4ec483ea..b1be0e8b39078a58a254b9ba0b0a18430ab678f6 100644
|
| --- a/src/mips64/assembler-mips64.h
|
| +++ b/src/mips64/assembler-mips64.h
|
| @@ -47,28 +47,6 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -// clang-format off
|
| -#define GENERAL_REGISTERS(V) \
|
| - V(zero_reg) V(at) V(v0) V(v1) V(a0) V(a1) V(a2) V(a3) \
|
| - V(a4) V(a5) V(a6) V(a7) V(t0) V(t1) V(t2) V(t3) \
|
| - V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) V(t8) V(t9) \
|
| - V(k0) V(k1) V(gp) V(sp) V(fp) V(ra)
|
| -
|
| -#define ALLOCATABLE_GENERAL_REGISTERS(V) \
|
| - V(v0) V(v1) V(a0) V(a1) V(a2) V(a3) \
|
| - V(a4) V(a5) V(a6) V(a7) V(t0) V(t1) V(t2) V(s7)
|
| -
|
| -#define DOUBLE_REGISTERS(V) \
|
| - V(f0) V(f1) V(f2) V(f3) V(f4) V(f5) V(f6) V(f7) \
|
| - V(f8) V(f9) V(f10) V(f11) V(f12) V(f13) V(f14) V(f15) \
|
| - V(f16) V(f17) V(f18) V(f19) V(f20) V(f21) V(f22) V(f23) \
|
| - V(f24) V(f25) V(f26) V(f27) V(f28) V(f29) V(f30) V(f31)
|
| -
|
| -#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
|
| - V(f0) V(f2) V(f4) V(f6) V(f8) V(f10) V(f12) V(f14) \
|
| - V(f16) V(f18) V(f20) V(f22) V(f24) V(f26)
|
| -// clang-format on
|
| -
|
| // CPU Registers.
|
| //
|
| // 1) We would prefer to use an enum, but enum values are assignment-
|
| @@ -94,7 +72,11 @@
|
| // -----------------------------------------------------------------------------
|
| // Implementation of Register and FPURegister.
|
|
|
| +// Core register.
|
| struct Register {
|
| + static const int kNumRegisters = v8::internal::kNumRegisters;
|
| + static const int kMaxNumAllocatableRegisters = 14; // v0 through t2 and cp.
|
| + static const int kSizeInBytes = 8;
|
| static const int kCpRegister = 23; // cp (s7) is the 23rd register.
|
|
|
| #if defined(V8_TARGET_LITTLE_ENDIAN)
|
| @@ -107,47 +89,117 @@
|
| #error Unknown endianness
|
| #endif
|
|
|
| - enum Code {
|
| -#define REGISTER_CODE(R) kCode_##R,
|
| - GENERAL_REGISTERS(REGISTER_CODE)
|
| -#undef REGISTER_CODE
|
| - kAfterLast,
|
| - kCode_no_reg = -1
|
| - };
|
| -
|
| - static const int kNumRegisters = Code::kAfterLast;
|
| + inline static int NumAllocatableRegisters();
|
| +
|
| + static int ToAllocationIndex(Register reg) {
|
| + DCHECK((reg.code() - 2) < (kMaxNumAllocatableRegisters - 1) ||
|
| + reg.is(from_code(kCpRegister)));
|
| + return reg.is(from_code(kCpRegister)) ?
|
| + kMaxNumAllocatableRegisters - 1 : // Return last index for 'cp'.
|
| + reg.code() - 2; // zero_reg and 'at' are skipped.
|
| + }
|
| +
|
| + static Register FromAllocationIndex(int index) {
|
| + DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
|
| + return index == kMaxNumAllocatableRegisters - 1 ?
|
| + from_code(kCpRegister) : // Last index is always the 'cp' register.
|
| + from_code(index + 2); // zero_reg and 'at' are skipped.
|
| + }
|
| +
|
| + static const char* AllocationIndexToString(int index) {
|
| + DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
|
| + const char* const names[] = {
|
| + "v0",
|
| + "v1",
|
| + "a0",
|
| + "a1",
|
| + "a2",
|
| + "a3",
|
| + "a4",
|
| + "a5",
|
| + "a6",
|
| + "a7",
|
| + "t0",
|
| + "t1",
|
| + "t2",
|
| + "s7",
|
| + };
|
| + return names[index];
|
| + }
|
|
|
| static Register from_code(int code) {
|
| - DCHECK(code >= 0);
|
| - DCHECK(code < kNumRegisters);
|
| Register r = { code };
|
| return r;
|
| }
|
|
|
| - const char* ToString();
|
| - bool IsAllocatable() const;
|
| - bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
|
| - bool is(Register reg) const { return reg_code == reg.reg_code; }
|
| + bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
|
| + bool is(Register reg) const { return code_ == reg.code_; }
|
| int code() const {
|
| DCHECK(is_valid());
|
| - return reg_code;
|
| + return code_;
|
| }
|
| int bit() const {
|
| DCHECK(is_valid());
|
| - return 1 << reg_code;
|
| + return 1 << code_;
|
| }
|
|
|
| // Unfortunately we can't make this private in a struct.
|
| - int reg_code;
|
| + int code_;
|
| };
|
|
|
| -// s7: context register
|
| -// s3: lithium scratch
|
| -// s4: lithium scratch2
|
| -#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};
|
| +#define REGISTER(N, C) \
|
| + const int kRegister_ ## N ## _Code = C; \
|
| + const Register N = { C }
|
| +
|
| +REGISTER(no_reg, -1);
|
| +// Always zero.
|
| +REGISTER(zero_reg, 0);
|
| +// at: Reserved for synthetic instructions.
|
| +REGISTER(at, 1);
|
| +// v0, v1: Used when returning multiple values from subroutines.
|
| +REGISTER(v0, 2);
|
| +REGISTER(v1, 3);
|
| +// a0 - a4: Used to pass non-FP parameters.
|
| +REGISTER(a0, 4);
|
| +REGISTER(a1, 5);
|
| +REGISTER(a2, 6);
|
| +REGISTER(a3, 7);
|
| +// a4 - a7 t0 - t3: Can be used without reservation, act as temporary registers
|
| +// and are allowed to be destroyed by subroutines.
|
| +REGISTER(a4, 8);
|
| +REGISTER(a5, 9);
|
| +REGISTER(a6, 10);
|
| +REGISTER(a7, 11);
|
| +REGISTER(t0, 12);
|
| +REGISTER(t1, 13);
|
| +REGISTER(t2, 14);
|
| +REGISTER(t3, 15);
|
| +// s0 - s7: Subroutine register variables. Subroutines that write to these
|
| +// registers must restore their values before exiting so that the caller can
|
| +// expect the values to be preserved.
|
| +REGISTER(s0, 16);
|
| +REGISTER(s1, 17);
|
| +REGISTER(s2, 18);
|
| +REGISTER(s3, 19);
|
| +REGISTER(s4, 20);
|
| +REGISTER(s5, 21);
|
| +REGISTER(s6, 22);
|
| +REGISTER(s7, 23);
|
| +REGISTER(t8, 24);
|
| +REGISTER(t9, 25);
|
| +// k0, k1: Reserved for system calls and interrupt handlers.
|
| +REGISTER(k0, 26);
|
| +REGISTER(k1, 27);
|
| +// gp: Reserved.
|
| +REGISTER(gp, 28);
|
| +// sp: Stack pointer.
|
| +REGISTER(sp, 29);
|
| +// fp: Frame pointer.
|
| +REGISTER(fp, 30);
|
| +// ra: Return address pointer.
|
| +REGISTER(ra, 31);
|
| +
|
| +#undef REGISTER
|
|
|
|
|
| int ToNumber(Register reg);
|
| @@ -155,71 +207,76 @@
|
| Register ToRegister(int num);
|
|
|
| // Coprocessor register.
|
| -struct DoubleRegister {
|
| - enum Code {
|
| -#define REGISTER_CODE(R) kCode_##R,
|
| - DOUBLE_REGISTERS(REGISTER_CODE)
|
| -#undef REGISTER_CODE
|
| - kAfterLast,
|
| - kCode_no_reg = -1
|
| - };
|
| -
|
| - static const int kMaxNumRegisters = Code::kAfterLast;
|
| -
|
| - inline static int NumRegisters();
|
| +struct FPURegister {
|
| + static const int kMaxNumRegisters = v8::internal::kNumFPURegisters;
|
|
|
| // TODO(plind): Warning, inconsistent numbering here. kNumFPURegisters refers
|
| // to number of 32-bit FPU regs, but kNumAllocatableRegisters refers to
|
| // number of Double regs (64-bit regs, or FPU-reg-pairs).
|
|
|
| - const char* ToString();
|
| - bool IsAllocatable() const;
|
| - bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
|
| - bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
|
| - DoubleRegister low() const {
|
| + // A few double registers are reserved: one as a scratch register and one to
|
| + // hold 0.0.
|
| + // f28: 0.0
|
| + // f30: scratch register.
|
| + static const int kNumReservedRegisters = 2;
|
| + static const int kMaxNumAllocatableRegisters = kMaxNumRegisters / 2 -
|
| + kNumReservedRegisters;
|
| +
|
| + inline static int NumRegisters();
|
| + inline static int NumAllocatableRegisters();
|
| +
|
| + // TODO(turbofan): Proper support for float32.
|
| + inline static int NumAllocatableAliasedRegisters();
|
| +
|
| + inline static int ToAllocationIndex(FPURegister reg);
|
| + static const char* AllocationIndexToString(int index);
|
| +
|
| + static FPURegister FromAllocationIndex(int index) {
|
| + DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
|
| + return from_code(index * 2);
|
| + }
|
| +
|
| + static FPURegister from_code(int code) {
|
| + FPURegister r = { code };
|
| + return r;
|
| + }
|
| +
|
| + bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters ; }
|
| + bool is(FPURegister creg) const { return code_ == creg.code_; }
|
| + FPURegister low() const {
|
| // TODO(plind): Create DCHECK for FR=0 mode. This usage suspect for FR=1.
|
| // Find low reg of a Double-reg pair, which is the reg itself.
|
| - DCHECK(reg_code % 2 == 0); // Specified Double reg must be even.
|
| - DoubleRegister reg;
|
| - reg.reg_code = reg_code;
|
| + DCHECK(code_ % 2 == 0); // Specified Double reg must be even.
|
| + FPURegister reg;
|
| + reg.code_ = code_;
|
| DCHECK(reg.is_valid());
|
| return reg;
|
| }
|
| - DoubleRegister high() const {
|
| + FPURegister high() const {
|
| // TODO(plind): Create DCHECK for FR=0 mode. This usage illegal in FR=1.
|
| // Find high reg of a Doubel-reg pair, which is reg + 1.
|
| - DCHECK(reg_code % 2 == 0); // Specified Double reg must be even.
|
| - DoubleRegister reg;
|
| - reg.reg_code = reg_code + 1;
|
| + DCHECK(code_ % 2 == 0); // Specified Double reg must be even.
|
| + FPURegister reg;
|
| + reg.code_ = code_ + 1;
|
| DCHECK(reg.is_valid());
|
| return reg;
|
| }
|
|
|
| int code() const {
|
| DCHECK(is_valid());
|
| - return reg_code;
|
| + return code_;
|
| }
|
| int bit() const {
|
| DCHECK(is_valid());
|
| - return 1 << reg_code;
|
| - }
|
| -
|
| - static DoubleRegister from_code(int code) {
|
| - DoubleRegister r = {code};
|
| - return r;
|
| + return 1 << code_;
|
| }
|
| void setcode(int f) {
|
| - reg_code = f;
|
| + code_ = f;
|
| DCHECK(is_valid());
|
| }
|
| // Unfortunately we can't make this private in a struct.
|
| - int reg_code;
|
| + int code_;
|
| };
|
| -
|
| -// A few double registers are reserved: one as a scratch register and one to
|
| -// hold 0.0.
|
| -// f28: 0.0
|
| -// f30: scratch register.
|
|
|
| // V8 now supports the O32 ABI, and the FPU Registers are organized as 32
|
| // 32-bit registers, f0 through f31. When used as 'double' they are used
|
| @@ -230,43 +287,43 @@
|
| // but it is not in common use. Someday we will want to support this in v8.)
|
|
|
| // For O32 ABI, Floats and Doubles refer to same set of 32 32-bit registers.
|
| -typedef DoubleRegister FPURegister;
|
| -typedef DoubleRegister FloatRegister;
|
| -
|
| -const 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};
|
| +typedef FPURegister DoubleRegister;
|
| +typedef FPURegister FloatRegister;
|
| +
|
| +const FPURegister no_freg = { -1 };
|
| +
|
| +const FPURegister f0 = { 0 }; // Return value in hard float mode.
|
| +const FPURegister f1 = { 1 };
|
| +const FPURegister f2 = { 2 };
|
| +const FPURegister f3 = { 3 };
|
| +const FPURegister f4 = { 4 };
|
| +const FPURegister f5 = { 5 };
|
| +const FPURegister f6 = { 6 };
|
| +const FPURegister f7 = { 7 };
|
| +const FPURegister f8 = { 8 };
|
| +const FPURegister f9 = { 9 };
|
| +const FPURegister f10 = { 10 };
|
| +const FPURegister f11 = { 11 };
|
| +const FPURegister f12 = { 12 }; // Arg 0 in hard float mode.
|
| +const FPURegister f13 = { 13 };
|
| +const FPURegister f14 = { 14 }; // Arg 1 in hard float mode.
|
| +const FPURegister f15 = { 15 };
|
| +const FPURegister f16 = { 16 };
|
| +const FPURegister f17 = { 17 };
|
| +const FPURegister f18 = { 18 };
|
| +const FPURegister f19 = { 19 };
|
| +const FPURegister f20 = { 20 };
|
| +const FPURegister f21 = { 21 };
|
| +const FPURegister f22 = { 22 };
|
| +const FPURegister f23 = { 23 };
|
| +const FPURegister f24 = { 24 };
|
| +const FPURegister f25 = { 25 };
|
| +const FPURegister f26 = { 26 };
|
| +const FPURegister f27 = { 27 };
|
| +const FPURegister f28 = { 28 };
|
| +const FPURegister f29 = { 29 };
|
| +const FPURegister f30 = { 30 };
|
| +const FPURegister f31 = { 31 };
|
|
|
| // Register aliases.
|
| // cp is assumed to be a callee saved register.
|
| @@ -286,22 +343,22 @@
|
| // FPU (coprocessor 1) control registers.
|
| // Currently only FCSR (#31) is implemented.
|
| struct FPUControlRegister {
|
| - bool is_valid() const { return reg_code == kFCSRRegister; }
|
| - bool is(FPUControlRegister creg) const { return reg_code == creg.reg_code; }
|
| + bool is_valid() const { return code_ == kFCSRRegister; }
|
| + bool is(FPUControlRegister creg) const { return code_ == creg.code_; }
|
| int code() const {
|
| DCHECK(is_valid());
|
| - return reg_code;
|
| + return code_;
|
| }
|
| int bit() const {
|
| DCHECK(is_valid());
|
| - return 1 << reg_code;
|
| + return 1 << code_;
|
| }
|
| void setcode(int f) {
|
| - reg_code = f;
|
| + code_ = f;
|
| DCHECK(is_valid());
|
| }
|
| // Unfortunately we can't make this private in a struct.
|
| - int reg_code;
|
| + int code_;
|
| };
|
|
|
| const FPUControlRegister no_fpucreg = { kInvalidFPUControlRegister };
|
|
|