"src/compiler/register-allocator.h",
"src/compiler/register-allocator-verifier.cc",
"src/compiler/register-allocator-verifier.h",
+ "src/compiler/register-configuration.cc",
+ "src/compiler/register-configuration.h",
"src/compiler/representation-change.h",
"src/compiler/schedule.cc",
"src/compiler/schedule.h",
"src/regexp/regexp-macro-assembler.h",
"src/regexp/regexp-stack.cc",
"src/regexp/regexp-stack.h",
- "src/register-configuration.cc",
- "src/register-configuration.h",
"src/runtime-profiler.cc",
"src/runtime-profiler.h",
"src/runtime/runtime-array.cc",
bool CpuFeatures::SupportsCrankshaft() { return IsSupported(VFP3); }
-int DoubleRegister::NumRegisters() {
+int Register::NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+}
+
+
+int DwVfpRegister::NumRegisters() {
return CpuFeatures::IsSupported(VFP32DREGS) ? 32 : 16;
}
+int DwVfpRegister::NumReservedRegisters() {
+ return kNumReservedRegisters;
+}
+
+
+int DwVfpRegister::NumAllocatableRegisters() {
+ return NumRegisters() - kNumReservedRegisters;
+}
+
+
+// static
+int DwVfpRegister::NumAllocatableAliasedRegisters() {
+ return LowDwVfpRegister::kMaxNumLowRegisters - kNumReservedRegisters;
+}
+
+
+int DwVfpRegister::ToAllocationIndex(DwVfpRegister reg) {
+ DCHECK(!reg.is(kDoubleRegZero));
+ DCHECK(!reg.is(kScratchDoubleReg));
+ if (reg.code() > kDoubleRegZero.code()) {
+ return reg.code() - kNumReservedRegisters;
+ }
+ return reg.code();
+}
+
+
+DwVfpRegister DwVfpRegister::FromAllocationIndex(int index) {
+ DCHECK(index >= 0 && index < NumAllocatableRegisters());
+ DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() ==
+ kNumReservedRegisters - 1);
+ if (index >= kDoubleRegZero.code()) {
+ return from_code(index + kNumReservedRegisters);
+ }
+ return from_code(index);
+}
+
+
void RelocInfo::apply(intptr_t delta) {
if (RelocInfo::IsInternalReference(rmode_)) {
// absolute code pointer inside code object moves with the code object.
}
+// -----------------------------------------------------------------------------
+// Implementation of DwVfpRegister
+
+const char* DwVfpRegister::AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < NumAllocatableRegisters());
+ DCHECK(kScratchDoubleReg.code() - kDoubleRegZero.code() ==
+ kNumReservedRegisters - 1);
+ if (index >= kDoubleRegZero.code()) index += kNumReservedRegisters;
+ return VFPRegisters::Name(index, true);
+}
+
+
// -----------------------------------------------------------------------------
// Implementation of RelocInfo
// str(r, MemOperand(sp, 4, NegPreIndex), al) instruction (aka push(r))
// register r is not encoded.
const Instr kPushRegPattern =
- al | B26 | 4 | NegPreIndex | Register::kCode_sp * B16;
+ al | B26 | 4 | NegPreIndex | kRegister_sp_Code * B16;
// ldr(r, MemOperand(sp, 4, PostIndex), al) instruction (aka pop(r))
// register r is not encoded.
const Instr kPopRegPattern =
- al | B26 | L | 4 | PostIndex | Register::kCode_sp * B16;
+ al | B26 | L | 4 | PostIndex | kRegister_sp_Code * B16;
// ldr rd, [pc, #offset]
const Instr kLdrPCImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPCImmedPattern = 5 * B24 | L | Register::kCode_pc * B16;
+const Instr kLdrPCImmedPattern = 5 * B24 | L | kRegister_pc_Code * B16;
// ldr rd, [pp, #offset]
const Instr kLdrPpImmedMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPpImmedPattern = 5 * B24 | L | Register::kCode_r8 * B16;
+const Instr kLdrPpImmedPattern = 5 * B24 | L | kRegister_r8_Code * B16;
// ldr rd, [pp, rn]
const Instr kLdrPpRegMask = 15 * B24 | 7 * B20 | 15 * B16;
-const Instr kLdrPpRegPattern = 7 * B24 | L | Register::kCode_r8 * B16;
+const Instr kLdrPpRegPattern = 7 * B24 | L | kRegister_r8_Code * B16;
// vldr dd, [pc, #offset]
const Instr kVldrDPCMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
-const Instr kVldrDPCPattern = 13 * B24 | L | Register::kCode_pc * B16 | 11 * B8;
+const Instr kVldrDPCPattern = 13 * B24 | L | kRegister_pc_Code * B16 | 11 * B8;
// vldr dd, [pp, #offset]
const Instr kVldrDPpMask = 15 * B24 | 3 * B20 | 15 * B16 | 15 * B8;
-const Instr kVldrDPpPattern = 13 * B24 | L | Register::kCode_r8 * B16 | 11 * B8;
+const Instr kVldrDPpPattern = 13 * B24 | L | kRegister_r8_Code * B16 | 11 * B8;
// blxcc rm
const Instr kBlxRegMask =
15 * B24 | 15 * B20 | 15 * B16 | 15 * B12 | 15 * B8 | 15 * B4;
// A mask for the Rd register for push, pop, ldr, str instructions.
const Instr kLdrRegFpOffsetPattern =
- al | B26 | L | Offset | Register::kCode_fp * B16;
+ al | B26 | L | Offset | kRegister_fp_Code * B16;
const Instr kStrRegFpOffsetPattern =
- al | B26 | Offset | Register::kCode_fp * B16;
+ al | B26 | Offset | kRegister_fp_Code * B16;
const Instr kLdrRegFpNegOffsetPattern =
- al | B26 | L | NegOffset | Register::kCode_fp * B16;
+ al | B26 | L | NegOffset | kRegister_fp_Code * B16;
const Instr kStrRegFpNegOffsetPattern =
- al | B26 | NegOffset | Register::kCode_fp * B16;
+ al | B26 | NegOffset | kRegister_fp_Code * B16;
const Instr kLdrStrInstrTypeMask = 0xffff0000;
Register Assembler::GetRd(Instr instr) {
Register reg;
- reg.reg_code = Instruction::RdValue(instr);
+ reg.code_ = Instruction::RdValue(instr);
return reg;
}
Register Assembler::GetRn(Instr instr) {
Register reg;
- reg.reg_code = Instruction::RnValue(instr);
+ reg.code_ = Instruction::RnValue(instr);
return reg;
}
Register Assembler::GetRm(Instr instr) {
Register reg;
- reg.reg_code = Instruction::RmValue(instr);
+ reg.code_ = Instruction::RmValue(instr);
return reg;
}
namespace v8 {
namespace internal {
-// clang-format off
-#define GENERAL_REGISTERS(V) \
- V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
- V(r8) V(r9) V(r10) V(fp) V(ip) V(sp) V(lr) V(pc)
-
-#define ALLOCATABLE_GENERAL_REGISTERS(V) \
- V(r0) V(r1) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) V(r8)
-
-#define DOUBLE_REGISTERS(V) \
- V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
- V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
- V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
-
-#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
- V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
- V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
- V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
-
-#define ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(V) \
- V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
- V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) \
-// clang-format on
-
// CPU Registers.
//
// 1) We would prefer to use an enum, but enum values are assignment-
// mode. This way we get the compile-time error checking in debug mode
// and best performance in optimized code.
+// These constants are used in several locations, including static initializers
+const int kRegister_no_reg_Code = -1;
+const int kRegister_r0_Code = 0;
+const int kRegister_r1_Code = 1;
+const int kRegister_r2_Code = 2;
+const int kRegister_r3_Code = 3;
+const int kRegister_r4_Code = 4;
+const int kRegister_r5_Code = 5;
+const int kRegister_r6_Code = 6;
+const int kRegister_r7_Code = 7;
+const int kRegister_r8_Code = 8;
+const int kRegister_r9_Code = 9;
+const int kRegister_r10_Code = 10;
+const int kRegister_fp_Code = 11;
+const int kRegister_ip_Code = 12;
+const int kRegister_sp_Code = 13;
+const int kRegister_lr_Code = 14;
+const int kRegister_pc_Code = 15;
+
+// Core register
struct Register {
- enum Code {
-#define REGISTER_CODE(R) kCode_##R,
- GENERAL_REGISTERS(REGISTER_CODE)
-#undef REGISTER_CODE
- kAfterLast,
- kCode_no_reg = -1
- };
+ static const int kNumRegisters = 16;
+ static const int kMaxNumAllocatableRegisters =
+ FLAG_enable_embedded_constant_pool ? 8 : 9;
+ static const int kSizeInBytes = 4;
+
+ inline static int NumAllocatableRegisters();
- static const int kNumRegisters = Code::kAfterLast;
+ static int ToAllocationIndex(Register reg) {
+ DCHECK(reg.code() < kMaxNumAllocatableRegisters);
+ return reg.code();
+ }
+
+ static Register FromAllocationIndex(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ return from_code(index);
+ }
+
+ static const char* AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ const char* const names[] = {
+ "r0",
+ "r1",
+ "r2",
+ "r3",
+ "r4",
+ "r5",
+ "r6",
+ "r7",
+ "r8",
+ };
+ if (FLAG_enable_embedded_constant_pool && (index >= 7)) {
+ return names[index + 1];
+ }
+ return names[index];
+ }
static Register from_code(int code) {
- DCHECK(code >= 0);
- DCHECK(code < kNumRegisters);
- Register r = {code};
+ 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_;
}
+
void set_code(int code) {
- reg_code = code;
+ code_ = code;
DCHECK(is_valid());
}
// Unfortunately we can't make this private in a struct.
- int reg_code;
+ int code_;
};
-// 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};
-GENERAL_REGISTERS(DECLARE_REGISTER)
-#undef DECLARE_REGISTER
-const Register no_reg = {Register::kCode_no_reg};
+const Register no_reg = { kRegister_no_reg_Code };
+
+const Register r0 = { kRegister_r0_Code };
+const Register r1 = { kRegister_r1_Code };
+const Register r2 = { kRegister_r2_Code };
+const Register r3 = { kRegister_r3_Code };
+const Register r4 = { kRegister_r4_Code };
+const Register r5 = { kRegister_r5_Code };
+const Register r6 = { kRegister_r6_Code };
+// Used as context register.
+const Register r7 = {kRegister_r7_Code};
+// Used as constant pool pointer register if FLAG_enable_embedded_constant_pool.
+const Register r8 = { kRegister_r8_Code };
+// Used as lithium codegen scratch register.
+const Register r9 = { kRegister_r9_Code };
+// Used as roots register.
+const Register r10 = { kRegister_r10_Code };
+const Register fp = { kRegister_fp_Code };
+const Register ip = { kRegister_ip_Code };
+const Register sp = { kRegister_sp_Code };
+const Register lr = { kRegister_lr_Code };
+const Register pc = { kRegister_pc_Code };
// Single word VFP register.
struct SwVfpRegister {
static const 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; }
+ bool is_valid() const { return 0 <= code_ && code_ < 32; }
+ bool is(SwVfpRegister 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_;
}
void split_code(int* vm, int* m) const {
DCHECK(is_valid());
- *m = reg_code & 0x1;
- *vm = reg_code >> 1;
+ *m = code_ & 0x1;
+ *vm = code_ >> 1;
}
- int reg_code;
+ int code_;
};
// Double word VFP 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 DwVfpRegister {
+ static const int kMaxNumRegisters = 32;
// A few double registers are reserved: one as a scratch register and one to
// hold 0.0, that does not fit in the immediate field of vmov instructions.
// d14: 0.0
// d15: scratch register.
+ static const int kNumReservedRegisters = 2;
+ static const int kMaxNumAllocatableRegisters = kMaxNumRegisters -
+ kNumReservedRegisters;
static const int kSizeInBytes = 8;
- 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; }
+ // Note: the number of registers can be different at snapshot and run-time.
+ // Any code included in the snapshot must be able to run both with 16 or 32
+ // registers.
+ inline static int NumRegisters();
+ inline static int NumReservedRegisters();
+ inline static int NumAllocatableRegisters();
+
+ // TODO(turbofan): This is a temporary work-around required because our
+ // register allocator does not yet support the aliasing of single/double
+ // registers on ARM.
+ inline static int NumAllocatableAliasedRegisters();
+
+ inline static int ToAllocationIndex(DwVfpRegister reg);
+ static const char* AllocationIndexToString(int index);
+ inline static DwVfpRegister FromAllocationIndex(int index);
+
+ static DwVfpRegister from_code(int code) {
+ DwVfpRegister r = { code };
+ return r;
+ }
+
+ bool is_valid() const {
+ return 0 <= code_ && code_ < kMaxNumRegisters;
+ }
+ bool is(DwVfpRegister 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;
- }
-
- static DoubleRegister from_code(int code) {
- DoubleRegister r = {code};
- return r;
+ return 1 << code_;
}
void split_code(int* vm, int* m) const {
DCHECK(is_valid());
- *m = (reg_code & 0x10) >> 4;
- *vm = reg_code & 0x0F;
+ *m = (code_ & 0x10) >> 4;
+ *vm = code_ & 0x0F;
}
- int reg_code;
+ int code_;
};
-typedef DoubleRegister DwVfpRegister;
+typedef DwVfpRegister DoubleRegister;
// Double word VFP register d0-15.
public:
static const int kMaxNumLowRegisters = 16;
operator DwVfpRegister() const {
- DwVfpRegister r = { reg_code };
+ DwVfpRegister r = { code_ };
return r;
}
static LowDwVfpRegister from_code(int code) {
}
bool is_valid() const {
- return 0 <= reg_code && reg_code < kMaxNumLowRegisters;
+ return 0 <= code_ && code_ < kMaxNumLowRegisters;
}
- bool is(DwVfpRegister reg) const { return reg_code == reg.reg_code; }
- bool is(LowDwVfpRegister reg) const { return reg_code == reg.reg_code; }
+ bool is(DwVfpRegister reg) const { return code_ == reg.code_; }
+ bool is(LowDwVfpRegister reg) const { return code_ == reg.code_; }
int code() const {
DCHECK(is_valid());
- return reg_code;
+ return code_;
}
SwVfpRegister low() const {
SwVfpRegister reg;
- reg.reg_code = reg_code * 2;
+ reg.code_ = code_ * 2;
DCHECK(reg.is_valid());
return reg;
}
SwVfpRegister high() const {
SwVfpRegister reg;
- reg.reg_code = (reg_code * 2) + 1;
+ reg.code_ = (code_ * 2) + 1;
DCHECK(reg.is_valid());
return reg;
}
- int reg_code;
+ int code_;
};
}
bool is_valid() const {
- return (0 <= reg_code) && (reg_code < kMaxNumRegisters);
+ return (0 <= code_) && (code_ < kMaxNumRegisters);
}
- bool is(QwNeonRegister reg) const { return reg_code == reg.reg_code; }
+ bool is(QwNeonRegister reg) const { return code_ == reg.code_; }
int code() const {
DCHECK(is_valid());
- return reg_code;
+ return code_;
}
void split_code(int* vm, int* m) const {
DCHECK(is_valid());
- int encoded_code = reg_code << 1;
+ int encoded_code = code_ << 1;
*m = (encoded_code & 0x10) >> 4;
*vm = encoded_code & 0x0F;
}
- int reg_code;
+ int code_;
};
// Coprocessor register
struct CRegister {
- bool is_valid() const { return 0 <= reg_code && reg_code < 16; }
- bool is(CRegister creg) const { return reg_code == creg.reg_code; }
+ bool is_valid() const { return 0 <= code_ && code_ < 16; }
+ bool is(CRegister 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_;
}
// Unfortunately we can't make this private in a struct.
- int reg_code;
+ int code_;
};
};
+const char* Registers::Name(int reg) {
+ const char* result;
+ if ((0 <= reg) && (reg < kNumRegisters)) {
+ result = names_[reg];
+ } else {
+ result = "noreg";
+ }
+ return result;
+}
+
+
// Support for VFP registers s0 to s31 (d0 to d15) and d16-d31.
// Note that "sN:sM" is the same as "dN/2" up to d15.
// These register names are defined in a way to match the native disassembler
#include "src/codegen.h"
#include "src/deoptimizer.h"
#include "src/full-codegen/full-codegen.h"
-#include "src/register-configuration.h"
#include "src/safepoint-table.h"
namespace v8 {
}
input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
input_->SetDoubleRegister(i, 0.0);
}
// Everything but pc, lr and ip which will be saved but not restored.
RegList restored_regs = kJSCallerSaved | kCalleeSaved | ip.bit();
- const int kDoubleRegsSize = kDoubleSize * DwVfpRegister::kMaxNumRegisters;
+ const int kDoubleRegsSize =
+ kDoubleSize * DwVfpRegister::kMaxNumAllocatableRegisters;
// Save all allocatable VFP registers before messing with them.
DCHECK(kDoubleRegZero.code() == 14);
// Check CPU flags for number of registers, setting the Z condition flag.
__ CheckFor32DRegs(ip);
- // Push registers d0-d15, and possibly d16-d31, on the stack.
+ // Push registers d0-d13, and possibly d16-d31, on the stack.
// If d16-d31 are not pushed, decrease the stack pointer instead.
__ vstm(db_w, sp, d16, d31, ne);
__ sub(sp, sp, Operand(16 * kDoubleSize), LeaveCC, eq);
- __ vstm(db_w, sp, d0, d15);
+ __ vstm(db_w, sp, d0, d13);
// Push all 16 registers (needed to populate FrameDescription::registers_).
// TODO(1588) Note that using pc with stm is deprecated, so we should perhaps
// Copy VFP registers to
// double_registers_[DoubleRegister::kMaxNumAllocatableRegisters]
int double_regs_offset = FrameDescription::double_registers_offset();
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- int dst_offset = code * kDoubleSize + double_regs_offset;
- int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize;
+ for (int i = 0; i < DwVfpRegister::kMaxNumAllocatableRegisters; ++i) {
+ int dst_offset = i * kDoubleSize + double_regs_offset;
+ int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
__ vldr(d0, sp, src_offset);
__ vstr(d0, r1, dst_offset);
}
const char* NameConverter::NameOfCPURegister(int reg) const {
- return v8::internal::Register::from_code(reg).ToString();
+ return v8::internal::Registers::Name(reg);
}
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
- return new (zone())
- LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg));
}
BitVector* doubles = chunk()->allocated_double_registers();
BitVector::Iterator save_iterator(doubles);
while (!save_iterator.Done()) {
- __ vstr(DoubleRegister::from_code(save_iterator.Current()),
+ __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
MemOperand(sp, count * kDoubleSize));
save_iterator.Advance();
count++;
BitVector::Iterator save_iterator(doubles);
int count = 0;
while (!save_iterator.Done()) {
- __ vldr(DoubleRegister::from_code(save_iterator.Current()),
- MemOperand(sp, count * kDoubleSize));
+ __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()),
+ MemOperand(sp, count * kDoubleSize));
save_iterator.Advance();
count++;
}
}
-Register LCodeGen::ToRegister(int code) const {
- return Register::from_code(code);
+Register LCodeGen::ToRegister(int index) const {
+ return Register::FromAllocationIndex(index);
}
-DwVfpRegister LCodeGen::ToDoubleRegister(int code) const {
- return DwVfpRegister::from_code(code);
+DwVfpRegister LCodeGen::ToDoubleRegister(int index) const {
+ return DwVfpRegister::FromAllocationIndex(index);
}
#include "src/codegen.h"
#include "src/cpu-profiler.h"
#include "src/debug/debug.h"
-#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
#include "src/arm/macro-assembler-arm.h"
// Number of d-regs not known at snapshot time.
DCHECK(!serializer_enabled());
// General purpose registers are pushed last on the stack.
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- int doubles_size = config->num_allocatable_double_registers() * kDoubleSize;
+ int doubles_size = DwVfpRegister::NumAllocatableRegisters() * kDoubleSize;
int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
return MemOperand(sp, doubles_size + register_offset);
}
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
- int code = config->GetAllocatableGeneralCode(i);
- Register candidate = Register::from_code(code);
+ for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+ Register candidate = Register::FromAllocationIndex(i);
if (regs & candidate.bit()) continue;
return candidate;
}
namespace internal {
// Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {Register::kCode_r0};
-const Register kReturnRegister1 = {Register::kCode_r1};
-const Register kJSFunctionRegister = {Register::kCode_r1};
-const Register kContextRegister = {Register::kCode_r7};
-const Register kInterpreterAccumulatorRegister = {Register::kCode_r0};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_r4};
-const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r5};
-const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r6};
-const Register kInterpreterDispatchTableRegister = {Register::kCode_r8};
-const Register kRuntimeCallFunctionRegister = {Register::kCode_r1};
-const Register kRuntimeCallArgCountRegister = {Register::kCode_r0};
+const Register kReturnRegister0 = {kRegister_r0_Code};
+const Register kReturnRegister1 = {kRegister_r1_Code};
+const Register kJSFunctionRegister = {kRegister_r1_Code};
+const Register kContextRegister = {kRegister_r7_Code};
+const Register kInterpreterAccumulatorRegister = {kRegister_r0_Code};
+const Register kInterpreterRegisterFileRegister = {kRegister_r4_Code};
+const Register kInterpreterBytecodeOffsetRegister = {kRegister_r5_Code};
+const Register kInterpreterBytecodeArrayRegister = {kRegister_r6_Code};
+const Register kInterpreterDispatchTableRegister = {kRegister_r8_Code};
+const Register kRuntimeCallFunctionRegister = {kRegister_r1_Code};
+const Register kRuntimeCallArgCountRegister = {kRegister_r0_Code};
// ----------------------------------------------------------------------------
// Static helper functions
// Give alias names to registers
-const Register cp = {Register::kCode_r7}; // JavaScript context pointer.
-const Register pp = {Register::kCode_r8}; // Constant pool pointer.
-const Register kRootRegister = {Register::kCode_r10}; // Roots array pointer.
+const Register cp = { kRegister_r7_Code }; // JavaScript context pointer.
+const Register pp = { kRegister_r8_Code }; // Constant pool pointer.
+const Register kRootRegister = { kRegister_r10_Code }; // Roots array pointer.
// Flags used for AllocateHeapNumber
enum TaggingMode {
if (strcmp(arg1, "all") == 0) {
for (int i = 0; i < kNumRegisters; i++) {
value = GetRegisterValue(i);
- PrintF("%3s: 0x%08x %10d", Register::from_code(i).ToString(),
- value, value);
+ PrintF("%3s: 0x%08x %10d", Registers::Name(i), value, value);
if ((argc == 3 && strcmp(arg2, "fp") == 0) &&
i < 8 &&
(i % 2) == 0) {
#include "src/arm64/frames-arm64.h"
#include "src/base/bits.h"
#include "src/base/cpu.h"
-#include "src/register-configuration.h"
namespace v8 {
namespace internal {
Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2,
Register reg3, Register reg4) {
CPURegList regs(reg1, reg2, reg3, reg4);
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- Register candidate = Register::from_code(code);
+ for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+ Register candidate = Register::FromAllocationIndex(i);
if (regs.IncludesAliasOf(candidate)) continue;
return candidate;
}
// -----------------------------------------------------------------------------
// Registers.
-// clang-format off
-#define GENERAL_REGISTER_CODE_LIST(R) \
- R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
- R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
- R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
- R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
-
-#define GENERAL_REGISTERS(R) \
- R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
- R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
- R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \
- R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31)
-
-#define ALLOCATABLE_GENERAL_REGISTERS(R) \
- R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
- R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
- R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27)
-
-#define DOUBLE_REGISTERS(R) \
- R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \
- R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \
- R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \
- R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31)
-
-#define ALLOCATABLE_DOUBLE_REGISTERS(R) \
- R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \
- R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \
- R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \
- R(d25) R(d26) R(d27) R(d28)
-// clang-format on
+#define REGISTER_CODE_LIST(R) \
+R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
+R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
+R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
+R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
+
static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
struct CPURegister {
- enum Code {
-#define REGISTER_CODE(R) kCode_##R,
- GENERAL_REGISTERS(REGISTER_CODE)
-#undef REGISTER_CODE
- kAfterLast,
- kCode_no_reg = -1
- };
-
enum RegisterType {
// The kInvalid value is used to detect uninitialized static instances,
// which are always zero-initialized before any constructors are called.
DCHECK(IsValidOrNone());
}
- const char* ToString();
- bool IsAllocatable() const;
bool IsValid() const {
DCHECK(IsRegister() || IsNone());
return IsValidRegister();
// A few of them may be unused for now.
static const int kNumRegisters = kNumberOfRegisters;
- STATIC_ASSERT(kNumRegisters == Code::kAfterLast);
static int NumRegisters() { return kNumRegisters; }
// We allow crankshaft to use the following registers:
// - "low range"
// - "high range"
// - "context"
+ static const unsigned kAllocatableLowRangeBegin = 0;
+ static const unsigned kAllocatableLowRangeEnd = 15;
+ static const unsigned kAllocatableHighRangeBegin = 18;
+ static const unsigned kAllocatableHighRangeEnd = 24;
+ static const unsigned kAllocatableContext = 27;
+
+ // Gap between low and high ranges.
+ static const int kAllocatableRangeGapSize =
+ (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
+
+ static const int kMaxNumAllocatableRegisters =
+ (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
+ (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1) + 1; // cp
+ static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
+
+ // Return true if the register is one that crankshaft can allocate.
+ bool IsAllocatable() const {
+ return ((reg_code == kAllocatableContext) ||
+ (reg_code <= kAllocatableLowRangeEnd) ||
+ ((reg_code >= kAllocatableHighRangeBegin) &&
+ (reg_code <= kAllocatableHighRangeEnd)));
+ }
+
+ static Register FromAllocationIndex(unsigned index) {
+ DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
+ // cp is the last allocatable register.
+ if (index == (static_cast<unsigned>(NumAllocatableRegisters() - 1))) {
+ return from_code(kAllocatableContext);
+ }
+
+ // Handle low and high ranges.
+ return (index <= kAllocatableLowRangeEnd)
+ ? from_code(index)
+ : from_code(index + kAllocatableRangeGapSize);
+ }
+
+ static const char* AllocationIndexToString(int index) {
+ DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
+ DCHECK((kAllocatableLowRangeBegin == 0) &&
+ (kAllocatableLowRangeEnd == 15) &&
+ (kAllocatableHighRangeBegin == 18) &&
+ (kAllocatableHighRangeEnd == 24) &&
+ (kAllocatableContext == 27));
+ const char* const names[] = {
+ "x0", "x1", "x2", "x3", "x4",
+ "x5", "x6", "x7", "x8", "x9",
+ "x10", "x11", "x12", "x13", "x14",
+ "x15", "x18", "x19", "x20", "x21",
+ "x22", "x23", "x24", "x27",
+ };
+ return names[index];
+ }
+
+ static int ToAllocationIndex(Register reg) {
+ DCHECK(reg.IsAllocatable());
+ unsigned code = reg.code();
+ if (code == kAllocatableContext) {
+ return NumAllocatableRegisters() - 1;
+ }
+
+ return (code <= kAllocatableLowRangeEnd)
+ ? code
+ : code - kAllocatableRangeGapSize;
+ }
static Register from_code(int code) {
// Always return an X register.
struct FPRegister : public CPURegister {
- enum Code {
-#define REGISTER_CODE(R) kCode_##R,
- DOUBLE_REGISTERS(REGISTER_CODE)
-#undef REGISTER_CODE
- kAfterLast,
- kCode_no_reg = -1
- };
-
static FPRegister Create(unsigned code, unsigned size) {
return FPRegister(
CPURegister::Create(code, size, CPURegister::kFPRegister));
DCHECK(IsValidOrNone());
}
- const char* ToString();
- bool IsAllocatable() const;
bool IsValid() const {
DCHECK(IsFPRegister() || IsNone());
return IsValidFPRegister();
// Start of V8 compatibility section ---------------------
static const int kMaxNumRegisters = kNumberOfFPRegisters;
- STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast);
// Crankshaft can use all the FP registers except:
// - d15 which is used to keep the 0 double value
// - d30 which is used in crankshaft as a double scratch register
// - d31 which is used in the MacroAssembler as a double scratch register
+ static const unsigned kAllocatableLowRangeBegin = 0;
+ static const unsigned kAllocatableLowRangeEnd = 14;
+ static const unsigned kAllocatableHighRangeBegin = 16;
+ static const unsigned kAllocatableHighRangeEnd = 28;
+
+ static const RegList kAllocatableFPRegisters = 0x1fff7fff;
+
+ // Gap between low and high ranges.
+ static const int kAllocatableRangeGapSize =
+ (kAllocatableHighRangeBegin - kAllocatableLowRangeEnd) - 1;
+
+ static const int kMaxNumAllocatableRegisters =
+ (kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1) +
+ (kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1);
+ static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
+
+ // TODO(turbofan): Proper float32 support.
+ static int NumAllocatableAliasedRegisters() {
+ return NumAllocatableRegisters();
+ }
+
+ // Return true if the register is one that crankshaft can allocate.
+ bool IsAllocatable() const {
+ return (Bit() & kAllocatableFPRegisters) != 0;
+ }
+
+ static FPRegister FromAllocationIndex(unsigned int index) {
+ DCHECK(index < static_cast<unsigned>(NumAllocatableRegisters()));
+
+ return (index <= kAllocatableLowRangeEnd)
+ ? from_code(index)
+ : from_code(index + kAllocatableRangeGapSize);
+ }
+
+ static const char* AllocationIndexToString(int index) {
+ DCHECK((index >= 0) && (index < NumAllocatableRegisters()));
+ DCHECK((kAllocatableLowRangeBegin == 0) &&
+ (kAllocatableLowRangeEnd == 14) &&
+ (kAllocatableHighRangeBegin == 16) &&
+ (kAllocatableHighRangeEnd == 28));
+ const char* const names[] = {
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "d10", "d11", "d12", "d13", "d14",
+ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23",
+ "d24", "d25", "d26", "d27", "d28"
+ };
+ return names[index];
+ }
+
+ static int ToAllocationIndex(FPRegister reg) {
+ DCHECK(reg.IsAllocatable());
+ unsigned code = reg.code();
+
+ return (code <= kAllocatableLowRangeEnd)
+ ? code
+ : code - kAllocatableRangeGapSize;
+ }
+
static FPRegister from_code(int code) {
// Always return a D register.
return FPRegister::Create(code, kDRegSizeInBits);
kWRegSizeInBits, CPURegister::kRegister); \
INITIALIZE_REGISTER(Register, x##N, N, \
kXRegSizeInBits, CPURegister::kRegister);
-GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS)
+REGISTER_CODE_LIST(DEFINE_REGISTERS)
#undef DEFINE_REGISTERS
INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
kSRegSizeInBits, CPURegister::kFPRegister); \
INITIALIZE_REGISTER(FPRegister, d##N, N, \
kDRegSizeInBits, CPURegister::kFPRegister);
-GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
+REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
#undef DEFINE_FPREGISTERS
#undef INITIALIZE_REGISTER
const unsigned kFloatMantissaBits = 23;
const unsigned kFloatExponentBits = 8;
+#define REGISTER_CODE_LIST(R) \
+R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
+R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
+R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
+R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
+
#define INSTRUCTION_FIELDS_LIST(V_) \
/* Register fields */ \
V_(Rd, 4, 0, Bits) /* Destination register. */ \
#include "src/codegen.h"
#include "src/deoptimizer.h"
#include "src/full-codegen/full-codegen.h"
-#include "src/register-configuration.h"
#include "src/safepoint-table.h"
input_->SetRegister(jssp.code(), reinterpret_cast<intptr_t>(frame->sp()));
input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
input_->SetDoubleRegister(i, 0.0);
}
// in the input frame.
// Save all allocatable floating point registers.
- CPURegList saved_fp_registers(
- CPURegister::kFPRegister, kDRegSizeInBits,
- RegisterConfiguration::ArchDefault()->allocatable_double_codes_mask());
+ CPURegList saved_fp_registers(CPURegister::kFPRegister, kDRegSizeInBits,
+ FPRegister::kAllocatableFPRegisters);
__ PushCPURegList(saved_fp_registers);
// We save all the registers expcept jssp, sp and lr.
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
- return new (zone())
- LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg));
}
while (!iterator.Done()) {
// TODO(all): Is this supposed to save just the callee-saved doubles? It
// looks like it's saving all of them.
- FPRegister value = FPRegister::from_code(iterator.Current());
+ FPRegister value = FPRegister::FromAllocationIndex(iterator.Current());
__ Poke(value, count * kDoubleSize);
iterator.Advance();
count++;
while (!iterator.Done()) {
// TODO(all): Is this supposed to restore just the callee-saved doubles? It
// looks like it's restoring all of them.
- FPRegister value = FPRegister::from_code(iterator.Current());
+ FPRegister value = FPRegister::FromAllocationIndex(iterator.Current());
__ Peek(value, count * kDoubleSize);
iterator.Advance();
count++;
Register LCodeGen::ToRegister(LOperand* op) const {
// TODO(all): support zero register results, as ToRegister32.
DCHECK((op != NULL) && op->IsRegister());
- return Register::from_code(op->index());
+ return Register::FromAllocationIndex(op->index());
}
DoubleRegister LCodeGen::ToDoubleRegister(LOperand* op) const {
DCHECK((op != NULL) && op->IsDoubleRegister());
- return DoubleRegister::from_code(op->index());
+ return DoubleRegister::FromAllocationIndex(op->index());
}
#include "src/codegen.h"
#include "src/cpu-profiler.h"
#include "src/debug/debug.h"
-#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
#include "src/arm64/frames-arm64.h"
void MacroAssembler::PushSafepointRegistersAndDoubles() {
PushSafepointRegisters();
- PushCPURegList(CPURegList(
- CPURegister::kFPRegister, kDRegSizeInBits,
- RegisterConfiguration::ArchDefault()->allocatable_double_codes_mask()));
+ PushCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
+ FPRegister::kAllocatableFPRegisters));
}
void MacroAssembler::PopSafepointRegistersAndDoubles() {
- PopCPURegList(CPURegList(
- CPURegister::kFPRegister, kDRegSizeInBits,
- RegisterConfiguration::ArchDefault()->allocatable_double_codes_mask()));
+ PopCPURegList(CPURegList(CPURegister::kFPRegister, kDRegSizeInBits,
+ FPRegister::kAllocatableFPRegisters));
PopSafepointRegisters();
}
#include "src/globals.h"
#include "src/utils.h"
+#define REGISTER_CODE_LIST(R) \
+R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
+R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
+R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
+R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
+
namespace v8 {
namespace internal {
#include "src/arm64/constants-arm64.h"
+#define REGISTER_CODE_LIST(R) \
+R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
+R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
+R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
+R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
+
namespace v8 {
namespace internal {
#include "src/regexp/jsregexp.h"
#include "src/regexp/regexp-macro-assembler.h"
#include "src/regexp/regexp-stack.h"
-#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
#include "src/simulator.h" // For flushing instruction cache.
#include "src/snapshot/serialize.h"
namespace v8 {
namespace internal {
-// -----------------------------------------------------------------------------
-// Common register code.
-
-const char* Register::ToString() {
- // This is the mapping of allocation indices to registers.
- DCHECK(reg_code >= 0 && reg_code < kNumRegisters);
- return RegisterConfiguration::ArchDefault()->GetGeneralRegisterName(reg_code);
-}
-
-
-bool Register::IsAllocatable() const {
- return ((1 << reg_code) &
- RegisterConfiguration::ArchDefault()
- ->allocatable_general_codes_mask()) != 0;
-}
-
-
-const char* DoubleRegister::ToString() {
- // This is the mapping of allocation indices to registers.
- DCHECK(reg_code >= 0 && reg_code < kMaxNumRegisters);
- return RegisterConfiguration::ArchDefault()->GetDoubleRegisterName(reg_code);
-}
-
-
-bool DoubleRegister::IsAllocatable() const {
- return ((1 << reg_code) &
- RegisterConfiguration::ArchDefault()
- ->allocatable_double_codes_mask()) != 0;
-}
-
-
// -----------------------------------------------------------------------------
// Common double constants.
PerTypeEntryInfo info_[ConstantPoolEntry::NUMBER_OF_TYPES];
};
+
} } // namespace v8::internal
#endif // V8_ASSEMBLER_H_
namespace {
LinkageLocation regloc(Register reg) {
- return LinkageLocation::ForRegister(reg.code());
+ return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg));
}
}
Register ToRegister(InstructionOperand* op) {
- return RegisterOperand::cast(op)->GetRegister();
+ return Register::FromAllocationIndex(RegisterOperand::cast(op)->index());
}
DoubleRegister ToDoubleRegister(InstructionOperand* op) {
- return DoubleRegisterOperand::cast(op)->GetDoubleRegister();
+ return DoubleRegister::FromAllocationIndex(
+ DoubleRegisterOperand::cast(op)->index());
}
Constant ToConstant(InstructionOperand* op) {
index -= stackSlotToSpillSlotDelta;
safepoint.DefinePointerSlot(index, zone());
} else if (operand.IsRegister() && (kind & Safepoint::kWithRegisters)) {
- Register reg = RegisterOperand::cast(operand).GetRegister();
+ Register reg =
+ Register::FromAllocationIndex(RegisterOperand::cast(operand).index());
safepoint.DefinePointerRegister(reg, zone());
}
}
os_ << vreg << ":" << range->relative_id() << " " << type;
if (range->HasRegisterAssigned()) {
AllocatedOperand op = AllocatedOperand::cast(range->GetAssignedOperand());
+ int assigned_reg = op.index();
if (op.IsDoubleRegister()) {
- DoubleRegister assigned_reg = op.GetDoubleRegister();
- os_ << " \"" << assigned_reg.ToString() << "\"";
+ os_ << " \"" << DoubleRegister::AllocationIndexToString(assigned_reg)
+ << "\"";
} else {
DCHECK(op.IsRegister());
- Register assigned_reg = op.GetRegister();
- os_ << " \"" << assigned_reg.ToString() << "\"";
+ os_ << " \"" << Register::AllocationIndexToString(assigned_reg) << "\"";
}
} else if (range->spilled()) {
auto top = range->TopLevel();
InstructionOperand DefineAsFixed(Node* node, Register reg) {
return Define(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
- reg.code(), GetVReg(node)));
+ Register::ToAllocationIndex(reg),
+ GetVReg(node)));
}
InstructionOperand DefineAsFixed(Node* node, DoubleRegister reg) {
return Define(node,
UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
- reg.code(), GetVReg(node)));
+ DoubleRegister::ToAllocationIndex(reg),
+ GetVReg(node)));
}
InstructionOperand DefineAsConstant(Node* node) {
InstructionOperand UseFixed(Node* node, Register reg) {
return Use(node, UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
- reg.code(), GetVReg(node)));
+ Register::ToAllocationIndex(reg),
+ GetVReg(node)));
}
InstructionOperand UseFixed(Node* node, DoubleRegister reg) {
return Use(node,
UnallocatedOperand(UnallocatedOperand::FIXED_DOUBLE_REGISTER,
- reg.code(), GetVReg(node)));
+ DoubleRegister::ToAllocationIndex(reg),
+ GetVReg(node)));
}
InstructionOperand UseImmediate(Node* node) {
}
InstructionOperand TempRegister(Register reg) {
- return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER, reg.code(),
+ return UnallocatedOperand(UnallocatedOperand::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg),
InstructionOperand::kInvalidVirtualRegister);
}
case UnallocatedOperand::NONE:
return os;
case UnallocatedOperand::FIXED_REGISTER:
- return os << "(="
- << conf->GetGeneralRegisterName(
- unalloc->fixed_register_index())
- << ")";
+ return os << "(=" << conf->general_register_name(
+ unalloc->fixed_register_index()) << ")";
case UnallocatedOperand::FIXED_DOUBLE_REGISTER:
- return os << "(="
- << conf->GetDoubleRegisterName(
- unalloc->fixed_register_index())
- << ")";
+ return os << "(=" << conf->double_register_name(
+ unalloc->fixed_register_index()) << ")";
case UnallocatedOperand::MUST_HAVE_REGISTER:
return os << "(R)";
case UnallocatedOperand::MUST_HAVE_SLOT:
os << "[double_stack:" << DoubleStackSlotOperand::cast(op).index();
break;
case AllocatedOperand::REGISTER:
- os << "[" << RegisterOperand::cast(op).GetRegister().ToString()
+ os << "["
+ << conf->general_register_name(RegisterOperand::cast(op).index())
<< "|R";
break;
case AllocatedOperand::DOUBLE_REGISTER:
- os << "[" << DoubleRegisterOperand::cast(op).GetRegister().ToString()
- << "|R";
+ os << "["
+ << conf->double_register_name(
+ DoubleRegisterOperand::cast(op).index()) << "|R";
break;
}
switch (allocated.machine_type()) {
#include "src/compiler/frame.h"
#include "src/compiler/instruction-codes.h"
#include "src/compiler/opcodes.h"
+#include "src/compiler/register-configuration.h"
#include "src/compiler/source-position.h"
-#include "src/macro-assembler.h"
-#include "src/register-configuration.h"
#include "src/zone-allocator.h"
namespace v8 {
}
int index() const {
- DCHECK(STACK_SLOT == allocated_kind() ||
- DOUBLE_STACK_SLOT == allocated_kind());
return static_cast<int64_t>(value_) >> IndexField::kShift;
}
- Register GetRegister() const {
- DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind());
- return Register::from_code(static_cast<int64_t>(value_) >>
- IndexField::kShift);
- }
-
- DoubleRegister GetDoubleRegister() const {
- DCHECK(REGISTER == allocated_kind() || DOUBLE_REGISTER == allocated_kind());
- return DoubleRegister::from_code(static_cast<int64_t>(value_) >>
- IndexField::kShift);
- }
-
AllocatedKind allocated_kind() const {
return AllocatedKindField::decode(value_);
}
namespace {
LinkageLocation regloc(Register reg) {
- return LinkageLocation::ForRegister(reg.code());
+ return LinkageLocation::ForRegister(Register::ToAllocationIndex(reg));
}
#include "src/compiler/verifier.h"
#include "src/compiler/zone-pool.h"
#include "src/ostreams.h"
-#include "src/register-configuration.h"
#include "src/type-info.h"
#include "src/utils.h"
namespace v8 {
namespace internal {
-
-class RegisterConfiguration;
-
namespace compiler {
class CallDescriptor;
class InstructionSequence;
class Linkage;
class PipelineData;
+class RegisterConfiguration;
class Schedule;
class Pipeline {
return;
case kFixedRegister:
CHECK(op->IsRegister());
- CHECK_EQ(RegisterOperand::cast(op)->GetDoubleRegister().code(),
- constraint->value_);
+ CHECK_EQ(RegisterOperand::cast(op)->index(), constraint->value_);
return;
case kDoubleRegister:
CHECK(op->IsDoubleRegister());
return;
case kFixedDoubleRegister:
CHECK(op->IsDoubleRegister());
- CHECK_EQ(DoubleRegisterOperand::cast(op)->GetDoubleRegister().code(),
- constraint->value_);
+ CHECK_EQ(DoubleRegisterOperand::cast(op)->index(), constraint->value_);
return;
case kFixedSlot:
CHECK(op->IsStackSlot());
int GetRegisterCount(const RegisterConfiguration* cfg, RegisterKind kind) {
- return kind == DOUBLE_REGISTERS ? cfg->num_double_registers()
+ return kind == DOUBLE_REGISTERS ? cfg->num_aliased_double_registers()
: cfg->num_general_registers();
}
-int GetAllocatableRegisterCount(const RegisterConfiguration* cfg,
- RegisterKind kind) {
- return kind == DOUBLE_REGISTERS
- ? cfg->num_allocatable_aliased_double_registers()
- : cfg->num_allocatable_general_registers();
-}
-
-
-const int* GetAllocatableRegisterCodes(const RegisterConfiguration* cfg,
- RegisterKind kind) {
- return kind == DOUBLE_REGISTERS ? cfg->allocatable_double_codes()
- : cfg->allocatable_general_codes();
-}
-
-
const InstructionBlock* GetContainingLoop(const InstructionSequence* sequence,
const InstructionBlock* block) {
auto index = block->loop_header();
}
-bool IsOutputRegisterOf(Instruction* instr, Register reg) {
+bool IsOutputRegisterOf(Instruction* instr, int index) {
for (size_t i = 0; i < instr->OutputCount(); i++) {
auto output = instr->OutputAt(i);
if (output->IsRegister() &&
- RegisterOperand::cast(output)->GetRegister().is(reg)) {
+ RegisterOperand::cast(output)->index() == index) {
return true;
}
}
}
-bool IsOutputDoubleRegisterOf(Instruction* instr, DoubleRegister reg) {
+bool IsOutputDoubleRegisterOf(Instruction* instr, int index) {
for (size_t i = 0; i < instr->OutputCount(); i++) {
auto output = instr->OutputAt(i);
if (output->IsDoubleRegister() &&
- DoubleRegisterOperand::cast(output)->GetDoubleRegister().is(reg)) {
+ DoubleRegisterOperand::cast(output)->index() == index) {
return true;
}
}
}
-bool UsePosition::HintRegister(int* register_code) const {
+bool UsePosition::HintRegister(int* register_index) const {
if (hint_ == nullptr) return false;
switch (HintTypeField::decode(flags_)) {
case UsePositionHintType::kNone:
auto use_pos = reinterpret_cast<UsePosition*>(hint_);
int assigned_register = AssignedRegisterField::decode(use_pos->flags_);
if (assigned_register == kUnassignedRegister) return false;
- *register_code = assigned_register;
+ *register_index = assigned_register;
return true;
}
case UsePositionHintType::kOperand: {
auto operand = reinterpret_cast<InstructionOperand*>(hint_);
- int assigned_register =
- operand->IsRegister()
- ? RegisterOperand::cast(operand)->GetRegister().code()
- : DoubleRegisterOperand::cast(operand)
- ->GetDoubleRegister()
- .code();
- *register_code = assigned_register;
+ int assigned_register = AllocatedOperand::cast(operand)->index();
+ *register_index = assigned_register;
return true;
}
case UsePositionHintType::kPhi: {
auto phi = reinterpret_cast<RegisterAllocationData::PhiMapValue*>(hint_);
int assigned_register = phi->assigned_register();
if (assigned_register == kUnassignedRegister) return false;
- *register_code = assigned_register;
+ *register_index = assigned_register;
return true;
}
}
debug_name_(debug_name),
config_(config),
phi_map_(allocation_zone()),
- allocatable_codes_(this->config()->num_general_registers(), -1,
- allocation_zone()),
- allocatable_double_codes_(this->config()->num_double_registers(), -1,
- allocation_zone()),
live_in_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
live_out_sets_(code->InstructionBlockCount(), nullptr, allocation_zone()),
live_ranges_(code->VirtualRegisterCount() * 2, nullptr,
assigned_registers_ = new (code_zone())
BitVector(this->config()->num_general_registers(), code_zone());
assigned_double_registers_ = new (code_zone())
- BitVector(this->config()->num_double_registers(), code_zone());
+ BitVector(this->config()->num_aliased_double_registers(), code_zone());
this->frame()->SetAllocatedRegisters(assigned_registers_);
this->frame()->SetAllocatedDoubleRegisters(assigned_double_registers_);
}
TopLevelLiveRange* LiveRangeBuilder::FixedDoubleLiveRangeFor(int index) {
- DCHECK(index < config()->num_double_registers());
+ DCHECK(index < config()->num_aliased_double_registers());
auto result = data()->fixed_double_live_ranges()[index];
if (result == nullptr) {
result = data()->NewLiveRange(FixedDoubleLiveRangeID(index), kRepFloat64);
return data()->GetOrCreateLiveRangeFor(
ConstantOperand::cast(operand)->virtual_register());
} else if (operand->IsRegister()) {
- return FixedLiveRangeFor(
- RegisterOperand::cast(operand)->GetRegister().code());
+ return FixedLiveRangeFor(RegisterOperand::cast(operand)->index());
} else if (operand->IsDoubleRegister()) {
return FixedDoubleLiveRangeFor(
- DoubleRegisterOperand::cast(operand)->GetDoubleRegister().code());
+ DoubleRegisterOperand::cast(operand)->index());
} else {
return nullptr;
}
}
if (instr->ClobbersRegisters()) {
- for (int i = 0; i < config()->num_allocatable_general_registers(); ++i) {
- int code = config()->GetAllocatableGeneralCode(i);
- if (!IsOutputRegisterOf(instr, Register::from_code(code))) {
- auto range = FixedLiveRangeFor(code);
+ for (int i = 0; i < config()->num_general_registers(); ++i) {
+ if (!IsOutputRegisterOf(instr, i)) {
+ auto range = FixedLiveRangeFor(i);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
}
if (instr->ClobbersDoubleRegisters()) {
- for (int i = 0; i < config()->num_allocatable_aliased_double_registers();
- ++i) {
- int code = config()->GetAllocatableDoubleCode(i);
- if (!IsOutputDoubleRegisterOf(instr, DoubleRegister::from_code(code))) {
- auto range = FixedDoubleLiveRangeFor(code);
+ for (int i = 0; i < config()->num_aliased_double_registers(); ++i) {
+ if (!IsOutputDoubleRegisterOf(instr, i)) {
+ auto range = FixedDoubleLiveRangeFor(i);
range->AddUseInterval(curr_position, curr_position.End(),
allocation_zone());
}
RegisterKind kind)
: data_(data),
mode_(kind),
- num_registers_(GetRegisterCount(data->config(), kind)),
- num_allocatable_registers_(
- GetAllocatableRegisterCount(data->config(), kind)),
- allocatable_register_codes_(
- GetAllocatableRegisterCodes(data->config(), kind)) {}
+ num_registers_(GetRegisterCount(data->config(), kind)) {}
LiveRange* RegisterAllocator::SplitRangeAt(LiveRange* range,
}
-const char* RegisterAllocator::RegisterName(int register_code) const {
+const char* RegisterAllocator::RegisterName(int allocation_index) const {
if (mode() == GENERAL_REGISTERS) {
- return data()->config()->GetGeneralRegisterName(register_code);
+ return data()->config()->general_register_name(allocation_index);
} else {
- return data()->config()->GetDoubleRegisterName(register_code);
+ return data()->config()->double_register_name(allocation_index);
}
}
for (auto cur_active : active_live_ranges()) {
free_until_pos[cur_active->assigned_register()] =
LifetimePosition::GapFromInstructionIndex(0);
- TRACE("Register %s is free until pos %d (1)\n",
- RegisterName(cur_active->assigned_register()),
- LifetimePosition::GapFromInstructionIndex(0).value());
}
for (auto cur_inactive : inactive_live_ranges()) {
if (!next_intersection.IsValid()) continue;
int cur_reg = cur_inactive->assigned_register();
free_until_pos[cur_reg] = Min(free_until_pos[cur_reg], next_intersection);
- TRACE("Register %s is free until pos %d (2)\n", RegisterName(cur_reg),
- Min(free_until_pos[cur_reg], next_intersection).value());
}
int hint_register;
}
// Find the register which stays free for the longest time.
- int reg = allocatable_register_code(0);
- for (int i = 1; i < num_alloctable_registers(); ++i) {
- int code = allocatable_register_code(i);
- if (free_until_pos[code] > free_until_pos[reg]) {
- reg = code;
+ int reg = 0;
+ for (int i = 1; i < num_registers(); ++i) {
+ if (free_until_pos[i] > free_until_pos[reg]) {
+ reg = i;
}
}
}
}
- int reg = allocatable_register_code(0);
- for (int i = 1; i < num_alloctable_registers(); ++i) {
- int code = allocatable_register_code(i);
- if (use_pos[code] > use_pos[reg]) {
- reg = code;
+ int reg = 0;
+ for (int i = 1; i < num_registers(); ++i) {
+ if (use_pos[i] > use_pos[reg]) {
+ reg = i;
}
}
#include "src/compiler/instruction.h"
#include "src/ostreams.h"
-#include "src/register-configuration.h"
#include "src/zone-containers.h"
namespace v8 {
void set_next(UsePosition* next) { next_ = next; }
// For hinting only.
- void set_assigned_register(int register_code) {
- flags_ = AssignedRegisterField::update(flags_, register_code);
+ void set_assigned_register(int register_index) {
+ flags_ = AssignedRegisterField::update(flags_, register_index);
}
UsePositionHintType hint_type() const {
return HintTypeField::decode(flags_);
}
bool HasHint() const;
- bool HintRegister(int* register_code) const;
+ bool HintRegister(int* register_index) const;
void ResolveHint(UsePosition* use_pos);
bool IsResolved() const {
return hint_type() != UsePositionHintType::kUnresolved;
// For hinting.
int assigned_register() const { return assigned_register_; }
- void set_assigned_register(int register_code) {
+ void set_assigned_register(int register_index) {
DCHECK_EQ(assigned_register_, kUnassignedRegister);
- assigned_register_ = register_code;
+ assigned_register_ = register_index;
}
void UnsetAssignedRegister() { assigned_register_ = kUnassignedRegister; }
const char* const debug_name_;
const RegisterConfiguration* const config_;
PhiMap phi_map_;
- ZoneVector<int> allocatable_codes_;
- ZoneVector<int> allocatable_double_codes_;
ZoneVector<BitVector*> live_in_sets_;
ZoneVector<BitVector*> live_out_sets_;
ZoneVector<TopLevelLiveRange*> live_ranges_;
InstructionSequence* code() const { return data()->code(); }
RegisterKind mode() const { return mode_; }
int num_registers() const { return num_registers_; }
- int num_alloctable_registers() const { return num_allocatable_registers_; }
- int allocatable_register_code(int allocatable_index) const {
- return allocatable_register_codes_[allocatable_index];
- }
Zone* allocation_zone() const { return data()->allocation_zone(); }
RegisterAllocationData* const data_;
const RegisterKind mode_;
const int num_registers_;
- int num_allocatable_registers_;
- const int* allocatable_register_codes_;
DISALLOW_COPY_AND_ASSIGN(RegisterAllocator);
};
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/register-configuration.h"
+#include "src/globals.h"
+#include "src/macro-assembler.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+namespace {
+
+STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
+ Register::kNumRegisters);
+STATIC_ASSERT(RegisterConfiguration::kMaxDoubleRegisters >=
+ DoubleRegister::kMaxNumRegisters);
+
+class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
+ public:
+ ArchDefaultRegisterConfiguration()
+ : RegisterConfiguration(Register::kMaxNumAllocatableRegisters,
+#if V8_TARGET_ARCH_X87
+ 1,
+ 1,
+#else
+ DoubleRegister::NumAllocatableRegisters(),
+ DoubleRegister::NumAllocatableAliasedRegisters(),
+#endif
+ general_register_name_table_,
+ double_register_name_table_) {
+ DCHECK_EQ(Register::kMaxNumAllocatableRegisters,
+ Register::NumAllocatableRegisters());
+ for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
+ general_register_name_table_[i] = Register::AllocationIndexToString(i);
+ }
+ DCHECK_GE(DoubleRegister::kMaxNumAllocatableRegisters,
+ DoubleRegister::NumAllocatableRegisters());
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
+ double_register_name_table_[i] =
+ DoubleRegister::AllocationIndexToString(i);
+ }
+ }
+
+ const char*
+ general_register_name_table_[Register::kMaxNumAllocatableRegisters];
+ const char*
+ double_register_name_table_[DoubleRegister::kMaxNumAllocatableRegisters];
+};
+
+
+static base::LazyInstance<ArchDefaultRegisterConfiguration>::type
+ kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+
+const RegisterConfiguration* RegisterConfiguration::ArchDefault() {
+ return &kDefaultRegisterConfiguration.Get();
+}
+
+RegisterConfiguration::RegisterConfiguration(
+ int num_general_registers, int num_double_registers,
+ int num_aliased_double_registers, const char* const* general_register_names,
+ const char* const* double_register_names)
+ : num_general_registers_(num_general_registers),
+ num_double_registers_(num_double_registers),
+ num_aliased_double_registers_(num_aliased_double_registers),
+ general_register_names_(general_register_names),
+ double_register_names_(double_register_names) {}
+
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
--- /dev/null
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef V8_COMPILER_REGISTER_CONFIGURATION_H_
+#define V8_COMPILER_REGISTER_CONFIGURATION_H_
+
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// An architecture independent representation of the sets of registers available
+// for instruction creation.
+class RegisterConfiguration {
+ public:
+ // Architecture independent maxes.
+ static const int kMaxGeneralRegisters = 32;
+ static const int kMaxDoubleRegisters = 32;
+
+ static const RegisterConfiguration* ArchDefault();
+
+ RegisterConfiguration(int num_general_registers, int num_double_registers,
+ int num_aliased_double_registers,
+ const char* const* general_register_name,
+ const char* const* double_register_name);
+
+ int num_general_registers() const { return num_general_registers_; }
+ int num_double_registers() const { return num_double_registers_; }
+ int num_aliased_double_registers() const {
+ return num_aliased_double_registers_;
+ }
+
+ const char* general_register_name(int offset) const {
+ DCHECK(offset >= 0 && offset < kMaxGeneralRegisters);
+ return general_register_names_[offset];
+ }
+ const char* double_register_name(int offset) const {
+ DCHECK(offset >= 0 && offset < kMaxDoubleRegisters);
+ return double_register_names_[offset];
+ }
+
+ private:
+ const int num_general_registers_;
+ const int num_double_registers_;
+ const int num_aliased_double_registers_;
+ const char* const* general_register_names_;
+ const char* const* double_register_names_;
+};
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_REGISTER_CONFIGURATION_H_
void Translation::StoreDoubleRegister(DoubleRegister reg) {
buffer_->Add(DOUBLE_REGISTER, zone());
- buffer_->Add(reg.code(), zone());
+ buffer_->Add(DoubleRegister::ToAllocationIndex(reg), zone());
}
double value = registers->GetDoubleRegister(input_reg);
if (trace_file != nullptr) {
PrintF(trace_file, "%e ; %s (bool)", value,
- DoubleRegister::from_code(input_reg).ToString());
+ DoubleRegister::AllocationIndexToString(input_reg));
}
return TranslatedValue::NewDouble(this, value);
}
#include "src/deoptimizer.h"
#include "src/frames-inl.h"
#include "src/full-codegen/full-codegen.h"
-#include "src/register-configuration.h"
#include "src/safepoint-table.h"
#include "src/scopeinfo.h"
#include "src/string-stream.h"
if (safepoint_entry.has_doubles()) {
// Number of doubles not known at snapshot time.
DCHECK(!isolate()->serializer_enabled());
- parameters_base += RegisterConfiguration::ArchDefault()
- ->num_allocatable_double_registers() *
- kDoubleSize / kPointerSize;
+ parameters_base += DoubleRegister::NumAllocatableRegisters() *
+ kDoubleSize / kPointerSize;
}
// Visit the registers that contain pointers if any.
int assigned_reg = op->index();
if (op->IsDoubleRegister()) {
trace_.Add(" \"%s\"",
- DoubleRegister::from_code(assigned_reg).ToString());
+ DoubleRegister::AllocationIndexToString(assigned_reg));
} else {
DCHECK(op->IsRegister());
- trace_.Add(" \"%s\"", Register::from_code(assigned_reg).ToString());
+ trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
}
} else if (range->IsSpilled()) {
LOperand* op = range->TopLevel()->GetSpillOperand();
#include "src/assembler.h"
#include "src/compiler.h"
#include "src/isolate.h"
-#include "src/utils.h"
namespace v8 {
namespace internal {
-#define GENERAL_REGISTERS(V) \
- V(eax) \
- V(ecx) \
- V(edx) \
- V(ebx) \
- V(esp) \
- V(ebp) \
- V(esi) \
- V(edi)
-
-#define ALLOCATABLE_GENERAL_REGISTERS(V) \
- V(eax) \
- V(ecx) \
- V(edx) \
- V(ebx) \
- V(esi) \
- V(edi)
-
-#define DOUBLE_REGISTERS(V) \
- V(xmm0) \
- V(xmm1) \
- V(xmm2) \
- V(xmm3) \
- V(xmm4) \
- V(xmm5) \
- V(xmm6) \
- V(xmm7)
-
-#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
- V(xmm1) \
- V(xmm2) \
- V(xmm3) \
- V(xmm4) \
- V(xmm5) \
- V(xmm6) \
- V(xmm7)
-
// CPU Registers.
//
// 1) We would prefer to use an enum, but enum values are assignment-
// and best performance in optimized code.
//
struct Register {
- enum Code {
-#define REGISTER_CODE(R) kCode_##R,
- GENERAL_REGISTERS(REGISTER_CODE)
-#undef REGISTER_CODE
- kAfterLast,
- kCode_no_reg = -1
- };
+ static const int kMaxNumAllocatableRegisters = 6;
+ static int NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+ }
+ static const int kNumRegisters = 8;
+
+ static inline const char* AllocationIndexToString(int index);
- static const int kNumRegisters = Code::kAfterLast;
+ static inline int ToAllocationIndex(Register reg);
+
+ static inline Register FromAllocationIndex(int index);
static Register from_code(int code) {
DCHECK(code >= 0);
DCHECK(code < kNumRegisters);
- Register r = {code};
+ 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_; }
+ // eax, ebx, ecx and edx are byte registers, the rest are not.
+ bool is_byte_register() const { return code_ <= 3; }
int code() const {
DCHECK(is_valid());
- return reg_code;
+ return code_;
}
int bit() const {
DCHECK(is_valid());
- return 1 << reg_code;
+ return 1 << code_;
}
- bool is_byte_register() const { return reg_code <= 3; }
-
// Unfortunately we can't make this private in a struct.
- int reg_code;
+ int code_;
};
+const int kRegister_eax_Code = 0;
+const int kRegister_ecx_Code = 1;
+const int kRegister_edx_Code = 2;
+const int kRegister_ebx_Code = 3;
+const int kRegister_esp_Code = 4;
+const int kRegister_ebp_Code = 5;
+const int kRegister_esi_Code = 6;
+const int kRegister_edi_Code = 7;
+const int kRegister_no_reg_Code = -1;
+
+const Register eax = { kRegister_eax_Code };
+const Register ecx = { kRegister_ecx_Code };
+const Register edx = { kRegister_edx_Code };
+const Register ebx = { kRegister_ebx_Code };
+const Register esp = { kRegister_esp_Code };
+const Register ebp = { kRegister_ebp_Code };
+const Register esi = { kRegister_esi_Code };
+const Register edi = { kRegister_edi_Code };
+const Register no_reg = { kRegister_no_reg_Code };
+
+
+inline const char* Register::AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ // This is the mapping of allocation indices to registers.
+ const char* const kNames[] = { "eax", "ecx", "edx", "ebx", "esi", "edi" };
+ return kNames[index];
+}
+
+
+inline int Register::ToAllocationIndex(Register reg) {
+ DCHECK(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
+ return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
+}
+
+
+inline Register Register::FromAllocationIndex(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ return (index >= 4) ? from_code(index + 2) : from_code(index);
+}
+
-#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};
+struct XMMRegister {
+ static const int kMaxNumAllocatableRegisters = 7;
+ static const int kMaxNumRegisters = 8;
+ static int NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+ }
+ // TODO(turbofan): Proper support for float32.
+ static int NumAllocatableAliasedRegisters() {
+ return NumAllocatableRegisters();
+ }
-struct DoubleRegister {
- enum Code {
-#define REGISTER_CODE(R) kCode_##R,
- DOUBLE_REGISTERS(REGISTER_CODE)
-#undef REGISTER_CODE
- kAfterLast,
- kCode_no_reg = -1
- };
+ static int ToAllocationIndex(XMMRegister reg) {
+ DCHECK(reg.code() != 0);
+ return reg.code() - 1;
+ }
- static const int kMaxNumRegisters = Code::kAfterLast;
+ static XMMRegister FromAllocationIndex(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ return from_code(index + 1);
+ }
- static DoubleRegister from_code(int code) {
- DoubleRegister result = {code};
+ static XMMRegister from_code(int code) {
+ XMMRegister result = { code };
return result;
}
- bool IsAllocatable() const;
- bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
+ bool is_valid() const {
+ return 0 <= code_ && code_ < kMaxNumRegisters;
+ }
int code() const {
DCHECK(is_valid());
- return reg_code;
+ return code_;
}
- bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
+ bool is(XMMRegister reg) const { return code_ == reg.code_; }
- const char* ToString();
+ static const char* AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ const char* const names[] = {
+ "xmm1",
+ "xmm2",
+ "xmm3",
+ "xmm4",
+ "xmm5",
+ "xmm6",
+ "xmm7"
+ };
+ return names[index];
+ }
- int reg_code;
+ int code_;
};
-#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};
-typedef DoubleRegister XMMRegister;
+typedef XMMRegister DoubleRegister;
+
+
+const XMMRegister xmm0 = { 0 };
+const XMMRegister xmm1 = { 1 };
+const XMMRegister xmm2 = { 2 };
+const XMMRegister xmm3 = { 3 };
+const XMMRegister xmm4 = { 4 };
+const XMMRegister xmm5 = { 5 };
+const XMMRegister xmm6 = { 6 };
+const XMMRegister xmm7 = { 7 };
+const XMMRegister no_xmm_reg = { -1 };
+
enum Condition {
// any value < 0 is considered no_condition
Register GetRegThatIsNotEcxOr(Register r1,
Register r2,
Register r3) {
- for (int i = 0; i < Register::kNumRegisters; i++) {
- Register candidate = Register::from_code(i);
- if (candidate.IsAllocatable()) {
- if (candidate.is(ecx)) continue;
- if (candidate.is(r1)) continue;
- if (candidate.is(r2)) continue;
- if (candidate.is(r3)) continue;
- return candidate;
- }
+ for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+ Register candidate = Register::FromAllocationIndex(i);
+ if (candidate.is(ecx)) continue;
+ if (candidate.is(r1)) continue;
+ if (candidate.is(r2)) continue;
+ if (candidate.is(r3)) continue;
+ return candidate;
}
UNREACHABLE();
return no_reg;
#include "src/deoptimizer.h"
#include "src/full-codegen/full-codegen.h"
#include "src/ia32/frames-ia32.h"
-#include "src/register-configuration.h"
#include "src/safepoint-table.h"
namespace v8 {
}
input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp()));
input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp()));
- for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; i++) {
input_->SetDoubleRegister(i, 0.0);
}
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
- for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) {
+ for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
double double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
// Save all general purpose registers before messing with them.
const int kNumberOfRegisters = Register::kNumRegisters;
- const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters;
+ const int kDoubleRegsSize = kDoubleSize *
+ XMMRegister::kMaxNumAllocatableRegisters;
__ sub(esp, Immediate(kDoubleRegsSize));
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- XMMRegister xmm_reg = XMMRegister::from_code(code);
- int offset = code * kDoubleSize;
+ for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
+ XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
+ int offset = i * kDoubleSize;
__ movsd(Operand(esp, offset), xmm_reg);
}
int double_regs_offset = FrameDescription::double_registers_offset();
// Fill in the double input registers.
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- int dst_offset = code * kDoubleSize + double_regs_offset;
- int src_offset = code * kDoubleSize;
+ for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
+ int dst_offset = i * kDoubleSize + double_regs_offset;
+ int src_offset = i * kDoubleSize;
__ movsd(xmm0, Operand(esp, src_offset));
__ movsd(Operand(ebx, dst_offset), xmm0);
}
__ j(below, &outer_push_loop);
// In case of a failed STUB, we have to restore the XMM registers.
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- XMMRegister xmm_reg = XMMRegister::from_code(code);
- int src_offset = code * kDoubleSize + double_regs_offset;
+ for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
+ XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
+ int src_offset = i * kDoubleSize + double_regs_offset;
__ movsd(xmm_reg, Operand(ebx, src_offset));
}
BitVector::Iterator save_iterator(doubles);
while (!save_iterator.Done()) {
__ movsd(MemOperand(esp, count * kDoubleSize),
- XMMRegister::from_code(save_iterator.Current()));
+ XMMRegister::FromAllocationIndex(save_iterator.Current()));
save_iterator.Advance();
count++;
}
BitVector::Iterator save_iterator(doubles);
int count = 0;
while (!save_iterator.Done()) {
- __ movsd(XMMRegister::from_code(save_iterator.Current()),
- MemOperand(esp, count * kDoubleSize));
+ __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
+ MemOperand(esp, count * kDoubleSize));
save_iterator.Advance();
count++;
}
}
-Register LCodeGen::ToRegister(int code) const {
- return Register::from_code(code);
+Register LCodeGen::ToRegister(int index) const {
+ return Register::FromAllocationIndex(index);
}
-XMMRegister LCodeGen::ToDoubleRegister(int code) const {
- return XMMRegister::from_code(code);
+XMMRegister LCodeGen::ToDoubleRegister(int index) const {
+ return XMMRegister::FromAllocationIndex(index);
}
#include "src/ia32/lithium-codegen-ia32.h"
#include "src/ia32/lithium-gap-resolver-ia32.h"
-#include "src/register-configuration.h"
namespace v8 {
namespace internal {
Register LGapResolver::GetFreeRegisterNot(Register reg) {
- int skip_index = reg.is(no_reg) ? -1 : reg.code();
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
- int code = config->GetAllocatableGeneralCode(i);
- if (source_uses_[code] == 0 && destination_uses_[code] > 0 &&
- code != skip_index) {
- return Register::from_code(code);
+ int skip_index = reg.is(no_reg) ? -1 : Register::ToAllocationIndex(reg);
+ for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
+ if (source_uses_[i] == 0 && destination_uses_[i] > 0 && i != skip_index) {
+ return Register::FromAllocationIndex(i);
}
}
return no_reg;
bool LGapResolver::HasBeenReset() {
if (!moves_.is_empty()) return false;
if (spilled_register_ >= 0) return false;
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
- int code = config->GetAllocatableGeneralCode(i);
- if (source_uses_[code] != 0) return false;
- if (destination_uses_[code] != 0) return false;
+
+ for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
+ if (source_uses_[i] != 0) return false;
+ if (destination_uses_[i] != 0) return false;
}
return true;
}
void LGapResolver::Finish() {
if (spilled_register_ >= 0) {
- __ pop(Register::from_code(spilled_register_));
+ __ pop(Register::FromAllocationIndex(spilled_register_));
spilled_register_ = -1;
}
moves_.Rewind(0);
void LGapResolver::EnsureRestored(LOperand* operand) {
if (operand->IsRegister() && operand->index() == spilled_register_) {
- __ pop(Register::from_code(spilled_register_));
+ __ pop(Register::FromAllocationIndex(spilled_register_));
spilled_register_ = -1;
}
}
Register LGapResolver::EnsureTempRegister() {
// 1. We may have already spilled to create a temp register.
if (spilled_register_ >= 0) {
- return Register::from_code(spilled_register_);
+ return Register::FromAllocationIndex(spilled_register_);
}
// 2. We may have a free register that we can use without spilling.
// 3. Prefer to spill a register that is not used in any remaining move
// because it will not need to be restored until the end.
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
- int code = config->GetAllocatableGeneralCode(i);
- if (source_uses_[code] == 0 && destination_uses_[code] == 0) {
- Register scratch = Register::from_code(code);
+ for (int i = 0; i < Register::NumAllocatableRegisters(); ++i) {
+ if (source_uses_[i] == 0 && destination_uses_[i] == 0) {
+ Register scratch = Register::FromAllocationIndex(i);
__ push(scratch);
- spilled_register_ = code;
+ spilled_register_ = i;
return scratch;
}
}
// 4. Use an arbitrary register. Register 0 is as arbitrary as any other.
- spilled_register_ = config->GetAllocatableGeneralCode(0);
- Register scratch = Register::from_code(spilled_register_);
+ Register scratch = Register::FromAllocationIndex(0);
__ push(scratch);
+ spilled_register_ = 0;
return scratch;
}
ZoneList<LMoveOperands> moves_;
// Source and destination use counts for the general purpose registers.
- int source_uses_[Register::kNumRegisters];
- int destination_uses_[DoubleRegister::kMaxNumRegisters];
+ int source_uses_[Register::kMaxNumAllocatableRegisters];
+ int destination_uses_[Register::kMaxNumAllocatableRegisters];
// If we had to spill on demand, the currently spilled register's
// allocation index.
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
- return new (zone())
- LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ XMMRegister::ToAllocationIndex(reg));
}
namespace internal {
// Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {Register::kCode_eax};
-const Register kReturnRegister1 = {Register::kCode_edx};
-const Register kJSFunctionRegister = {Register::kCode_edi};
-const Register kContextRegister = {Register::kCode_esi};
-const Register kInterpreterAccumulatorRegister = {Register::kCode_eax};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
-const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
-const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
-const Register kInterpreterDispatchTableRegister = {Register::kCode_ebx};
-const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
-const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
+const Register kReturnRegister0 = {kRegister_eax_Code};
+const Register kReturnRegister1 = {kRegister_edx_Code};
+const Register kJSFunctionRegister = {kRegister_edi_Code};
+const Register kContextRegister = {kRegister_esi_Code};
+const Register kInterpreterAccumulatorRegister = {kRegister_eax_Code};
+const Register kInterpreterRegisterFileRegister = {kRegister_edx_Code};
+const Register kInterpreterBytecodeOffsetRegister = {kRegister_ecx_Code};
+const Register kInterpreterBytecodeArrayRegister = {kRegister_edi_Code};
+const Register kInterpreterDispatchTableRegister = {kRegister_ebx_Code};
+const Register kRuntimeCallFunctionRegister = {kRegister_ebx_Code};
+const Register kRuntimeCallArgCountRegister = {kRegister_eax_Code};
// Spill slots used by interpreter dispatch calling convention.
const int kInterpreterContextSpillSlot = -1;
#include "src/hydrogen.h"
#include "src/lithium-inl.h"
#include "src/lithium-allocator-inl.h"
-#include "src/register-configuration.h"
#include "src/string-stream.h"
namespace v8 {
int LAllocator::FixedDoubleLiveRangeID(int index) {
- return -index - 1 - Register::kNumRegisters;
+ return -index - 1 - Register::kMaxNumAllocatableRegisters;
}
LiveRange* LAllocator::FixedLiveRangeFor(int index) {
- DCHECK(index < Register::kNumRegisters);
+ DCHECK(index < Register::kMaxNumAllocatableRegisters);
LiveRange* result = fixed_live_ranges_[index];
if (result == NULL) {
result = new(zone()) LiveRange(FixedLiveRangeID(index), chunk()->zone());
LiveRange* LAllocator::FixedDoubleLiveRangeFor(int index) {
- DCHECK(index < DoubleRegister::kMaxNumRegisters);
+ DCHECK(index < DoubleRegister::NumAllocatableRegisters());
LiveRange* result = fixed_double_live_ranges_[index];
if (result == NULL) {
result = new(zone()) LiveRange(FixedDoubleLiveRangeID(index),
}
if (instr->ClobbersRegisters()) {
- for (int i = 0; i < Register::kNumRegisters; ++i) {
- if (Register::from_code(i).IsAllocatable()) {
- if (output == NULL || !output->IsRegister() ||
- output->index() != i) {
- LiveRange* range = FixedLiveRangeFor(i);
- range->AddUseInterval(curr_position,
- curr_position.InstructionEnd(), zone());
- }
+ for (int i = 0; i < Register::kMaxNumAllocatableRegisters; ++i) {
+ if (output == NULL || !output->IsRegister() ||
+ output->index() != i) {
+ LiveRange* range = FixedLiveRangeFor(i);
+ range->AddUseInterval(curr_position,
+ curr_position.InstructionEnd(),
+ zone());
}
}
}
if (instr->ClobbersDoubleRegisters(isolate())) {
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; ++i) {
- if (DoubleRegister::from_code(i).IsAllocatable()) {
- if (output == NULL || !output->IsDoubleRegister() ||
- output->index() != i) {
- LiveRange* range = FixedDoubleLiveRangeFor(i);
- range->AddUseInterval(curr_position,
- curr_position.InstructionEnd(), zone());
- }
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
+ if (output == NULL || !output->IsDoubleRegister() ||
+ output->index() != i) {
+ LiveRange* range = FixedDoubleLiveRangeFor(i);
+ range->AddUseInterval(curr_position,
+ curr_position.InstructionEnd(),
+ zone());
}
}
}
DCHECK(chunk_ == NULL);
chunk_ = static_cast<LPlatformChunk*>(chunk);
assigned_registers_ =
- new (chunk->zone()) BitVector(Register::kNumRegisters, chunk->zone());
- assigned_double_registers_ = new (chunk->zone())
- BitVector(DoubleRegister::kMaxNumRegisters, chunk->zone());
+ new(chunk->zone()) BitVector(Register::NumAllocatableRegisters(),
+ chunk->zone());
+ assigned_double_registers_ =
+ new(chunk->zone()) BitVector(DoubleRegister::NumAllocatableRegisters(),
+ chunk->zone());
MeetRegisterConstraints();
if (!AllocationOk()) return false;
ResolvePhis();
void LAllocator::AllocateGeneralRegisters() {
LAllocatorPhase phase("L_Allocate general registers", this);
- num_registers_ =
- RegisterConfiguration::ArchDefault()->num_allocatable_general_registers();
- allocatable_register_codes_ =
- RegisterConfiguration::ArchDefault()->allocatable_general_codes();
+ num_registers_ = Register::NumAllocatableRegisters();
mode_ = GENERAL_REGISTERS;
AllocateRegisters();
}
void LAllocator::AllocateDoubleRegisters() {
LAllocatorPhase phase("L_Allocate double registers", this);
- num_registers_ =
- RegisterConfiguration::ArchDefault()->num_allocatable_double_registers();
- allocatable_register_codes_ =
- RegisterConfiguration::ArchDefault()->allocatable_double_codes();
+ num_registers_ = DoubleRegister::NumAllocatableRegisters();
mode_ = DOUBLE_REGISTERS;
AllocateRegisters();
}
DCHECK(inactive_live_ranges_.is_empty());
if (mode_ == DOUBLE_REGISTERS) {
- for (int i = 0; i < fixed_double_live_ranges_.length(); ++i) {
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); ++i) {
LiveRange* current = fixed_double_live_ranges_.at(i);
if (current != NULL) {
AddToInactive(current);
const char* LAllocator::RegisterName(int allocation_index) {
if (mode_ == GENERAL_REGISTERS) {
- return Register::from_code(allocation_index).ToString();
+ return Register::AllocationIndexToString(allocation_index);
} else {
- return DoubleRegister::from_code(allocation_index).ToString();
+ return DoubleRegister::AllocationIndexToString(allocation_index);
}
}
}
-bool LAllocator::TryAllocateFreeReg(LiveRange* current) {
- DCHECK(DoubleRegister::kMaxNumRegisters >= Register::kNumRegisters);
+// TryAllocateFreeReg and AllocateBlockedReg assume this
+// when allocating local arrays.
+STATIC_ASSERT(DoubleRegister::kMaxNumAllocatableRegisters >=
+ Register::kMaxNumAllocatableRegisters);
- LifetimePosition free_until_pos[DoubleRegister::kMaxNumRegisters];
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
+bool LAllocator::TryAllocateFreeReg(LiveRange* current) {
+ LifetimePosition free_until_pos[DoubleRegister::kMaxNumAllocatableRegisters];
+
+ for (int i = 0; i < num_registers_; i++) {
free_until_pos[i] = LifetimePosition::MaxPosition();
}
}
// Find the register which stays free for the longest time.
- int reg = allocatable_register_codes_[0];
+ int reg = 0;
for (int i = 1; i < RegisterCount(); ++i) {
- int code = allocatable_register_codes_[i];
- if (free_until_pos[code].Value() > free_until_pos[reg].Value()) {
- reg = code;
+ if (free_until_pos[i].Value() > free_until_pos[reg].Value()) {
+ reg = i;
}
}
}
- LifetimePosition use_pos[DoubleRegister::kMaxNumRegisters];
- LifetimePosition block_pos[DoubleRegister::kMaxNumRegisters];
+ LifetimePosition use_pos[DoubleRegister::kMaxNumAllocatableRegisters];
+ LifetimePosition block_pos[DoubleRegister::kMaxNumAllocatableRegisters];
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < num_registers_; i++) {
use_pos[i] = block_pos[i] = LifetimePosition::MaxPosition();
}
}
}
- int reg = allocatable_register_codes_[0];
+ int reg = 0;
for (int i = 1; i < RegisterCount(); ++i) {
- int code = allocatable_register_codes_[i];
- if (use_pos[code].Value() > use_pos[reg].Value()) {
- reg = code;
+ if (use_pos[i].Value() > use_pos[reg].Value()) {
+ reg = i;
}
}
ZoneList<LiveRange*> live_ranges_;
// Lists of live ranges
- EmbeddedVector<LiveRange*, Register::kNumRegisters> fixed_live_ranges_;
- EmbeddedVector<LiveRange*, DoubleRegister::kMaxNumRegisters>
+ EmbeddedVector<LiveRange*, Register::kMaxNumAllocatableRegisters>
+ fixed_live_ranges_;
+ EmbeddedVector<LiveRange*, DoubleRegister::kMaxNumAllocatableRegisters>
fixed_double_live_ranges_;
ZoneList<LiveRange*> unhandled_live_ranges_;
ZoneList<LiveRange*> active_live_ranges_;
RegisterKind mode_;
int num_registers_;
- const int* allocatable_register_codes_;
BitVector* assigned_registers_;
BitVector* assigned_double_registers_;
break;
case LUnallocated::FIXED_REGISTER: {
int reg_index = unalloc->fixed_register_index();
- if (reg_index < 0 || reg_index >= Register::kNumRegisters) {
+ if (reg_index < 0 ||
+ reg_index >= Register::kMaxNumAllocatableRegisters) {
stream->Add("(=invalid_reg#%d)", reg_index);
} else {
const char* register_name =
- Register::from_code(reg_index).ToString();
+ Register::AllocationIndexToString(reg_index);
stream->Add("(=%s)", register_name);
}
break;
}
case LUnallocated::FIXED_DOUBLE_REGISTER: {
int reg_index = unalloc->fixed_register_index();
- if (reg_index < 0 || reg_index >= DoubleRegister::kMaxNumRegisters) {
+ if (reg_index < 0 ||
+ reg_index >= DoubleRegister::kMaxNumAllocatableRegisters) {
stream->Add("(=invalid_double_reg#%d)", reg_index);
} else {
const char* double_register_name =
- DoubleRegister::from_code(reg_index).ToString();
+ DoubleRegister::AllocationIndexToString(reg_index);
stream->Add("(=%s)", double_register_name);
}
break;
break;
case REGISTER: {
int reg_index = index();
- if (reg_index < 0 || reg_index >= Register::kNumRegisters) {
+ if (reg_index < 0 || reg_index >= Register::kMaxNumAllocatableRegisters) {
stream->Add("(=invalid_reg#%d|R)", reg_index);
} else {
- stream->Add("[%s|R]", Register::from_code(reg_index).ToString());
+ stream->Add("[%s|R]", Register::AllocationIndexToString(reg_index));
}
break;
}
case DOUBLE_REGISTER: {
int reg_index = index();
- if (reg_index < 0 || reg_index >= DoubleRegister::kMaxNumRegisters) {
+ if (reg_index < 0 ||
+ reg_index >= DoubleRegister::kMaxNumAllocatableRegisters) {
stream->Add("(=invalid_double_reg#%d|R)", reg_index);
} else {
- stream->Add("[%s|R]", DoubleRegister::from_code(reg_index).ToString());
+ stream->Add("[%s|R]",
+ DoubleRegister::AllocationIndexToString(reg_index));
}
break;
}
}
+int Register::NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+}
+
+
+int DoubleRegister::NumRegisters() {
+ return FPURegister::kMaxNumRegisters;
+}
+
+
+int DoubleRegister::NumAllocatableRegisters() {
+ return FPURegister::kMaxNumAllocatableRegisters;
+}
+
+
+int DoubleRegister::NumAllocatableAliasedRegisters() {
+ return NumAllocatableRegisters();
+}
+
+
+int FPURegister::ToAllocationIndex(FPURegister reg) {
+ DCHECK(reg.code() % 2 == 0);
+ DCHECK(reg.code() / 2 < kMaxNumAllocatableRegisters);
+ DCHECK(reg.is_valid());
+ DCHECK(!reg.is(kDoubleRegZero));
+ DCHECK(!reg.is(kLithiumScratchDouble));
+ return (reg.code() / 2);
+}
+
+
// -----------------------------------------------------------------------------
// RelocInfo.
}
+const char* DoubleRegister::AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ const char* const names[] = {
+ "f0",
+ "f2",
+ "f4",
+ "f6",
+ "f8",
+ "f10",
+ "f12",
+ "f14",
+ "f16",
+ "f18",
+ "f20",
+ "f22",
+ "f24",
+ "f26"
+ };
+ return names[index];
+}
+
+
void CpuFeatures::ProbeImpl(bool cross_compile) {
supported_ |= CpuFeaturesImpliedByCompiler();
static const int kNegOffset = 0x00008000;
// addiu(sp, sp, 4) aka Pop() operation or part of Pop(r)
// operations as post-increment of sp.
-const Instr kPopInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
- (Register::kCode_sp << kRtShift) |
- (kPointerSize & kImm16Mask); // NOLINT
+const Instr kPopInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
+ | (kRegister_sp_Code << kRtShift)
+ | (kPointerSize & kImm16Mask); // NOLINT
// addiu(sp, sp, -4) part of Push(r) operation as pre-decrement of sp.
-const Instr kPushInstruction = ADDIU | (Register::kCode_sp << kRsShift) |
- (Register::kCode_sp << kRtShift) |
- (-kPointerSize & kImm16Mask); // NOLINT
+const Instr kPushInstruction = ADDIU | (kRegister_sp_Code << kRsShift)
+ | (kRegister_sp_Code << kRtShift)
+ | (-kPointerSize & kImm16Mask); // NOLINT
// sw(r, MemOperand(sp, 0))
-const Instr kPushRegPattern =
- SW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kPushRegPattern = SW | (kRegister_sp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
// lw(r, MemOperand(sp, 0))
-const Instr kPopRegPattern =
- LW | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kPopRegPattern = LW | (kRegister_sp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
-const Instr kLwRegFpOffsetPattern =
- LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
-const Instr kSwRegFpOffsetPattern =
- SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
-const Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
- (kNegOffset & kImm16Mask); // NOLINT
+const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
+ | (kNegOffset & kImm16Mask); // NOLINT
-const Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
- (kNegOffset & kImm16Mask); // NOLINT
+const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
+ | (kNegOffset & kImm16Mask); // NOLINT
// A mask for the Rt register for push, pop, lw, sw instructions.
const Instr kRtMask = kRtFieldMask;
const Instr kLwSwInstrTypeMask = 0xffe00000;
Register Assembler::GetRtReg(Instr instr) {
Register rt;
- rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
+ rt.code_ = (instr & kRtFieldMask) >> kRtShift;
return rt;
}
Register Assembler::GetRsReg(Instr instr) {
Register rs;
- rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
+ rs.code_ = (instr & kRsFieldMask) >> kRsShift;
return rs;
}
Register Assembler::GetRdReg(Instr instr) {
Register rd;
- rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
+ rd.code_ = (instr & kRdFieldMask) >> kRdShift;
return rd;
}
void Assembler::movt(Register rd, Register rs, uint16_t cc) {
Register rt;
- rt.reg_code = (cc & 0x0007) << 2 | 1;
+ rt.code_ = (cc & 0x0007) << 2 | 1;
GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
}
void Assembler::movf(Register rd, Register rs, uint16_t cc) {
Register rt;
- rt.reg_code = (cc & 0x0007) << 2 | 0;
+ rt.code_ = (cc & 0x0007) << 2 | 0;
GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
}
void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(IsMipsArchVariant(kMips32r2));
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 1;
+ ft.code_ = (cc & 0x0007) << 2 | 1;
GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
}
void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(IsMipsArchVariant(kMips32r2));
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 1;
+ ft.code_ = (cc & 0x0007) << 2 | 1;
GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
}
void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(IsMipsArchVariant(kMips32r2));
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 0;
+ ft.code_ = (cc & 0x0007) << 2 | 0;
GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
}
void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(IsMipsArchVariant(kMips32r2));
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 0;
+ ft.code_ = (cc & 0x0007) << 2 | 0;
GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
}
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(t0) V(t1) V(t2) V(t3) V(t4) V(t5) V(t6) V(t7) \
- 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(t0) V(t1) V(t2) V(t3) V(t4) V(t5) V(t6) 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-
// -----------------------------------------------------------------------------
// Implementation of Register and FPURegister.
+// Core register.
struct Register {
+ static const int kNumRegisters = v8::internal::kNumRegisters;
+ static const int kMaxNumAllocatableRegisters = 14; // v0 through t6 and cp.
+ static const int kSizeInBytes = 4;
static const int kCpRegister = 23; // cp (s7) is the 23rd register.
- 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;
-
#if defined(V8_TARGET_LITTLE_ENDIAN)
static const int kMantissaOffset = 0;
static const int kExponentOffset = 4;
#error Unknown endianness
#endif
+ 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",
+ "t0",
+ "t1",
+ "t2",
+ "t3",
+ "t4",
+ "t5",
+ "t6",
+ "s7",
+ };
+ return names[index];
+ }
static Register from_code(int code) {
- DCHECK(code >= 0);
- DCHECK(code < kNumRegisters);
- Register r = {code};
+ 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);
+// t0 - t9: Can be used without reservation, act as temporary registers and are
+// allowed to be destroyed by subroutines.
+REGISTER(t0, 8);
+REGISTER(t1, 9);
+REGISTER(t2, 10);
+REGISTER(t3, 11);
+REGISTER(t4, 12);
+REGISTER(t5, 13);
+REGISTER(t6, 14);
+REGISTER(t7, 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);
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 {
// 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 {
// 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
// in pairs, starting with the even numbered register. So a double operation
// 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.
// 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 };
#include "src/codegen.h"
#include "src/deoptimizer.h"
#include "src/full-codegen/full-codegen.h"
-#include "src/register-configuration.h"
#include "src/safepoint-table.h"
namespace v8 {
}
input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
input_->SetDoubleRegister(i, 0.0);
}
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
- const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters;
+ const int kDoubleRegsSize =
+ kDoubleSize * FPURegister::kMaxNumAllocatableRegisters;
// Save all FPU registers before messing with them.
__ Subu(sp, sp, Operand(kDoubleRegsSize));
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
- int offset = code * kDoubleSize;
+ for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
+ FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
+ int offset = i * kDoubleSize;
__ sdc1(fpu_reg, MemOperand(sp, offset));
}
int double_regs_offset = FrameDescription::double_registers_offset();
// Copy FPU registers to
// double_registers_[DoubleRegister::kNumAllocatableRegisters]
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- int dst_offset = code * kDoubleSize + double_regs_offset;
- int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize;
+ for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
+ int dst_offset = i * kDoubleSize + double_regs_offset;
+ int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
__ ldc1(f0, MemOperand(sp, src_offset));
__ sdc1(f0, MemOperand(a1, dst_offset));
}
__ BranchShort(&outer_push_loop, lt, t0, Operand(a1));
__ lw(a1, MemOperand(a0, Deoptimizer::input_offset()));
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
- int src_offset = code * kDoubleSize + double_regs_offset;
+ for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
+ const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
+ int src_offset = i * kDoubleSize + double_regs_offset;
__ ldc1(fpu_reg, MemOperand(a1, src_offset));
}
BitVector* doubles = chunk()->allocated_double_registers();
BitVector::Iterator save_iterator(doubles);
while (!save_iterator.Done()) {
- __ sdc1(DoubleRegister::from_code(save_iterator.Current()),
+ __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
MemOperand(sp, count * kDoubleSize));
save_iterator.Advance();
count++;
BitVector::Iterator save_iterator(doubles);
int count = 0;
while (!save_iterator.Done()) {
- __ ldc1(DoubleRegister::from_code(save_iterator.Current()),
+ __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
MemOperand(sp, count * kDoubleSize));
save_iterator.Advance();
count++;
Register LCodeGen::ToRegister(int index) const {
- return Register::from_code(index);
+ return Register::FromAllocationIndex(index);
}
DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
- return DoubleRegister::from_code(index);
+ return DoubleRegister::FromAllocationIndex(index);
}
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
- return new (zone())
- LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg));
}
#include "src/cpu-profiler.h"
#include "src/debug/debug.h"
#include "src/mips/macro-assembler-mips.h"
-#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
namespace v8 {
MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
UNIMPLEMENTED_MIPS();
// General purpose registers are pushed last on the stack.
- int doubles_size = DoubleRegister::kMaxNumRegisters * kDoubleSize;
+ int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize;
int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
return MemOperand(sp, doubles_size + register_offset);
}
// Find a temp register in temps list.
for (int i = 0; i < kNumRegisters; i++) {
if ((temps & (1 << i)) != 0) {
- tmp.reg_code = i;
+ tmp.code_ = i;
break;
}
}
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
- int code = config->GetAllocatableGeneralCode(i);
- Register candidate = Register::from_code(code);
+ for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+ Register candidate = Register::FromAllocationIndex(i);
if (regs & candidate.bit()) continue;
return candidate;
}
namespace internal {
// Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {Register::kCode_v0};
-const Register kReturnRegister1 = {Register::kCode_v1};
-const Register kJSFunctionRegister = {Register::kCode_a1};
+const Register kReturnRegister0 = {kRegister_v0_Code};
+const Register kReturnRegister1 = {kRegister_v1_Code};
+const Register kJSFunctionRegister = {kRegister_a1_Code};
const Register kContextRegister = {Register::kCpRegister};
-const Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_t3};
-const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t4};
-const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t5};
-const Register kInterpreterDispatchTableRegister = {Register::kCode_t6};
-const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
-const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
+const Register kInterpreterAccumulatorRegister = {kRegister_v0_Code};
+const Register kInterpreterRegisterFileRegister = {kRegister_t3_Code};
+const Register kInterpreterBytecodeOffsetRegister = {kRegister_t4_Code};
+const Register kInterpreterBytecodeArrayRegister = {kRegister_t5_Code};
+const Register kInterpreterDispatchTableRegister = {kRegister_t6_Code};
+const Register kRuntimeCallFunctionRegister = {kRegister_a1_Code};
+const Register kRuntimeCallArgCountRegister = {kRegister_a0_Code};
// Forward declaration.
class JumpTarget;
}
+int Register::NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+}
+
+
+int DoubleRegister::NumRegisters() {
+ return FPURegister::kMaxNumRegisters;
+}
+
+
+int DoubleRegister::NumAllocatableRegisters() {
+ return FPURegister::kMaxNumAllocatableRegisters;
+}
+
+
+int DoubleRegister::NumAllocatableAliasedRegisters() {
+ return NumAllocatableRegisters();
+}
+
+
+int FPURegister::ToAllocationIndex(FPURegister reg) {
+ DCHECK(reg.code() % 2 == 0);
+ DCHECK(reg.code() / 2 < kMaxNumAllocatableRegisters);
+ DCHECK(reg.is_valid());
+ DCHECK(!reg.is(kDoubleRegZero));
+ DCHECK(!reg.is(kLithiumScratchDouble));
+ return (reg.code() / 2);
+}
+
+
// -----------------------------------------------------------------------------
// RelocInfo.
}
+const char* DoubleRegister::AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ const char* const names[] = {
+ "f0",
+ "f2",
+ "f4",
+ "f6",
+ "f8",
+ "f10",
+ "f12",
+ "f14",
+ "f16",
+ "f18",
+ "f20",
+ "f22",
+ "f24",
+ "f26"
+ };
+ return names[index];
+}
+
+
void CpuFeatures::ProbeImpl(bool cross_compile) {
supported_ |= CpuFeaturesImpliedByCompiler();
static const int kNegOffset = 0x00008000;
// daddiu(sp, sp, 8) aka Pop() operation or part of Pop(r)
// operations as post-increment of sp.
-const Instr kPopInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
- (Register::kCode_sp << kRtShift) |
- (kPointerSize & kImm16Mask); // NOLINT
+const Instr kPopInstruction = DADDIU | (kRegister_sp_Code << kRsShift)
+ | (kRegister_sp_Code << kRtShift)
+ | (kPointerSize & kImm16Mask); // NOLINT
// daddiu(sp, sp, -8) part of Push(r) operation as pre-decrement of sp.
-const Instr kPushInstruction = DADDIU | (Register::kCode_sp << kRsShift) |
- (Register::kCode_sp << kRtShift) |
- (-kPointerSize & kImm16Mask); // NOLINT
+const Instr kPushInstruction = DADDIU | (kRegister_sp_Code << kRsShift)
+ | (kRegister_sp_Code << kRtShift)
+ | (-kPointerSize & kImm16Mask); // NOLINT
// sd(r, MemOperand(sp, 0))
-const Instr kPushRegPattern =
- SD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kPushRegPattern = SD | (kRegister_sp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
// ld(r, MemOperand(sp, 0))
-const Instr kPopRegPattern =
- LD | (Register::kCode_sp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kPopRegPattern = LD | (kRegister_sp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
-const Instr kLwRegFpOffsetPattern =
- LW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kLwRegFpOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
-const Instr kSwRegFpOffsetPattern =
- SW | (Register::kCode_fp << kRsShift) | (0 & kImm16Mask); // NOLINT
+const Instr kSwRegFpOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
+ | (0 & kImm16Mask); // NOLINT
-const Instr kLwRegFpNegOffsetPattern = LW | (Register::kCode_fp << kRsShift) |
- (kNegOffset & kImm16Mask); // NOLINT
+const Instr kLwRegFpNegOffsetPattern = LW | (kRegister_fp_Code << kRsShift)
+ | (kNegOffset & kImm16Mask); // NOLINT
-const Instr kSwRegFpNegOffsetPattern = SW | (Register::kCode_fp << kRsShift) |
- (kNegOffset & kImm16Mask); // NOLINT
+const Instr kSwRegFpNegOffsetPattern = SW | (kRegister_fp_Code << kRsShift)
+ | (kNegOffset & kImm16Mask); // NOLINT
// A mask for the Rt register for push, pop, lw, sw instructions.
const Instr kRtMask = kRtFieldMask;
const Instr kLwSwInstrTypeMask = 0xffe00000;
Register Assembler::GetRtReg(Instr instr) {
Register rt;
- rt.reg_code = (instr & kRtFieldMask) >> kRtShift;
+ rt.code_ = (instr & kRtFieldMask) >> kRtShift;
return rt;
}
Register Assembler::GetRsReg(Instr instr) {
Register rs;
- rs.reg_code = (instr & kRsFieldMask) >> kRsShift;
+ rs.code_ = (instr & kRsFieldMask) >> kRsShift;
return rs;
}
Register Assembler::GetRdReg(Instr instr) {
Register rd;
- rd.reg_code = (instr & kRdFieldMask) >> kRdShift;
+ rd.code_ = (instr & kRdFieldMask) >> kRdShift;
return rd;
}
void Assembler::movt(Register rd, Register rs, uint16_t cc) {
Register rt;
- rt.reg_code = (cc & 0x0007) << 2 | 1;
+ rt.code_ = (cc & 0x0007) << 2 | 1;
GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
}
void Assembler::movf(Register rd, Register rs, uint16_t cc) {
Register rt;
- rt.reg_code = (cc & 0x0007) << 2 | 0;
+ rt.code_ = (cc & 0x0007) << 2 | 0;
GenInstrRegister(SPECIAL, rs, rt, rd, 0, MOVCI);
}
void Assembler::movt_s(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(kArchVariant == kMips64r2);
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 1;
+ ft.code_ = (cc & 0x0007) << 2 | 1;
GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
}
void Assembler::movt_d(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(kArchVariant == kMips64r2);
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 1;
+ ft.code_ = (cc & 0x0007) << 2 | 1;
GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
}
void Assembler::movf_s(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(kArchVariant == kMips64r2);
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 0;
+ ft.code_ = (cc & 0x0007) << 2 | 0;
GenInstrRegister(COP1, S, ft, fs, fd, MOVF);
}
void Assembler::movf_d(FPURegister fd, FPURegister fs, uint16_t cc) {
DCHECK(kArchVariant == kMips64r2);
FPURegister ft;
- ft.reg_code = (cc & 0x0007) << 2 | 0;
+ ft.code_ = (cc & 0x0007) << 2 | 0;
GenInstrRegister(COP1, D, ft, fs, fd, MOVF);
}
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-
// -----------------------------------------------------------------------------
// 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.
- 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);
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
// in pairs, starting with the even numbered register. So a double operation
// 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.
// 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 };
#include "src/codegen.h"
#include "src/deoptimizer.h"
#include "src/full-codegen/full-codegen.h"
-#include "src/register-configuration.h"
#include "src/safepoint-table.h"
namespace v8 {
}
input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
input_->SetDoubleRegister(i, 0.0);
}
RegList restored_regs = kJSCallerSaved | kCalleeSaved;
RegList saved_regs = restored_regs | sp.bit() | ra.bit();
- const int kDoubleRegsSize = kDoubleSize * DoubleRegister::kMaxNumRegisters;
+ const int kDoubleRegsSize =
+ kDoubleSize * FPURegister::kMaxNumAllocatableRegisters;
// Save all FPU registers before messing with them.
__ Dsubu(sp, sp, Operand(kDoubleRegsSize));
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
- int offset = code * kDoubleSize;
+ for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
+ FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
+ int offset = i * kDoubleSize;
__ sdc1(fpu_reg, MemOperand(sp, offset));
}
int double_regs_offset = FrameDescription::double_registers_offset();
// Copy FPU registers to
// double_registers_[DoubleRegister::kNumAllocatableRegisters]
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- int dst_offset = code * kDoubleSize + double_regs_offset;
- int src_offset = code * kDoubleSize + kNumberOfRegisters * kPointerSize;
+ for (int i = 0; i < FPURegister::NumAllocatableRegisters(); ++i) {
+ int dst_offset = i * kDoubleSize + double_regs_offset;
+ int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
__ ldc1(f0, MemOperand(sp, src_offset));
__ sdc1(f0, MemOperand(a1, dst_offset));
}
__ BranchShort(&outer_push_loop, lt, a4, Operand(a1));
__ ld(a1, MemOperand(a0, Deoptimizer::input_offset()));
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- const DoubleRegister fpu_reg = DoubleRegister::from_code(code);
- int src_offset = code * kDoubleSize + double_regs_offset;
+ for (int i = 0; i < FPURegister::kMaxNumAllocatableRegisters; ++i) {
+ const FPURegister fpu_reg = FPURegister::FromAllocationIndex(i);
+ int src_offset = i * kDoubleSize + double_regs_offset;
__ ldc1(fpu_reg, MemOperand(a1, src_offset));
}
BitVector* doubles = chunk()->allocated_double_registers();
BitVector::Iterator save_iterator(doubles);
while (!save_iterator.Done()) {
- __ sdc1(DoubleRegister::from_code(save_iterator.Current()),
+ __ sdc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
MemOperand(sp, count * kDoubleSize));
save_iterator.Advance();
count++;
BitVector::Iterator save_iterator(doubles);
int count = 0;
while (!save_iterator.Done()) {
- __ ldc1(DoubleRegister::from_code(save_iterator.Current()),
+ __ ldc1(DoubleRegister::FromAllocationIndex(save_iterator.Current()),
MemOperand(sp, count * kDoubleSize));
save_iterator.Advance();
count++;
Register LCodeGen::ToRegister(int index) const {
- return Register::from_code(index);
+ return Register::FromAllocationIndex(index);
}
DoubleRegister LCodeGen::ToDoubleRegister(int index) const {
- return DoubleRegister::from_code(index);
+ return DoubleRegister::FromAllocationIndex(index);
}
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(DoubleRegister reg) {
- return new (zone())
- LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ DoubleRegister::ToAllocationIndex(reg));
}
#include "src/cpu-profiler.h"
#include "src/debug/debug.h"
#include "src/mips64/macro-assembler-mips64.h"
-#include "src/register-configuration.h"
#include "src/runtime/runtime.h"
namespace v8 {
MemOperand MacroAssembler::SafepointRegistersAndDoublesSlot(Register reg) {
UNIMPLEMENTED_MIPS();
// General purpose registers are pushed last on the stack.
- int doubles_size = DoubleRegister::kMaxNumRegisters * kDoubleSize;
+ int doubles_size = FPURegister::NumAllocatableRegisters() * kDoubleSize;
int register_offset = SafepointRegisterStackIndex(reg.code()) * kPointerSize;
return MemOperand(sp, doubles_size + register_offset);
}
// Find a temp register in temps list.
for (int i = 0; i < kNumRegisters; i++) {
if ((temps & (1 << i)) != 0) {
- tmp.reg_code = i;
+ tmp.code_ = i;
break;
}
}
if (reg5.is_valid()) regs |= reg5.bit();
if (reg6.is_valid()) regs |= reg6.bit();
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_general_registers(); ++i) {
- int code = config->GetAllocatableGeneralCode(i);
- Register candidate = Register::from_code(code);
+ for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+ Register candidate = Register::FromAllocationIndex(i);
if (regs & candidate.bit()) continue;
return candidate;
}
namespace internal {
// Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {Register::kCode_v0};
-const Register kReturnRegister1 = {Register::kCode_v1};
-const Register kJSFunctionRegister = {Register::kCode_a1};
-const Register kContextRegister = {Register::kCpRegister};
-const Register kInterpreterAccumulatorRegister = {Register::kCode_v0};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_a7};
-const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_t0};
-const Register kInterpreterBytecodeArrayRegister = {Register::kCode_t1};
-const Register kInterpreterDispatchTableRegister = {Register::kCode_t2};
-const Register kRuntimeCallFunctionRegister = {Register::kCode_a1};
-const Register kRuntimeCallArgCountRegister = {Register::kCode_a0};
+const Register kReturnRegister0 = {kRegister_v0_Code};
+const Register kReturnRegister1 = {kRegister_v1_Code};
+const Register kJSFunctionRegister = {kRegister_a1_Code};
+const Register kContextRegister = {kRegister_s7_Code};
+const Register kInterpreterAccumulatorRegister = {kRegister_v0_Code};
+const Register kInterpreterRegisterFileRegister = {kRegister_a7_Code};
+const Register kInterpreterBytecodeOffsetRegister = {kRegister_t0_Code};
+const Register kInterpreterBytecodeArrayRegister = {kRegister_t1_Code};
+const Register kInterpreterDispatchTableRegister = {kRegister_t2_Code};
+const Register kRuntimeCallFunctionRegister = {kRegister_a1_Code};
+const Register kRuntimeCallArgCountRegister = {kRegister_a0_Code};
// Forward declaration.
class JumpTarget;
case Translation::DOUBLE_REGISTER: {
int reg_code = iterator.Next();
- os << "{input=" << DoubleRegister::from_code(reg_code).ToString()
+ os << "{input=" << DoubleRegister::AllocationIndexToString(reg_code)
<< "}";
break;
}
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "src/register-configuration.h"
-#include "src/globals.h"
-#include "src/macro-assembler.h"
-
-namespace v8 {
-namespace internal {
-
-namespace {
-
-#define REGISTER_COUNT(R) 1 +
-static const int kMaxAllocatableGeneralRegisterCount =
- ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
-static const int kMaxAllocatableDoubleRegisterCount =
- ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_COUNT)0;
-
-static const char* const kGeneralRegisterNames[] = {
-#define REGISTER_NAME(R) #R,
- GENERAL_REGISTERS(REGISTER_NAME)
-#undef REGISTER_NAME
-};
-
-static const char* const kDoubleRegisterNames[] = {
-#define REGISTER_NAME(R) #R,
- DOUBLE_REGISTERS(REGISTER_NAME)
-#undef REGISTER_NAME
-};
-
-STATIC_ASSERT(RegisterConfiguration::kMaxGeneralRegisters >=
- Register::kNumRegisters);
-STATIC_ASSERT(RegisterConfiguration::kMaxDoubleRegisters >=
- DoubleRegister::kMaxNumRegisters);
-
-class ArchDefaultRegisterConfiguration : public RegisterConfiguration {
- public:
- ArchDefaultRegisterConfiguration()
- : RegisterConfiguration(
- Register::kNumRegisters, DoubleRegister::kMaxNumRegisters,
-#if V8_TARGET_ARCH_IA32
- kMaxAllocatableGeneralRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
-#elif V8_TARGET_ARCH_X87
- kMaxAllocatableGeneralRegisterCount, 1, 1,
-#elif V8_TARGET_ARCH_X64
- kMaxAllocatableGeneralRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
-#elif V8_TARGET_ARCH_ARM
- FLAG_enable_embedded_constant_pool
- ? (kMaxAllocatableGeneralRegisterCount - 1)
- : kMaxAllocatableGeneralRegisterCount,
- CpuFeatures::IsSupported(VFP32DREGS)
- ? kMaxAllocatableDoubleRegisterCount
- : (ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT)0),
- ALLOCATABLE_NO_VFP32_DOUBLE_REGISTERS(REGISTER_COUNT)0,
-#elif V8_TARGET_ARCH_ARM64
- kMaxAllocatableGeneralRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
-#elif V8_TARGET_ARCH_MIPS
- kMaxAllocatableGeneralRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
-#elif V8_TARGET_ARCH_MIPS64
- kMaxAllocatableGeneralRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
- kMaxAllocatableDoubleRegisterCount,
-#else
- GetAllocatableGeneralRegisterCount(),
- GetAllocatableDoubleRegisterCount(),
- GetAllocatableAliasedDoubleRegisterCount(),
-#endif
- GetAllocatableGeneralCodes(), GetAllocatableDoubleCodes(),
- kGeneralRegisterNames, kDoubleRegisterNames) {
- }
-
- const char* general_register_name_table_[Register::kNumRegisters];
- const char* double_register_name_table_[DoubleRegister::kMaxNumRegisters];
-
- private:
- friend struct Register;
- friend struct DoubleRegister;
-
- static const int* GetAllocatableGeneralCodes() {
-#define REGISTER_CODE(R) Register::kCode_##R,
- static const int general_codes[] = {
- ALLOCATABLE_GENERAL_REGISTERS(REGISTER_CODE)};
-#undef REGISTER_CODE
- return general_codes;
- }
-
- static const int* GetAllocatableDoubleCodes() {
-#define REGISTER_CODE(R) DoubleRegister::kCode_##R,
- static const int double_codes[] = {
- ALLOCATABLE_DOUBLE_REGISTERS(REGISTER_CODE)};
-#undef REGISTER_CODE
- return double_codes;
- }
-};
-
-
-static base::LazyInstance<ArchDefaultRegisterConfiguration>::type
- kDefaultRegisterConfiguration = LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-
-const RegisterConfiguration* RegisterConfiguration::ArchDefault() {
- return &kDefaultRegisterConfiguration.Get();
-}
-
-RegisterConfiguration::RegisterConfiguration(
- int num_general_registers, int num_double_registers,
- int num_allocatable_general_registers, int num_allocatable_double_registers,
- int num_allocatable_aliased_double_registers,
- const int* allocatable_general_codes, const int* allocatable_double_codes,
- const char* const* general_register_names,
- const char* const* double_register_names)
- : num_general_registers_(num_general_registers),
- num_double_registers_(num_double_registers),
- num_allocatable_general_registers_(num_allocatable_general_registers),
- num_allocatable_double_registers_(num_allocatable_double_registers),
- num_allocatable_aliased_double_registers_(
- num_allocatable_aliased_double_registers),
- allocatable_general_codes_mask_(0),
- allocatable_double_codes_mask_(0),
- allocatable_general_codes_(allocatable_general_codes),
- allocatable_double_codes_(allocatable_double_codes),
- general_register_names_(general_register_names),
- double_register_names_(double_register_names) {
- for (int i = 0; i < num_allocatable_general_registers_; ++i) {
- allocatable_general_codes_mask_ |= (1 << allocatable_general_codes_[i]);
- }
- for (int i = 0; i < num_allocatable_double_registers_; ++i) {
- allocatable_double_codes_mask_ |= (1 << allocatable_double_codes_[i]);
- }
-}
-
-#undef REGISTER_COUNT
-
-} // namespace internal
-} // namespace v8
+++ /dev/null
-// Copyright 2014 the V8 project authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef V8_COMPILER_REGISTER_CONFIGURATION_H_
-#define V8_COMPILER_REGISTER_CONFIGURATION_H_
-
-#include "src/base/macros.h"
-
-namespace v8 {
-namespace internal {
-
-// An architecture independent representation of the sets of registers available
-// for instruction creation.
-class RegisterConfiguration {
- public:
- // Architecture independent maxes.
- static const int kMaxGeneralRegisters = 32;
- static const int kMaxDoubleRegisters = 32;
-
- static const RegisterConfiguration* ArchDefault();
-
- RegisterConfiguration(int num_general_registers, int num_double_registers,
- int num_allocatable_general_registers,
- int num_allocatable_double_registers,
- int num_allocatable_aliased_double_registers,
- const int* allocatable_general_codes,
- const int* allocatable_double_codes,
- char const* const* general_names,
- char const* const* double_names);
-
- int num_general_registers() const { return num_general_registers_; }
- int num_double_registers() const { return num_double_registers_; }
- int num_allocatable_general_registers() const {
- return num_allocatable_general_registers_;
- }
- int num_allocatable_double_registers() const {
- return num_allocatable_double_registers_;
- }
- // TODO(turbofan): This is a temporary work-around required because our
- // register allocator does not yet support the aliasing of single/double
- // registers on ARM.
- int num_allocatable_aliased_double_registers() const {
- return num_allocatable_aliased_double_registers_;
- }
- int32_t allocatable_general_codes_mask() const {
- return allocatable_general_codes_mask_;
- }
- int32_t allocatable_double_codes_mask() const {
- return allocatable_double_codes_mask_;
- }
- int GetAllocatableGeneralCode(int index) const {
- return allocatable_general_codes_[index];
- }
- int GetAllocatableDoubleCode(int index) const {
- return allocatable_double_codes_[index];
- }
- const char* GetGeneralRegisterName(int code) const {
- return general_register_names_[code];
- }
- const char* GetDoubleRegisterName(int code) const {
- return double_register_names_[code];
- }
- const int* allocatable_general_codes() const {
- return allocatable_general_codes_;
- }
- const int* allocatable_double_codes() const {
- return allocatable_double_codes_;
- }
-
- private:
- const int num_general_registers_;
- const int num_double_registers_;
- int num_allocatable_general_registers_;
- int num_allocatable_double_registers_;
- int num_allocatable_aliased_double_registers_;
- int32_t allocatable_general_codes_mask_;
- int32_t allocatable_double_codes_mask_;
- const int* allocatable_general_codes_;
- const int* allocatable_double_codes_;
- char const* const* general_register_names_;
- char const* const* double_register_names_;
-};
-
-} // namespace internal
-} // namespace v8
-
-#endif // V8_COMPILER_REGISTER_CONFIGURATION_H_
}
+// -----------------------------------------------------------------------------
+// Register constants.
+
+const int
+ Register::kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters] = {
+ // rax, rbx, rdx, rcx, rsi, rdi, r8, r9, r11, r12, r14, r15
+ 0, 3, 2, 1, 6, 7, 8, 9, 11, 12, 14, 15
+};
+
+const int Register::kAllocationIndexByRegisterCode[kNumRegisters] = {
+ 0, 3, 2, 1, -1, -1, 4, 5, 6, 7, -1, 8, 9, -1, 10, 11
+};
+
+
// -----------------------------------------------------------------------------
// Implementation of Operand
// Utility functions
-#define GENERAL_REGISTERS(V) \
- V(rax) \
- V(rcx) \
- V(rdx) \
- V(rbx) \
- V(rsp) \
- V(rbp) \
- V(rsi) \
- V(rdi) \
- V(r8) \
- V(r9) \
- V(r10) \
- V(r11) \
- V(r12) \
- V(r13) \
- V(r14) \
- V(r15)
-
-#define ALLOCATABLE_GENERAL_REGISTERS(V) \
- V(rax) \
- V(rbx) \
- V(rdx) \
- V(rcx) \
- V(rsi) \
- V(rdi) \
- V(r8) \
- V(r9) \
- V(r11) \
- V(r12) \
- V(r14) \
- V(r15)
-
-
// CPU Registers.
//
// 1) We would prefer to use an enum, but enum values are assignment-
// mode. This way we get the compile-time error checking in debug mode
// and best performance in optimized code.
//
+
struct Register {
- enum Code {
-#define REGISTER_CODE(R) kCode_##R,
- GENERAL_REGISTERS(REGISTER_CODE)
-#undef REGISTER_CODE
- kAfterLast,
- kCode_no_reg = -1
- };
+ // The non-allocatable registers are:
+ // rsp - stack pointer
+ // rbp - frame pointer
+ // r10 - fixed scratch register
+ // r13 - root register
+ static const int kMaxNumAllocatableRegisters = 12;
+ static int NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+ }
+ static const int kNumRegisters = 16;
+
+ static int ToAllocationIndex(Register reg) {
+ return kAllocationIndexByRegisterCode[reg.code()];
+ }
+
+ static Register FromAllocationIndex(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ Register result = { kRegisterCodeByAllocationIndex[index] };
+ return result;
+ }
- static const int kNumRegisters = Code::kAfterLast;
+ static const char* AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ const char* const names[] = {
+ "rax",
+ "rbx",
+ "rdx",
+ "rcx",
+ "rsi",
+ "rdi",
+ "r8",
+ "r9",
+ "r11",
+ "r12",
+ "r14",
+ "r15"
+ };
+ return names[index];
+ }
static Register from_code(int code) {
- DCHECK(code >= 0);
- DCHECK(code < kNumRegisters);
- Register r = {code};
+ 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_; }
+ // rax, rbx, rcx and rdx are byte registers, the rest are not.
+ bool is_byte_register() const { return code_ <= 3; }
int code() const {
DCHECK(is_valid());
- return reg_code;
+ return code_;
}
int bit() const {
- DCHECK(is_valid());
- return 1 << reg_code;
+ return 1 << code_;
}
- bool is_byte_register() const { return reg_code <= 3; }
// Return the high bit of the register code as a 0 or 1. Used often
// when constructing the REX prefix byte.
- int high_bit() const { return reg_code >> 3; }
+ int high_bit() const {
+ return code_ >> 3;
+ }
// Return the 3 low bits of the register code. Used when encoding registers
// in modR/M, SIB, and opcode bytes.
- int low_bits() const { return reg_code & 0x7; }
+ int low_bits() const {
+ return code_ & 0x7;
+ }
// Unfortunately we can't make this private in a struct when initializing
// by assignment.
- int reg_code;
-};
-
+ int code_;
-#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};
+ private:
+ static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters];
+ static const int kAllocationIndexByRegisterCode[kNumRegisters];
+};
+const int kRegister_rax_Code = 0;
+const int kRegister_rcx_Code = 1;
+const int kRegister_rdx_Code = 2;
+const int kRegister_rbx_Code = 3;
+const int kRegister_rsp_Code = 4;
+const int kRegister_rbp_Code = 5;
+const int kRegister_rsi_Code = 6;
+const int kRegister_rdi_Code = 7;
+const int kRegister_r8_Code = 8;
+const int kRegister_r9_Code = 9;
+const int kRegister_r10_Code = 10;
+const int kRegister_r11_Code = 11;
+const int kRegister_r12_Code = 12;
+const int kRegister_r13_Code = 13;
+const int kRegister_r14_Code = 14;
+const int kRegister_r15_Code = 15;
+const int kRegister_no_reg_Code = -1;
+
+const Register rax = { kRegister_rax_Code };
+const Register rcx = { kRegister_rcx_Code };
+const Register rdx = { kRegister_rdx_Code };
+const Register rbx = { kRegister_rbx_Code };
+const Register rsp = { kRegister_rsp_Code };
+const Register rbp = { kRegister_rbp_Code };
+const Register rsi = { kRegister_rsi_Code };
+const Register rdi = { kRegister_rdi_Code };
+const Register r8 = { kRegister_r8_Code };
+const Register r9 = { kRegister_r9_Code };
+const Register r10 = { kRegister_r10_Code };
+const Register r11 = { kRegister_r11_Code };
+const Register r12 = { kRegister_r12_Code };
+const Register r13 = { kRegister_r13_Code };
+const Register r14 = { kRegister_r14_Code };
+const Register r15 = { kRegister_r15_Code };
+const Register no_reg = { kRegister_no_reg_Code };
#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};
+ const Register arg_reg_1 = { kRegister_rcx_Code };
+ const Register arg_reg_2 = { kRegister_rdx_Code };
+ const Register arg_reg_3 = { kRegister_r8_Code };
+ const Register arg_reg_4 = { kRegister_r9_Code };
#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};
+ const Register arg_reg_1 = { kRegister_rdi_Code };
+ const Register arg_reg_2 = { kRegister_rsi_Code };
+ const Register arg_reg_3 = { kRegister_rdx_Code };
+ const Register arg_reg_4 = { kRegister_rcx_Code };
#endif // _WIN64
+struct XMMRegister {
+ static const int kMaxNumRegisters = 16;
+ static const int kMaxNumAllocatableRegisters = 15;
+ static int NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+ }
+
+ // TODO(turbofan): Proper support for float32.
+ static int NumAllocatableAliasedRegisters() {
+ return NumAllocatableRegisters();
+ }
+
+ static int ToAllocationIndex(XMMRegister reg) {
+ DCHECK(reg.code() != 0);
+ return reg.code() - 1;
+ }
-#define DOUBLE_REGISTERS(V) \
- V(xmm0) \
- V(xmm1) \
- V(xmm2) \
- V(xmm3) \
- V(xmm4) \
- V(xmm5) \
- V(xmm6) \
- V(xmm7) \
- V(xmm8) \
- V(xmm9) \
- V(xmm10) \
- V(xmm11) \
- V(xmm12) \
- V(xmm13) \
- V(xmm14) \
- V(xmm15)
-
-#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
- V(xmm1) \
- V(xmm2) \
- V(xmm3) \
- V(xmm4) \
- V(xmm5) \
- V(xmm6) \
- V(xmm7) \
- V(xmm8) \
- V(xmm9) \
- V(xmm10) \
- V(xmm11) \
- V(xmm12) \
- V(xmm13) \
- V(xmm14) \
- V(xmm15)
-
-
-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;
-
- static DoubleRegister from_code(int code) {
- DoubleRegister result = {code};
+ static XMMRegister FromAllocationIndex(int index) {
+ DCHECK(0 <= index && index < kMaxNumAllocatableRegisters);
+ XMMRegister result = { index + 1 };
return result;
}
- 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; }
+ static const char* AllocationIndexToString(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ const char* const names[] = {
+ "xmm1",
+ "xmm2",
+ "xmm3",
+ "xmm4",
+ "xmm5",
+ "xmm6",
+ "xmm7",
+ "xmm8",
+ "xmm9",
+ "xmm10",
+ "xmm11",
+ "xmm12",
+ "xmm13",
+ "xmm14",
+ "xmm15"
+ };
+ return names[index];
+ }
+
+ static XMMRegister from_code(int code) {
+ DCHECK(code >= 0);
+ DCHECK(code < kMaxNumRegisters);
+ XMMRegister r = { code };
+ return r;
+ }
+ bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
+ bool is(XMMRegister reg) const { return code_ == reg.code_; }
int code() const {
DCHECK(is_valid());
- return reg_code;
+ return code_;
}
// Return the high bit of the register code as a 0 or 1. Used often
// when constructing the REX prefix byte.
- int high_bit() const { return reg_code >> 3; }
+ int high_bit() const {
+ return code_ >> 3;
+ }
// Return the 3 low bits of the register code. Used when encoding registers
// in modR/M, SIB, and opcode bytes.
- int low_bits() const { return reg_code & 0x7; }
+ int low_bits() const {
+ return code_ & 0x7;
+ }
- // Unfortunately we can't make this private in a struct when initializing
- // by assignment.
- int reg_code;
+ int code_;
};
+const XMMRegister xmm0 = { 0 };
+const XMMRegister xmm1 = { 1 };
+const XMMRegister xmm2 = { 2 };
+const XMMRegister xmm3 = { 3 };
+const XMMRegister xmm4 = { 4 };
+const XMMRegister xmm5 = { 5 };
+const XMMRegister xmm6 = { 6 };
+const XMMRegister xmm7 = { 7 };
+const XMMRegister xmm8 = { 8 };
+const XMMRegister xmm9 = { 9 };
+const XMMRegister xmm10 = { 10 };
+const XMMRegister xmm11 = { 11 };
+const XMMRegister xmm12 = { 12 };
+const XMMRegister xmm13 = { 13 };
+const XMMRegister xmm14 = { 14 };
+const XMMRegister xmm15 = { 15 };
+
+
+typedef XMMRegister DoubleRegister;
-#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};
-
-
-typedef DoubleRegister XMMRegister;
enum Condition {
// any value < 0 is considered no_condition
Register GetRegThatIsNotRcxOr(Register r1,
Register r2,
Register r3) {
- for (int i = 0; i < Register::kNumRegisters; i++) {
- Register candidate = Register::from_code(i);
- if (candidate.IsAllocatable()) {
- if (candidate.is(rcx)) continue;
- if (candidate.is(r1)) continue;
- if (candidate.is(r2)) continue;
- if (candidate.is(r3)) continue;
- return candidate;
- }
+ for (int i = 0; i < Register::NumAllocatableRegisters(); i++) {
+ Register candidate = Register::FromAllocationIndex(i);
+ if (candidate.is(rcx)) continue;
+ if (candidate.is(r1)) continue;
+ if (candidate.is(r2)) continue;
+ if (candidate.is(r3)) continue;
+ return candidate;
}
UNREACHABLE();
return no_reg;
#include "src/codegen.h"
#include "src/deoptimizer.h"
#include "src/full-codegen/full-codegen.h"
-#include "src/register-configuration.h"
#include "src/safepoint-table.h"
namespace v8 {
}
input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp()));
input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp()));
- for (int i = 0; i < DoubleRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
input_->SetDoubleRegister(i, 0.0);
}
void Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
- for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) {
+ for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
double double_value = input_->GetDoubleRegister(i);
output_frame->SetDoubleRegister(i, double_value);
}
// Save all general purpose registers before messing with them.
const int kNumberOfRegisters = Register::kNumRegisters;
- const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters;
+ const int kDoubleRegsSize = kDoubleSize *
+ XMMRegister::NumAllocatableRegisters();
__ subp(rsp, Immediate(kDoubleRegsSize));
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- XMMRegister xmm_reg = XMMRegister::from_code(code);
- int offset = code * kDoubleSize;
+ for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
+ XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
+ int offset = i * kDoubleSize;
__ movsd(Operand(rsp, offset), xmm_reg);
}
// Fill in the double input registers.
int double_regs_offset = FrameDescription::double_registers_offset();
- for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
+ for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
int dst_offset = i * kDoubleSize + double_regs_offset;
__ popq(Operand(rbx, dst_offset));
}
__ cmpp(rax, rdx);
__ j(below, &outer_push_loop);
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- int code = config->GetAllocatableDoubleCode(i);
- XMMRegister xmm_reg = XMMRegister::from_code(code);
- int src_offset = code * kDoubleSize + double_regs_offset;
+ for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); ++i) {
+ XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
+ int src_offset = i * kDoubleSize + double_regs_offset;
__ movsd(xmm_reg, Operand(rbx, src_offset));
}
BitVector::Iterator save_iterator(doubles);
while (!save_iterator.Done()) {
__ movsd(MemOperand(rsp, count * kDoubleSize),
- XMMRegister::from_code(save_iterator.Current()));
+ XMMRegister::FromAllocationIndex(save_iterator.Current()));
save_iterator.Advance();
count++;
}
BitVector::Iterator save_iterator(doubles);
int count = 0;
while (!save_iterator.Done()) {
- __ movsd(XMMRegister::from_code(save_iterator.Current()),
+ __ movsd(XMMRegister::FromAllocationIndex(save_iterator.Current()),
MemOperand(rsp, count * kDoubleSize));
save_iterator.Advance();
count++;
Register LCodeGen::ToRegister(int index) const {
- return Register::from_code(index);
+ return Register::FromAllocationIndex(index);
}
XMMRegister LCodeGen::ToDoubleRegister(int index) const {
- return XMMRegister::from_code(index);
+ return XMMRegister::FromAllocationIndex(index);
}
LUnallocated* LChunkBuilder::ToUnallocated(Register reg) {
- return new (zone()) LUnallocated(LUnallocated::FIXED_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_REGISTER,
+ Register::ToAllocationIndex(reg));
}
LUnallocated* LChunkBuilder::ToUnallocated(XMMRegister reg) {
- return new (zone())
- LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER, reg.code());
+ return new(zone()) LUnallocated(LUnallocated::FIXED_DOUBLE_REGISTER,
+ XMMRegister::ToAllocationIndex(reg));
}
#include "src/cpu-profiler.h"
#include "src/debug/debug.h"
#include "src/heap/heap.h"
-#include "src/register-configuration.h"
#include "src/x64/assembler-x64.h"
#include "src/x64/macro-assembler-x64.h"
}
-#define REG(Name) \
- { Register::kCode_##Name }
+#define REG(Name) { kRegister_ ## Name ## _Code }
static const Register saved_regs[] = {
REG(rax), REG(rcx), REG(rdx), REG(rbx), REG(rbp), REG(rsi), REG(rdi), REG(r8),
#endif
// Optionally save all XMM registers.
if (save_doubles) {
- int space = XMMRegister::kMaxNumRegisters * kDoubleSize +
- arg_stack_space * kRegisterSize;
+ int space = XMMRegister::kMaxNumAllocatableRegisters * kDoubleSize +
+ arg_stack_space * kRegisterSize;
subp(rsp, Immediate(space));
int offset = -2 * kPointerSize;
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- DoubleRegister reg =
- DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
+ for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
+ XMMRegister reg = XMMRegister::FromAllocationIndex(i);
movsd(Operand(rbp, offset - ((i + 1) * kDoubleSize)), reg);
}
} else if (arg_stack_space > 0) {
// r15 : argv
if (save_doubles) {
int offset = -2 * kPointerSize;
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
- DoubleRegister reg =
- DoubleRegister::from_code(config->GetAllocatableDoubleCode(i));
+ for (int i = 0; i < XMMRegister::NumAllocatableRegisters(); i++) {
+ XMMRegister reg = XMMRegister::FromAllocationIndex(i);
movsd(reg, Operand(rbp, offset - ((i + 1) * kDoubleSize)));
}
}
namespace internal {
// Give alias names to registers for calling conventions.
-const Register kReturnRegister0 = {Register::kCode_rax};
-const Register kReturnRegister1 = {Register::kCode_rdx};
-const Register kJSFunctionRegister = {Register::kCode_rdi};
-const Register kContextRegister = {Register::kCode_rsi};
-const Register kInterpreterAccumulatorRegister = {Register::kCode_rax};
-const Register kInterpreterRegisterFileRegister = {Register::kCode_r11};
-const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_r12};
-const Register kInterpreterBytecodeArrayRegister = {Register::kCode_r14};
-const Register kInterpreterDispatchTableRegister = {Register::kCode_r15};
-const Register kRuntimeCallFunctionRegister = {Register::kCode_rbx};
-const Register kRuntimeCallArgCountRegister = {Register::kCode_rax};
+const Register kReturnRegister0 = {kRegister_rax_Code};
+const Register kReturnRegister1 = {kRegister_rdx_Code};
+const Register kJSFunctionRegister = {kRegister_rdi_Code};
+const Register kContextRegister = {kRegister_rsi_Code};
+const Register kInterpreterAccumulatorRegister = {kRegister_rax_Code};
+const Register kInterpreterRegisterFileRegister = {kRegister_r11_Code};
+const Register kInterpreterBytecodeOffsetRegister = {kRegister_r12_Code};
+const Register kInterpreterBytecodeArrayRegister = {kRegister_r14_Code};
+const Register kInterpreterDispatchTableRegister = {kRegister_r15_Code};
+const Register kRuntimeCallFunctionRegister = {kRegister_rbx_Code};
+const Register kRuntimeCallArgCountRegister = {kRegister_rax_Code};
// Default scratch register used by MacroAssembler (and other code that needs
// a spare register). The register isn't callee save, and not used by the
static inline const char* AllocationIndexToString(int index);
+ static inline int ToAllocationIndex(Register reg);
+
+ static inline Register FromAllocationIndex(int index);
+
static Register from_code(int code) {
DCHECK(code >= 0);
DCHECK(code < kNumRegisters);
}
+inline int Register::ToAllocationIndex(Register reg) {
+ DCHECK(reg.is_valid() && !reg.is(esp) && !reg.is(ebp));
+ return (reg.code() >= 6) ? reg.code() - 2 : reg.code();
+}
+
+
+inline Register Register::FromAllocationIndex(int index) {
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
+ return (index >= 4) ? from_code(index + 2) : from_code(index);
+}
+
+
struct X87Register {
static const int kMaxNumAllocatableRegisters = 6;
static const int kMaxNumRegisters = 8;
AllocatedOperand::AllocatedKind kind;
int index;
if (!is_constant) {
- if (op.IsRegister()) {
- index = AllocatedOperand::cast(op).GetRegister().code();
- } else if (op.IsDoubleRegister()) {
- index = AllocatedOperand::cast(op).GetDoubleRegister().code();
- } else {
- index = AllocatedOperand::cast(op).index();
- }
+ index = AllocatedOperand::cast(op).index();
kind = AllocatedOperand::cast(op).allocated_kind();
} else {
index = ConstantOperand::cast(op).virtual_register();
return ConstantOperand(key.index);
}
return AllocatedOperand(
- key.kind,
- v8::internal::compiler::InstructionSequence::DefaultRepresentation(),
- key.index);
+ key.kind, InstructionSequence::DefaultRepresentation(), key.index);
}
friend std::ostream& operator<<(std::ostream& os,
#include "src/compiler/linkage.h"
#include "src/compiler/machine-type.h"
#include "src/compiler/raw-machine-assembler.h"
-#include "src/register-configuration.h"
#include "test/cctest/cctest.h"
#include "test/cctest/compiler/codegen-tester.h"
// to select a representative set.
class Pairs {
public:
- Pairs(int max_pairs, int range, const int* codes)
+ Pairs(int max_pairs, int range)
: range_(range),
- codes_(codes),
max_pairs_(std::min(max_pairs, range_ * range_)),
counter_(0) {}
do {
// Find the next pair.
if (exhaustive()) {
- *r0 = codes_[counter_ % range_];
- *r1 = codes_[counter_ / range_];
+ *r0 = counter_ % range_;
+ *r1 = counter_ / range_;
} else {
// Try each integer at least once for both r0 and r1.
int index = counter_ / 2;
if (counter_ & 1) {
- *r0 = codes_[index % range_];
- *r1 = codes_[index / range_];
+ *r0 = index % range_;
+ *r1 = index / range_;
} else {
- *r1 = codes_[index % range_];
- *r0 = codes_[index / range_];
+ *r1 = index % range_;
+ *r0 = index / range_;
}
}
counter_++;
- if ((same_is_ok) || (*r0 != *r1)) break;
- if (counter_ == max_pairs_) {
- // For the last hurrah, reg#0 with reg#n-1
- *r0 = codes_[0];
- *r1 = codes_[range_ - 1];
- break;
+ if (same_is_ok) break;
+ if (*r0 == *r1) {
+ if (counter_ >= max_pairs_) {
+ // For the last hurrah, reg#0 with reg#n-1
+ *r0 = 0;
+ *r1 = range_ - 1;
+ break;
+ }
}
} while (true);
+
+ DCHECK(*r0 >= 0 && *r0 < range_);
+ DCHECK(*r1 >= 0 && *r1 < range_);
}
private:
int range_;
- const int* codes_;
int max_pairs_;
int counter_;
bool exhaustive() { return max_pairs_ == (range_ * range_); }
// Pairs of general purpose registers.
class RegisterPairs : public Pairs {
public:
- RegisterPairs()
- : Pairs(
- 100, RegisterConfiguration::ArchDefault()
- ->num_allocatable_general_registers(),
- RegisterConfiguration::ArchDefault()->allocatable_general_codes()) {
- }
+ RegisterPairs() : Pairs(100, Register::kMaxNumAllocatableRegisters) {}
};
class Float32RegisterPairs : public Pairs {
public:
Float32RegisterPairs()
- : Pairs(
- 100, RegisterConfiguration::ArchDefault()
- ->num_allocatable_aliased_double_registers(),
- RegisterConfiguration::ArchDefault()->allocatable_double_codes()) {}
+ : Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {}
};
class Float64RegisterPairs : public Pairs {
public:
Float64RegisterPairs()
- : Pairs(
- 100, RegisterConfiguration::ArchDefault()
- ->num_allocatable_aliased_double_registers(),
- RegisterConfiguration::ArchDefault()->allocatable_double_codes()) {}
+ : Pairs(100, DoubleRegister::NumAllocatableAliasedRegisters()) {}
};
// Separate tests for parallelization.
-#define TEST_INT32_SUB_WITH_RET(x) \
- TEST(Run_Int32Sub_all_allocatable_pairs_##x) { \
- if (x < Register::kNumRegisters && \
- Register::from_code(x).IsAllocatable()) { \
- Test_RunInt32SubWithRet(x); \
- } \
+#define TEST_INT32_SUB_WITH_RET(x) \
+ TEST(Run_Int32Sub_all_allocatable_pairs_##x) { \
+ if (Register::kMaxNumAllocatableRegisters > x) Test_RunInt32SubWithRet(x); \
}
while (pairs.More()) {
Zone zone;
int parray[2];
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
+ int rarray[] = {0};
pairs.Next(&parray[0], &parray[1], false);
Allocator params(parray, 2, nullptr, 0);
Allocator rets(rarray, 1, nullptr, 0);
static void Test_Int32_WeightedSum_of_size(int count) {
if (DISABLE_NATIVE_STACK_PARAMS) return;
Int32Signature sig(count);
- for (int p0 = 0; p0 < Register::kNumRegisters; p0++) {
- if (Register::from_code(p0).IsAllocatable()) {
- Zone zone;
+ for (int p0 = 0; p0 < Register::kMaxNumAllocatableRegisters; p0++) {
+ Zone zone;
- int parray[] = {p0};
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
- Allocator params(parray, 1, nullptr, 0);
- Allocator rets(rarray, 1, nullptr, 0);
- RegisterConfig config(params, rets);
- CallDescriptor* desc = config.Create(&zone, &sig);
- Run_Computation<int32_t>(desc, Build_Int32_WeightedSum,
- Compute_Int32_WeightedSum, 257 + count);
- }
+ int parray[] = {p0};
+ int rarray[] = {0};
+ Allocator params(parray, 1, nullptr, 0);
+ Allocator rets(rarray, 1, nullptr, 0);
+ RegisterConfig config(params, rets);
+ CallDescriptor* desc = config.Create(&zone, &sig);
+ Run_Computation<int32_t>(desc, Build_Int32_WeightedSum,
+ Compute_Int32_WeightedSum, 257 + count);
}
}
void Test_Int32_Select() {
if (DISABLE_NATIVE_STACK_PARAMS) return;
- int parray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
+ int parray[] = {0};
+ int rarray[] = {0};
Allocator params(parray, 1, nullptr, 0);
Allocator rets(rarray, 1, nullptr, 0);
RegisterConfig config(params, rets);
TEST(Int64Select_registers) {
- if (RegisterConfiguration::ArchDefault()
- ->num_allocatable_general_registers() < 2)
- return;
+ if (Register::kMaxNumAllocatableRegisters < 2) return;
if (kPointerSize < 8) return; // TODO(titzer): int64 on 32-bit platforms
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
+ int rarray[] = {0};
ArgsBuffer<int64_t>::Sig sig(2);
RegisterPairs pairs;
TEST(Float32Select_registers) {
- if (RegisterConfiguration::ArchDefault()->num_allocatable_double_registers() <
- 2) {
- return;
- }
+ if (RegisterConfiguration::ArchDefault()->num_double_registers() < 2) return;
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
+ int rarray[] = {0};
ArgsBuffer<float32>::Sig sig(2);
Float32RegisterPairs pairs;
TEST(Float64Select_registers) {
- if (RegisterConfiguration::ArchDefault()->num_allocatable_double_registers() <
- 2)
- return;
- if (RegisterConfiguration::ArchDefault()
- ->num_allocatable_general_registers() < 2)
- return;
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
+ if (RegisterConfiguration::ArchDefault()->num_double_registers() < 2) return;
+
+ int rarray[] = {0};
ArgsBuffer<float64>::Sig sig(2);
Float64RegisterPairs pairs;
TEST(Float32Select_stack_params_return_reg) {
if (DISABLE_NATIVE_STACK_PARAMS) return;
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
+ int rarray[] = {0};
Allocator params(nullptr, 0, nullptr, 0);
Allocator rets(nullptr, 0, rarray, 1);
RegisterConfig config(params, rets);
TEST(Float64Select_stack_params_return_reg) {
if (DISABLE_NATIVE_STACK_PARAMS) return;
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
+ int rarray[] = {0};
Allocator params(nullptr, 0, nullptr, 0);
Allocator rets(nullptr, 0, rarray, 1);
RegisterConfig config(params, rets);
TEST(Float64StackParamsToStackParams) {
if (DISABLE_NATIVE_STACK_PARAMS) return;
- int rarray[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
+ int rarray[] = {0};
Allocator params(nullptr, 0, nullptr, 0);
Allocator rets(nullptr, 0, rarray, 1);
const int num_params = static_cast<int>(arraysize(types) - start);
// Build call descriptor
- int parray_gp[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0),
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(1)};
- int rarray_gp[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableGeneralCode(0)};
- int parray_fp[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0),
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(1)};
- int rarray_fp[] = {
- RegisterConfiguration::ArchDefault()->GetAllocatableDoubleCode(0)};
- Allocator palloc(parray_gp, 2, parray_fp, 2);
- Allocator ralloc(rarray_gp, 1, rarray_fp, 1);
+ int parray[] = {0, 1};
+ int rarray[] = {0};
+ Allocator palloc(parray, 2, parray, 2);
+ Allocator ralloc(rarray, 1, rarray, 1);
RegisterConfig config(palloc, ralloc);
for (int which = 0; which < num_params; which++) {
// Save registers make sure they don't get clobbered.
int source_reg_offset = kDoubleSize;
int reg_num = 0;
- for (; reg_num < Register::kNumRegisters; ++reg_num) {
+ for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
Register reg = Register::from_code(reg_num);
- if (reg.IsAllocatable()) {
- if (!reg.is(destination_reg)) {
- __ push(reg);
- source_reg_offset += kPointerSize;
- }
+ if (!reg.is(destination_reg)) {
+ __ push(reg);
+ source_reg_offset += kPointerSize;
}
}
// Make sure no registers have been unexpectedly clobbered
for (--reg_num; reg_num >= 0; --reg_num) {
Register reg = Register::from_code(reg_num);
- if (reg.IsAllocatable()) {
- if (!reg.is(destination_reg)) {
- __ ldr(ip, MemOperand(sp, 0));
- __ cmp(reg, ip);
- __ Assert(eq, kRegisterWasClobbered);
- __ add(sp, sp, Operand(kPointerSize));
- }
+ if (!reg.is(destination_reg)) {
+ __ ldr(ip, MemOperand(sp, 0));
+ __ cmp(reg, ip);
+ __ Assert(eq, kRegisterWasClobbered);
+ __ add(sp, sp, Operand(kPointerSize));
}
}
// Save registers make sure they don't get clobbered.
int source_reg_offset = kDoubleSize;
int reg_num = 0;
- for (; reg_num < Register::kNumRegisters; ++reg_num) {
+ for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
Register reg = Register::from_code(reg_num);
- if (reg.IsAllocatable()) {
- if (!reg.is(destination_reg)) {
- queue.Queue(reg);
- source_reg_offset += kPointerSize;
- }
+ if (!reg.is(destination_reg)) {
+ queue.Queue(reg);
+ source_reg_offset += kPointerSize;
}
}
// Re-push the double argument.
// // Make sure no registers have been unexpectedly clobbered
for (--reg_num; reg_num >= 0; --reg_num) {
Register reg = Register::from_code(reg_num);
- if (reg.IsAllocatable()) {
- if (!reg.is(destination_reg)) {
- __ Pop(ip0);
- __ cmp(reg, ip0);
- __ Assert(eq, kRegisterWasClobbered);
- }
+ if (!reg.is(destination_reg)) {
+ __ Pop(ip0);
+ __ cmp(reg, ip0);
+ __ Assert(eq, kRegisterWasClobbered);
}
}
int param_offset = 7 * kPointerSize;
// Save registers make sure they don't get clobbered.
int reg_num = 0;
- for (; reg_num < Register::kNumRegisters; ++reg_num) {
- Register reg = Register::from_code(reg_num);
- if (reg.IsAllocatable()) {
- if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
- __ push(reg);
- param_offset += kPointerSize;
- }
+ for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
+ Register reg = Register::FromAllocationIndex(reg_num);
+ if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
+ __ push(reg);
+ param_offset += kPointerSize;
}
}
// Make sure no registers have been unexpectedly clobbered
for (--reg_num; reg_num >= 0; --reg_num) {
- Register reg = Register::from_code(reg_num);
- if (reg.IsAllocatable()) {
- if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
- __ cmp(reg, MemOperand(esp, 0));
- __ Assert(equal, kRegisterWasClobbered);
- __ add(esp, Immediate(kPointerSize));
- }
+ Register reg = Register::FromAllocationIndex(reg_num);
+ if (!reg.is(esp) && !reg.is(ebp) && !reg.is(destination_reg)) {
+ __ cmp(reg, MemOperand(esp, 0));
+ __ Assert(equal, kRegisterWasClobbered);
+ __ add(esp, Immediate(kPointerSize));
}
}
#include "src/factory.h"
#include "src/macro-assembler.h"
#include "src/mips/constants-mips.h"
-#include "src/register-configuration.h"
#include "src/simulator.h"
#include "test/cctest/cctest.h"
#include "test/cctest/test-code-stubs.h"
// Save registers make sure they don't get clobbered.
int source_reg_offset = kDoubleSize;
int reg_num = 2;
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
+ for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
Register reg = Register::from_code(reg_num);
if (!reg.is(destination_reg)) {
__ push(reg);
#include "src/factory.h"
#include "src/macro-assembler.h"
#include "src/mips64/constants-mips64.h"
-#include "src/register-configuration.h"
#include "src/simulator.h"
#include "test/cctest/cctest.h"
#include "test/cctest/test-code-stubs.h"
// Save registers make sure they don't get clobbered.
int source_reg_offset = kDoubleSize;
int reg_num = 2;
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
- for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
+ for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
Register reg = Register::from_code(reg_num);
if (!reg.is(destination_reg)) {
__ push(reg);
#include "src/code-stubs.h"
#include "src/factory.h"
#include "src/macro-assembler.h"
-#include "src/register-configuration.h"
#include "test/cctest/cctest.h"
#include "test/cctest/test-code-stubs.h"
__ pushq(rsi);
__ pushq(rdi);
-
- const RegisterConfiguration* config = RegisterConfiguration::ArchDefault();
if (!source_reg.is(rsp)) {
// The argument we pass to the stub is not a heap number, but instead
// stack-allocated and offset-wise made to look like a heap number for
// the stub. We create that "heap number" after pushing all allocatable
// registers.
int double_argument_slot =
- (config->num_allocatable_general_registers() - 1) * kPointerSize +
- kDoubleSize;
+ (Register::NumAllocatableRegisters() - 1) * kPointerSize + kDoubleSize;
__ leaq(source_reg, MemOperand(rsp, -double_argument_slot - offset));
}
// Save registers make sure they don't get clobbered.
int reg_num = 0;
- for (; reg_num < config->num_allocatable_general_registers(); ++reg_num) {
- Register reg =
- Register::from_code(config->GetAllocatableGeneralCode(reg_num));
+ for (;reg_num < Register::NumAllocatableRegisters(); ++reg_num) {
+ Register reg = Register::FromAllocationIndex(reg_num);
if (!reg.is(rsp) && !reg.is(rbp) && !reg.is(destination_reg)) {
__ pushq(reg);
}
// Make sure no registers have been unexpectedly clobbered
for (--reg_num; reg_num >= 0; --reg_num) {
- Register reg =
- Register::from_code(config->GetAllocatableGeneralCode(reg_num));
+ Register reg = Register::FromAllocationIndex(reg_num);
if (!reg.is(rsp) && !reg.is(rbp) && !reg.is(destination_reg)) {
__ cmpq(reg, MemOperand(rsp, 0));
__ Assert(equal, kRegisterWasClobbered);
if (!operand->IsUnallocated()) return false;
const UnallocatedOperand* unallocated = UnallocatedOperand::cast(operand);
if (!unallocated->HasFixedRegisterPolicy()) return false;
- return unallocated->fixed_register_index() == reg.code();
+ const int index = Register::ToAllocationIndex(reg);
+ return unallocated->fixed_register_index() == index;
}
RegisterConfiguration::kMaxDoubleRegisters)];
-namespace {
-static int allocatable_codes[InstructionSequenceTest::kDefaultNRegs] = {
- 0, 1, 2, 3, 4, 5, 6, 7};
-static int allocatable_double_codes[InstructionSequenceTest::kDefaultNRegs] = {
- 0, 1, 2, 3, 4, 5, 6, 7};
-}
-
-
static void InitializeRegisterNames() {
char* loc = register_names_;
for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) {
RegisterConfiguration* InstructionSequenceTest::config() {
if (config_.is_empty()) {
config_.Reset(new RegisterConfiguration(
- num_general_registers_, num_double_registers_, num_general_registers_,
- num_double_registers_, num_double_registers_, allocatable_codes,
- allocatable_double_codes, general_register_names_,
- double_register_names_));
+ num_general_registers_, num_double_registers_, num_double_registers_,
+ general_register_names_, double_register_names_));
}
return config_.get();
}
class InstructionSequenceTest : public TestWithIsolateAndZone {
public:
- static const int kDefaultNRegs = 8;
+ static const int kDefaultNRegs = 4;
static const int kNoValue = kMinInt;
typedef RpoNumber Rpo;
const AllocatedOperand& op,
const InstructionSequenceTest::TestOperand& test_op) {
return AreOperandsOfSameType(op, test_op) &&
- ((op.IsRegister() ? op.GetRegister().code() : op.index()) ==
- test_op.value_ ||
+ (op.index() == test_op.value_ ||
test_op.value_ == InstructionSequenceTest::kNoValue);
}
'../../src/compiler/register-allocator.h',
'../../src/compiler/register-allocator-verifier.cc',
'../../src/compiler/register-allocator-verifier.h',
+ '../../src/compiler/register-configuration.cc',
+ '../../src/compiler/register-configuration.h',
'../../src/compiler/representation-change.h',
'../../src/compiler/schedule.cc',
'../../src/compiler/schedule.h',
'../../src/regexp/regexp-macro-assembler.h',
'../../src/regexp/regexp-stack.cc',
'../../src/regexp/regexp-stack.h',
- '../../src/register-configuration.cc',
- '../../src/register-configuration.h',
'../../src/rewriter.cc',
'../../src/rewriter.h',
'../../src/runtime-profiler.cc',