Commit ec362684 authored by Yu Yin's avatar Yu Yin Committed by Commit Bot

[mips64][wasm-simd][liftoff] Support S128.

Port several CLs recorded in bug 9909.
We test this on 3A4000, and find many issues in MSA implement, but they are not related with this patch, will fix in another CL.
Looks like there is no 32-bit os for 3a4000, so we do not implements s128 for mips32.

Bug: v8:9909
Change-Id: Iad7569ebb92904bae66d420c8306cde24afb034a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2147575
Commit-Queue: Yu Yin <xwafish@gmail.com>
Reviewed-by: 's avatarZhi An Ng <zhin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#67259}
parent 6f7b4c7f
......@@ -642,7 +642,9 @@ config("toolchain") {
if (v8_can_use_fpu_instructions) {
defines += [ "CAN_USE_FPU_INSTRUCTIONS" ]
}
if (mips_use_msa) {
defines += [ "_MIPS_MSA" ]
}
if (host_byteorder == "little") {
defines += [ "V8_TARGET_ARCH_MIPS64_LE" ]
} else if (host_byteorder == "big") {
......@@ -658,9 +660,6 @@ config("toolchain") {
}
if (mips_arch_variant == "r6") {
defines += [ "_MIPS_ARCH_MIPS64R6" ]
if (mips_use_msa) {
defines += [ "_MIPS_MSA" ]
}
} else if (mips_arch_variant == "r2") {
defines += [ "_MIPS_ARCH_MIPS64R2" ]
}
......
......@@ -84,14 +84,12 @@ void CpuFeatures::ProbeImpl(bool cross_compile) {
// Probe for additional features at runtime.
base::CPU cpu;
if (cpu.has_fpu()) supported_ |= 1u << FPU;
#if defined(_MIPS_ARCH_MIPS64R6)
#if defined(_MIPS_MSA)
supported_ |= 1u << MIPS_SIMD;
#else
if (cpu.has_msa()) supported_ |= 1u << MIPS_SIMD;
#endif
#endif
#endif
}
void CpuFeatures::PrintTarget() {}
......@@ -261,6 +259,9 @@ Assembler::Assembler(const AssemblerOptions& options,
std::unique_ptr<AssemblerBuffer> buffer)
: AssemblerBase(options, std::move(buffer)),
scratch_register_list_(at.bit()) {
if (CpuFeatures::IsSupported(MIPS_SIMD)) {
EnableCpuFeature(MIPS_SIMD);
}
reloc_info_writer.Reposition(buffer_start_ + buffer_->size(), pc_);
last_trampoline_pool_end_ = 0;
......@@ -1169,7 +1170,7 @@ void Assembler::GenInstrJump(Opcode opcode, uint32_t address) {
// MSA instructions
void Assembler::GenInstrMsaI8(SecondaryField operation, uint32_t imm8,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid() && is_uint8(imm8));
Instr instr = MSA | operation | ((imm8 & kImm8Mask) << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
......@@ -1178,7 +1179,7 @@ void Assembler::GenInstrMsaI8(SecondaryField operation, uint32_t imm8,
void Assembler::GenInstrMsaI5(SecondaryField operation, SecondaryField df,
int32_t imm5, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
DCHECK((operation == MAXI_S) || (operation == MINI_S) ||
(operation == CEQI) || (operation == CLTI_S) ||
......@@ -1192,7 +1193,7 @@ void Assembler::GenInstrMsaI5(SecondaryField operation, SecondaryField df,
void Assembler::GenInstrMsaBit(SecondaryField operation, SecondaryField df,
uint32_t m, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid() && is_valid_msa_df_m(df, m));
Instr instr = MSA | operation | df | (m << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
......@@ -1201,7 +1202,7 @@ void Assembler::GenInstrMsaBit(SecondaryField operation, SecondaryField df,
void Assembler::GenInstrMsaI10(SecondaryField operation, SecondaryField df,
int32_t imm10, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(wd.is_valid() && is_int10(imm10));
Instr instr = MSA | operation | df | ((imm10 & kImm10Mask) << kWsShift) |
(wd.code() << kWdShift);
......@@ -1211,7 +1212,7 @@ void Assembler::GenInstrMsaI10(SecondaryField operation, SecondaryField df,
template <typename RegType>
void Assembler::GenInstrMsa3R(SecondaryField operation, SecondaryField df,
RegType t, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(t.is_valid() && ws.is_valid() && wd.is_valid());
Instr instr = MSA | operation | df | (t.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift);
......@@ -1221,7 +1222,7 @@ void Assembler::GenInstrMsa3R(SecondaryField operation, SecondaryField df,
template <typename DstType, typename SrcType>
void Assembler::GenInstrMsaElm(SecondaryField operation, SecondaryField df,
uint32_t n, SrcType src, DstType dst) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(src.is_valid() && dst.is_valid() && is_valid_msa_df_n(df, n));
Instr instr = MSA | operation | df | (n << kWtShift) |
(src.code() << kWsShift) | (dst.code() << kWdShift) |
......@@ -1231,7 +1232,7 @@ void Assembler::GenInstrMsaElm(SecondaryField operation, SecondaryField df,
void Assembler::GenInstrMsa3RF(SecondaryField operation, uint32_t df,
MSARegister wt, MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
DCHECK_LT(df, 2);
Instr instr = MSA | operation | (df << 21) | (wt.code() << kWtShift) |
......@@ -1241,7 +1242,7 @@ void Assembler::GenInstrMsa3RF(SecondaryField operation, uint32_t df,
void Assembler::GenInstrMsaVec(SecondaryField operation, MSARegister wt,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && ws.is_valid() && wd.is_valid());
Instr instr = MSA | operation | (wt.code() << kWtShift) |
(ws.code() << kWsShift) | (wd.code() << kWdShift) |
......@@ -1251,7 +1252,7 @@ void Assembler::GenInstrMsaVec(SecondaryField operation, MSARegister wt,
void Assembler::GenInstrMsaMI10(SecondaryField operation, int32_t s10,
Register rs, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(rs.is_valid() && wd.is_valid() && is_int10(s10));
Instr instr = MSA | operation | ((s10 & kImm10Mask) << kWtShift) |
(rs.code() << kWsShift) | (wd.code() << kWdShift);
......@@ -1260,7 +1261,7 @@ void Assembler::GenInstrMsaMI10(SecondaryField operation, int32_t s10,
void Assembler::GenInstrMsa2R(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MSA_2R_FORMAT | operation | df | (ws.code() << kWsShift) |
(wd.code() << kWdShift) | MSA_VEC_2R_2RF_MINOR;
......@@ -1269,7 +1270,7 @@ void Assembler::GenInstrMsa2R(SecondaryField operation, SecondaryField df,
void Assembler::GenInstrMsa2RF(SecondaryField operation, SecondaryField df,
MSARegister ws, MSARegister wd) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(ws.is_valid() && wd.is_valid());
Instr instr = MSA | MSA_2RF_FORMAT | operation | df |
(ws.code() << kWsShift) | (wd.code() << kWdShift) |
......@@ -1279,7 +1280,7 @@ void Assembler::GenInstrMsa2RF(SecondaryField operation, SecondaryField df,
void Assembler::GenInstrMsaBranch(SecondaryField operation, MSARegister wt,
int32_t offset16) {
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD));
DCHECK(IsEnabled(MIPS_SIMD));
DCHECK(wt.is_valid() && is_int16(offset16));
BlockTrampolinePoolScope block_trampoline_pool(this);
Instr instr =
......@@ -3157,28 +3158,29 @@ MSA_BRANCH_LIST(MSA_BRANCH)
#undef MSA_BRANCH_LIST
#define MSA_LD_ST_LIST(V) \
V(ld_b, LD_B) \
V(ld_h, LD_H) \
V(ld_w, LD_W) \
V(ld_d, LD_D) \
V(st_b, ST_B) \
V(st_h, ST_H) \
V(st_w, ST_W) \
V(st_d, ST_D)
#define MSA_LD_ST(name, opcode) \
void Assembler::name(MSARegister wd, const MemOperand& rs) { \
MemOperand source = rs; \
AdjustBaseAndOffset(&source); \
if (is_int10(source.offset())) { \
GenInstrMsaMI10(opcode, source.offset(), source.rm(), wd); \
} else { \
UseScratchRegisterScope temps(this); \
Register scratch = temps.Acquire(); \
DCHECK(rs.rm() != scratch); \
daddiu(scratch, source.rm(), source.offset()); \
GenInstrMsaMI10(opcode, 0, scratch, wd); \
} \
V(ld_b, LD_B, 1) \
V(ld_h, LD_H, 2) \
V(ld_w, LD_W, 4) \
V(ld_d, LD_D, 8) \
V(st_b, ST_B, 1) \
V(st_h, ST_H, 2) \
V(st_w, ST_W, 4) \
V(st_d, ST_D, 8)
#define MSA_LD_ST(name, opcode, b) \
void Assembler::name(MSARegister wd, const MemOperand& rs) { \
MemOperand source = rs; \
AdjustBaseAndOffset(&source); \
if (is_int10(source.offset())) { \
DCHECK_EQ(source.offset() % b, 0); \
GenInstrMsaMI10(opcode, source.offset() / b, source.rm(), wd); \
} else { \
UseScratchRegisterScope temps(this); \
Register scratch = temps.Acquire(); \
DCHECK_NE(rs.rm(), scratch); \
daddiu(scratch, source.rm(), source.offset()); \
GenInstrMsaMI10(opcode, 0, scratch, wd); \
} \
}
MSA_LD_ST_LIST(MSA_LD_ST)
......@@ -3291,7 +3293,7 @@ MSA_2R_LIST(MSA_2R)
#define MSA_FILL(format) \
void Assembler::fill_##format(MSARegister wd, Register rs) { \
DCHECK((kArchVariant == kMips64r6) && IsEnabled(MIPS_SIMD)); \
DCHECK(IsEnabled(MIPS_SIMD)); \
DCHECK(rs.is_valid() && wd.is_valid()); \
Instr instr = MSA | MSA_2R_FORMAT | FILL | MSA_2R_DF_##format | \
(rs.code() << kWsShift) | (wd.code() << kWdShift) | \
......
......@@ -2729,7 +2729,7 @@ void TurboAssembler::BranchMSA(Label* target, MSABranchDF df,
void TurboAssembler::BranchShortMSA(MSABranchDF df, Label* target,
MSABranchCondition cond, MSARegister wt,
BranchDelaySlot bd) {
if (kArchVariant == kMips64r6) {
if (IsEnabled(MIPS_SIMD)) {
BlockTrampolinePoolScope block_trampoline_pool(this);
if (target) {
switch (cond) {
......@@ -2775,6 +2775,8 @@ void TurboAssembler::BranchShortMSA(MSABranchDF df, Label* target,
UNREACHABLE();
}
}
} else {
UNREACHABLE();
}
if (bd == PROTECT) {
nop();
......
......@@ -207,6 +207,19 @@ constexpr bool kPadArguments = false;
constexpr bool kSimpleFPAliasing = true;
constexpr bool kSimdMaskRegisters = false;
enum MSARegisterCode {
#define REGISTER_CODE(R) kMsaCode_##R,
SIMD128_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kMsaAfterLast
};
// MIPS SIMD (MSA) register
class MSARegister : public RegisterBase<MSARegister, kMsaAfterLast> {
friend class RegisterBase;
explicit constexpr MSARegister(int code) : RegisterBase(code) {}
};
enum DoubleRegisterCode {
#define REGISTER_CODE(R) kDoubleCode_##R,
DOUBLE_REGISTERS(REGISTER_CODE)
......@@ -234,24 +247,13 @@ class FPURegister : public RegisterBase<FPURegister, kDoubleAfterLast> {
return FPURegister::from_code(code() + 1);
}
MSARegister toW() const { return MSARegister::from_code(code()); }
private:
friend class RegisterBase;
explicit constexpr FPURegister(int code) : RegisterBase(code) {}
};
enum MSARegisterCode {
#define REGISTER_CODE(R) kMsaCode_##R,
SIMD128_REGISTERS(REGISTER_CODE)
#undef REGISTER_CODE
kMsaAfterLast
};
// MIPS SIMD (MSA) register
class MSARegister : public RegisterBase<MSARegister, kMsaAfterLast> {
friend class RegisterBase;
explicit constexpr MSARegister(int code) : RegisterBase(code) {}
};
// A few double registers are reserved: one as a scratch register and one to
// hold 0.0.
// f28: 0.0
......
......@@ -61,6 +61,9 @@ inline void Load(LiftoffAssembler* assm, LiftoffRegister dst, MemOperand src,
case ValueType::kF64:
assm->Ldc1(dst.fp(), src);
break;
case ValueType::kS128:
assm->ld_d(dst.fp().toW(), src);
break;
default:
UNREACHABLE();
}
......@@ -104,6 +107,10 @@ inline void push(LiftoffAssembler* assm, LiftoffRegister reg, ValueType type) {
assm->daddiu(sp, sp, -kSystemPointerSize);
assm->Sdc1(reg.fp(), MemOperand(sp, 0));
break;
case ValueType::kS128:
assm->daddiu(sp, sp, -kSystemPointerSize * 2);
assm->st_d(reg.fp().toW(), MemOperand(sp, 0));
break;
default:
UNREACHABLE();
}
......@@ -374,6 +381,9 @@ void LiftoffAssembler::Load(LiftoffRegister dst, Register src_addr,
case LoadType::kF64Load:
TurboAssembler::Uldc1(dst.fp(), src_op, t8);
break;
case LoadType::kS128Load:
TurboAssembler::ld_d(dst.fp().toW(), src_op);
break;
default:
UNREACHABLE();
}
......@@ -437,6 +447,9 @@ void LiftoffAssembler::Store(Register dst_addr, Register offset_reg,
case StoreType::kF64Store:
TurboAssembler::Usdc1(src.fp(), dst_op, t8);
break;
case StoreType::kS128Store:
TurboAssembler::st_d(src.fp().toW(), dst_op);
break;
default:
UNREACHABLE();
}
......@@ -524,7 +537,11 @@ void LiftoffAssembler::Move(Register dst, Register src, ValueType type) {
void LiftoffAssembler::Move(DoubleRegister dst, DoubleRegister src,
ValueType type) {
DCHECK_NE(dst, src);
TurboAssembler::Move(dst, src);
if (type != kWasmS128) {
TurboAssembler::Move(dst, src);
} else {
TurboAssembler::move_v(dst.toW(), src.toW());
}
}
void LiftoffAssembler::Spill(int offset, LiftoffRegister reg, ValueType type) {
......@@ -543,6 +560,9 @@ void LiftoffAssembler::Spill(int offset, LiftoffRegister reg, ValueType type) {
case ValueType::kF64:
TurboAssembler::Sdc1(reg.fp(), dst);
break;
case ValueType::kS128:
TurboAssembler::st_d(reg.fp().toW(), dst);
break;
default:
UNREACHABLE();
}
......@@ -586,6 +606,9 @@ void LiftoffAssembler::Fill(LiftoffRegister reg, int offset, ValueType type) {
case ValueType::kF64:
TurboAssembler::Ldc1(reg.fp(), src);
break;
case ValueType::kS128:
TurboAssembler::ld_d(reg.fp().toW(), src);
break;
default:
UNREACHABLE();
}
......@@ -2178,15 +2201,20 @@ void LiftoffAssembler::PushRegisters(LiftoffRegList regs) {
LiftoffRegList fp_regs = regs & kFpCacheRegList;
unsigned num_fp_regs = fp_regs.GetNumRegsSet();
if (num_fp_regs) {
daddiu(sp, sp, -(num_fp_regs * kStackSlotSize));
unsigned slot_size = IsEnabled(MIPS_SIMD) ? 16 : 8;
daddiu(sp, sp, -(num_fp_regs * slot_size));
unsigned offset = 0;
while (!fp_regs.is_empty()) {
LiftoffRegister reg = fp_regs.GetFirstRegSet();
TurboAssembler::Sdc1(reg.fp(), MemOperand(sp, offset));
if (IsEnabled(MIPS_SIMD)) {
TurboAssembler::st_d(reg.fp().toW(), MemOperand(sp, offset));
} else {
TurboAssembler::Sdc1(reg.fp(), MemOperand(sp, offset));
}
fp_regs.clear(reg);
offset += sizeof(double);
offset += slot_size;
}
DCHECK_EQ(offset, num_fp_regs * sizeof(double));
DCHECK_EQ(offset, num_fp_regs * slot_size);
}
}
......@@ -2195,9 +2223,13 @@ void LiftoffAssembler::PopRegisters(LiftoffRegList regs) {
unsigned fp_offset = 0;
while (!fp_regs.is_empty()) {
LiftoffRegister reg = fp_regs.GetFirstRegSet();
TurboAssembler::Ldc1(reg.fp(), MemOperand(sp, fp_offset));
if (IsEnabled(MIPS_SIMD)) {
TurboAssembler::ld_d(reg.fp().toW(), MemOperand(sp, fp_offset));
} else {
TurboAssembler::Ldc1(reg.fp(), MemOperand(sp, fp_offset));
}
fp_regs.clear(reg);
fp_offset += sizeof(double);
fp_offset += (IsEnabled(MIPS_SIMD) ? 16 : 8);
}
if (fp_offset) daddiu(sp, sp, fp_offset);
LiftoffRegList gp_regs = regs & kGpCacheRegList;
......@@ -2295,8 +2327,15 @@ void LiftoffStackSlots::Construct() {
const LiftoffAssembler::VarState& src = slot.src_;
switch (src.loc()) {
case LiftoffAssembler::VarState::kStack:
asm_->ld(kScratchReg, liftoff::GetStackSlot(slot.src_offset_));
asm_->push(kScratchReg);
if (src.type() != kWasmS128) {
asm_->ld(kScratchReg, liftoff::GetStackSlot(slot.src_offset_));
asm_->push(kScratchReg);
} else {
asm_->ld(kScratchReg, liftoff::GetStackSlot(slot.src_offset_ - 8));
asm_->push(kScratchReg);
asm_->ld(kScratchReg, liftoff::GetStackSlot(slot.src_offset_));
asm_->push(kScratchReg);
}
break;
case LiftoffAssembler::VarState::kRegister:
liftoff::push(asm_, src.reg(), src.type());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment