MIPS[64]: Support for some SIMD operations (8)
Add support for S1x4And, S1x4Or, S1x4Xor, S1x4Not, S1x4AnyTrue, S1x4AllTrue, S1x8And, S1x8Or, S1x8Xor, S1x8Not, S1x8AnyTrue, S1x8AllTrue, S1x16And, S1x16Or, S1x16Xor, S1x16Not, S1x16AnyTrue, S1x16AllTrue, SimdLoad, SimdStore operations for mips32 and mips64 architectures. BUG= Review-Url: https://codereview.chromium.org/2801683003 Cr-Commit-Position: refs/heads/master@{#45662}
This commit is contained in:
parent
6a99238b90
commit
3e3dbdf3e5
@ -2451,7 +2451,7 @@ void InstructionSelector::VisitS8x16Select(Node* node) { UNIMPLEMENTED(); }
|
|||||||
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS &&
|
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS &&
|
||||||
// !V8_TARGET_ARCH_MIPS64
|
// !V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
#if !V8_TARGET_ARCH_ARM
|
#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
|
||||||
void InstructionSelector::VisitS1x4And(Node* node) { UNIMPLEMENTED(); }
|
void InstructionSelector::VisitS1x4And(Node* node) { UNIMPLEMENTED(); }
|
||||||
|
|
||||||
void InstructionSelector::VisitS1x4Or(Node* node) { UNIMPLEMENTED(); }
|
void InstructionSelector::VisitS1x4Or(Node* node) { UNIMPLEMENTED(); }
|
||||||
@ -2487,7 +2487,7 @@ void InstructionSelector::VisitS1x16Not(Node* node) { UNIMPLEMENTED(); }
|
|||||||
void InstructionSelector::VisitS1x16AnyTrue(Node* node) { UNIMPLEMENTED(); }
|
void InstructionSelector::VisitS1x16AnyTrue(Node* node) { UNIMPLEMENTED(); }
|
||||||
|
|
||||||
void InstructionSelector::VisitS1x16AllTrue(Node* node) { UNIMPLEMENTED(); }
|
void InstructionSelector::VisitS1x16AllTrue(Node* node) { UNIMPLEMENTED(); }
|
||||||
#endif // !V8_TARGET_ARCH_ARM
|
#endif // !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_MIPS && !V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
|
void InstructionSelector::VisitFinishRegion(Node* node) { EmitIdentity(node); }
|
||||||
|
|
||||||
|
@ -2226,6 +2226,63 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
i.InputSimd128Register(0));
|
i.InputSimd128Register(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kMipsS1x4AnyTrue:
|
||||||
|
case kMipsS1x8AnyTrue:
|
||||||
|
case kMipsS1x16AnyTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_false;
|
||||||
|
|
||||||
|
__ BranchMSA(&all_false, MSA_BRANCH_V, all_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, 0); // branch delay slot
|
||||||
|
__ li(dst, -1);
|
||||||
|
__ bind(&all_false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMipsS1x4AllTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_true;
|
||||||
|
__ BranchMSA(&all_true, MSA_BRANCH_W, all_not_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, -1); // branch delay slot
|
||||||
|
__ li(dst, 0);
|
||||||
|
__ bind(&all_true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMipsS1x8AllTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_true;
|
||||||
|
__ BranchMSA(&all_true, MSA_BRANCH_H, all_not_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, -1); // branch delay slot
|
||||||
|
__ li(dst, 0);
|
||||||
|
__ bind(&all_true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMipsS1x16AllTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_true;
|
||||||
|
__ BranchMSA(&all_true, MSA_BRANCH_B, all_not_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, -1); // branch delay slot
|
||||||
|
__ li(dst, 0);
|
||||||
|
__ bind(&all_true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMipsMsaLd: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
__ ld_b(i.OutputSimd128Register(), i.MemoryOperand());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMipsMsaSt: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
__ st_b(i.InputSimd128Register(2), i.MemoryOperand());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return kSuccess;
|
return kSuccess;
|
||||||
} // NOLINT(readability/fn_size)
|
} // NOLINT(readability/fn_size)
|
||||||
|
@ -228,7 +228,15 @@ namespace compiler {
|
|||||||
V(MipsS128And) \
|
V(MipsS128And) \
|
||||||
V(MipsS128Or) \
|
V(MipsS128Or) \
|
||||||
V(MipsS128Xor) \
|
V(MipsS128Xor) \
|
||||||
V(MipsS128Not)
|
V(MipsS128Not) \
|
||||||
|
V(MipsS1x4AnyTrue) \
|
||||||
|
V(MipsS1x4AllTrue) \
|
||||||
|
V(MipsS1x8AnyTrue) \
|
||||||
|
V(MipsS1x8AllTrue) \
|
||||||
|
V(MipsS1x16AnyTrue) \
|
||||||
|
V(MipsS1x16AllTrue) \
|
||||||
|
V(MipsMsaLd) \
|
||||||
|
V(MipsMsaSt)
|
||||||
|
|
||||||
// Addressing modes represent the "shape" of inputs to an instruction.
|
// Addressing modes represent the "shape" of inputs to an instruction.
|
||||||
// Many instructions support multiple addressing modes. Addressing modes
|
// Many instructions support multiple addressing modes. Addressing modes
|
||||||
|
@ -294,8 +294,10 @@ void InstructionSelector::VisitLoad(Node* node) {
|
|||||||
case MachineRepresentation::kWord32:
|
case MachineRepresentation::kWord32:
|
||||||
opcode = kMipsLw;
|
opcode = kMipsLw;
|
||||||
break;
|
break;
|
||||||
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMipsMsaLd;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kWord64: // Fall through.
|
case MachineRepresentation::kWord64: // Fall through.
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -382,8 +384,10 @@ void InstructionSelector::VisitStore(Node* node) {
|
|||||||
case MachineRepresentation::kWord32:
|
case MachineRepresentation::kWord32:
|
||||||
opcode = kMipsSw;
|
opcode = kMipsSw;
|
||||||
break;
|
break;
|
||||||
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMipsMsaSt;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kWord64: // Fall through.
|
case MachineRepresentation::kWord64: // Fall through.
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -1234,8 +1238,10 @@ void InstructionSelector::VisitUnalignedLoad(Node* node) {
|
|||||||
case MachineRepresentation::kFloat64:
|
case MachineRepresentation::kFloat64:
|
||||||
opcode = kMipsUldc1;
|
opcode = kMipsUldc1;
|
||||||
break;
|
break;
|
||||||
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMipsMsaLd;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kWord64: // Fall through.
|
case MachineRepresentation::kWord64: // Fall through.
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -1287,8 +1293,10 @@ void InstructionSelector::VisitUnalignedStore(Node* node) {
|
|||||||
case MachineRepresentation::kWord32:
|
case MachineRepresentation::kWord32:
|
||||||
opcode = kMipsUsw;
|
opcode = kMipsUsw;
|
||||||
break;
|
break;
|
||||||
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMipsMsaSt;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kWord64: // Fall through.
|
case MachineRepresentation::kWord64: // Fall through.
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -2341,6 +2349,78 @@ void InstructionSelector::VisitS128Not(Node* node) {
|
|||||||
VisitRR(this, kMipsS128Not, node);
|
VisitRR(this, kMipsS128Not, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4And(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128And, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4Or(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128Or, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4Xor(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128Xor, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4Not(Node* node) {
|
||||||
|
VisitRR(this, kMipsS128Not, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4AnyTrue(Node* node) {
|
||||||
|
VisitRR(this, kMipsS1x4AnyTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4AllTrue(Node* node) {
|
||||||
|
VisitRR(this, kMipsS1x4AllTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8And(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128And, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8Or(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128Or, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8Xor(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128Xor, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8Not(Node* node) {
|
||||||
|
VisitRR(this, kMipsS128Not, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8AnyTrue(Node* node) {
|
||||||
|
VisitRR(this, kMipsS1x8AnyTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8AllTrue(Node* node) {
|
||||||
|
VisitRR(this, kMipsS1x8AllTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16And(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128And, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16Or(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128Or, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16Xor(Node* node) {
|
||||||
|
VisitRRR(this, kMipsS128Xor, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16Not(Node* node) {
|
||||||
|
VisitRR(this, kMipsS128Not, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16AnyTrue(Node* node) {
|
||||||
|
VisitRR(this, kMipsS1x16AnyTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16AllTrue(Node* node) {
|
||||||
|
VisitRR(this, kMipsS1x16AllTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
MachineOperatorBuilder::Flags
|
MachineOperatorBuilder::Flags
|
||||||
InstructionSelector::SupportedMachineOperatorFlags() {
|
InstructionSelector::SupportedMachineOperatorFlags() {
|
||||||
|
@ -2546,6 +2546,62 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
|||||||
i.InputSimd128Register(0));
|
i.InputSimd128Register(0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case kMips64S1x4AnyTrue:
|
||||||
|
case kMips64S1x8AnyTrue:
|
||||||
|
case kMips64S1x16AnyTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_false;
|
||||||
|
__ BranchMSA(&all_false, MSA_BRANCH_V, all_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, 0); // branch delay slot
|
||||||
|
__ li(dst, -1);
|
||||||
|
__ bind(&all_false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMips64S1x4AllTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_true;
|
||||||
|
__ BranchMSA(&all_true, MSA_BRANCH_W, all_not_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, -1); // branch delay slot
|
||||||
|
__ li(dst, 0);
|
||||||
|
__ bind(&all_true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMips64S1x8AllTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_true;
|
||||||
|
__ BranchMSA(&all_true, MSA_BRANCH_H, all_not_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, -1); // branch delay slot
|
||||||
|
__ li(dst, 0);
|
||||||
|
__ bind(&all_true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMips64S1x16AllTrue: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
Register dst = i.OutputRegister();
|
||||||
|
Label all_true;
|
||||||
|
__ BranchMSA(&all_true, MSA_BRANCH_B, all_not_zero,
|
||||||
|
i.InputSimd128Register(0), USE_DELAY_SLOT);
|
||||||
|
__ li(dst, -1); // branch delay slot
|
||||||
|
__ li(dst, 0);
|
||||||
|
__ bind(&all_true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMips64MsaLd: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
__ ld_b(i.OutputSimd128Register(), i.MemoryOperand());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case kMips64MsaSt: {
|
||||||
|
CpuFeatureScope msa_scope(masm(), MIPS_SIMD);
|
||||||
|
__ st_b(i.InputSimd128Register(2), i.MemoryOperand());
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return kSuccess;
|
return kSuccess;
|
||||||
} // NOLINT(readability/fn_size)
|
} // NOLINT(readability/fn_size)
|
||||||
|
@ -262,7 +262,15 @@ namespace compiler {
|
|||||||
V(Mips64S128And) \
|
V(Mips64S128And) \
|
||||||
V(Mips64S128Or) \
|
V(Mips64S128Or) \
|
||||||
V(Mips64S128Xor) \
|
V(Mips64S128Xor) \
|
||||||
V(Mips64S128Not)
|
V(Mips64S128Not) \
|
||||||
|
V(Mips64S1x4AnyTrue) \
|
||||||
|
V(Mips64S1x4AllTrue) \
|
||||||
|
V(Mips64S1x8AnyTrue) \
|
||||||
|
V(Mips64S1x8AllTrue) \
|
||||||
|
V(Mips64S1x16AnyTrue) \
|
||||||
|
V(Mips64S1x16AllTrue) \
|
||||||
|
V(Mips64MsaLd) \
|
||||||
|
V(Mips64MsaSt)
|
||||||
|
|
||||||
// Addressing modes represent the "shape" of inputs to an instruction.
|
// Addressing modes represent the "shape" of inputs to an instruction.
|
||||||
// Many instructions support multiple addressing modes. Addressing modes
|
// Many instructions support multiple addressing modes. Addressing modes
|
||||||
|
@ -411,7 +411,9 @@ void InstructionSelector::VisitLoad(Node* node) {
|
|||||||
case MachineRepresentation::kWord64:
|
case MachineRepresentation::kWord64:
|
||||||
opcode = kMips64Ld;
|
opcode = kMips64Ld;
|
||||||
break;
|
break;
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMips64MsaLd;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -491,7 +493,9 @@ void InstructionSelector::VisitStore(Node* node) {
|
|||||||
case MachineRepresentation::kWord64:
|
case MachineRepresentation::kWord64:
|
||||||
opcode = kMips64Sd;
|
opcode = kMips64Sd;
|
||||||
break;
|
break;
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMips64MsaSt;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -1785,7 +1789,9 @@ void InstructionSelector::VisitUnalignedLoad(Node* node) {
|
|||||||
case MachineRepresentation::kWord64:
|
case MachineRepresentation::kWord64:
|
||||||
opcode = kMips64Uld;
|
opcode = kMips64Uld;
|
||||||
break;
|
break;
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMips64MsaLd;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -1838,7 +1844,9 @@ void InstructionSelector::VisitUnalignedStore(Node* node) {
|
|||||||
case MachineRepresentation::kWord64:
|
case MachineRepresentation::kWord64:
|
||||||
opcode = kMips64Usd;
|
opcode = kMips64Usd;
|
||||||
break;
|
break;
|
||||||
case MachineRepresentation::kSimd128: // Fall through.
|
case MachineRepresentation::kSimd128:
|
||||||
|
opcode = kMips64MsaSt;
|
||||||
|
break;
|
||||||
case MachineRepresentation::kSimd1x4: // Fall through.
|
case MachineRepresentation::kSimd1x4: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x8: // Fall through.
|
case MachineRepresentation::kSimd1x8: // Fall through.
|
||||||
case MachineRepresentation::kSimd1x16: // Fall through.
|
case MachineRepresentation::kSimd1x16: // Fall through.
|
||||||
@ -3093,6 +3101,78 @@ void InstructionSelector::VisitS128Not(Node* node) {
|
|||||||
VisitRR(this, kMips64S128Not, node);
|
VisitRR(this, kMips64S128Not, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4And(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128And, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4Or(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128Or, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4Xor(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128Xor, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4Not(Node* node) {
|
||||||
|
VisitRR(this, kMips64S128Not, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4AnyTrue(Node* node) {
|
||||||
|
VisitRR(this, kMips64S1x4AnyTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x4AllTrue(Node* node) {
|
||||||
|
VisitRR(this, kMips64S1x4AllTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8And(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128And, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8Or(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128Or, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8Xor(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128Xor, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8Not(Node* node) {
|
||||||
|
VisitRR(this, kMips64S128Not, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8AnyTrue(Node* node) {
|
||||||
|
VisitRR(this, kMips64S1x8AnyTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x8AllTrue(Node* node) {
|
||||||
|
VisitRR(this, kMips64S1x8AllTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16And(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128And, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16Or(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128Or, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16Xor(Node* node) {
|
||||||
|
VisitRRR(this, kMips64S128Xor, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16Not(Node* node) {
|
||||||
|
VisitRR(this, kMips64S128Not, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16AnyTrue(Node* node) {
|
||||||
|
VisitRR(this, kMips64S1x16AnyTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstructionSelector::VisitS1x16AllTrue(Node* node) {
|
||||||
|
VisitRR(this, kMips64S1x16AllTrue, node);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
MachineOperatorBuilder::Flags
|
MachineOperatorBuilder::Flags
|
||||||
InstructionSelector::SupportedMachineOperatorFlags() {
|
InstructionSelector::SupportedMachineOperatorFlags() {
|
||||||
|
@ -479,6 +479,29 @@ const int kEndOfChain = -4;
|
|||||||
// Determines the end of the Jump chain (a subset of the label link chain).
|
// Determines the end of the Jump chain (a subset of the label link chain).
|
||||||
const int kEndOfJumpChain = 0;
|
const int kEndOfJumpChain = 0;
|
||||||
|
|
||||||
|
bool Assembler::IsMsaBranch(Instr instr) {
|
||||||
|
uint32_t opcode = GetOpcodeField(instr);
|
||||||
|
uint32_t rs_field = GetRsField(instr);
|
||||||
|
if (opcode == COP1) {
|
||||||
|
switch (rs_field) {
|
||||||
|
case BZ_V:
|
||||||
|
case BZ_B:
|
||||||
|
case BZ_H:
|
||||||
|
case BZ_W:
|
||||||
|
case BZ_D:
|
||||||
|
case BNZ_V:
|
||||||
|
case BNZ_B:
|
||||||
|
case BNZ_H:
|
||||||
|
case BNZ_W:
|
||||||
|
case BNZ_D:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Assembler::IsBranch(Instr instr) {
|
bool Assembler::IsBranch(Instr instr) {
|
||||||
uint32_t opcode = GetOpcodeField(instr);
|
uint32_t opcode = GetOpcodeField(instr);
|
||||||
@ -492,7 +515,7 @@ bool Assembler::IsBranch(Instr instr) {
|
|||||||
rt_field == BLTZAL || rt_field == BGEZAL)) ||
|
rt_field == BLTZAL || rt_field == BGEZAL)) ||
|
||||||
(opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
|
(opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
|
||||||
(opcode == COP1 && rs_field == BC1EQZ) ||
|
(opcode == COP1 && rs_field == BC1EQZ) ||
|
||||||
(opcode == COP1 && rs_field == BC1NEZ);
|
(opcode == COP1 && rs_field == BC1NEZ) || IsMsaBranch(instr);
|
||||||
if (!isBranch && IsMipsArchVariant(kMips32r6)) {
|
if (!isBranch && IsMipsArchVariant(kMips32r6)) {
|
||||||
// All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
|
// All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
|
||||||
// POP30 (BNVC, BNEC, BNEZALC) are branch ops.
|
// POP30 (BNVC, BNEC, BNEZALC) are branch ops.
|
||||||
|
@ -1104,15 +1104,45 @@ class Assembler : public AssemblerBase {
|
|||||||
|
|
||||||
// MSA instructions
|
// MSA instructions
|
||||||
void bz_v(MSARegister wt, int16_t offset);
|
void bz_v(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_v(MSARegister wt, Label* L) {
|
||||||
|
bz_v(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_b(MSARegister wt, int16_t offset);
|
void bz_b(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_b(MSARegister wt, Label* L) {
|
||||||
|
bz_b(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_h(MSARegister wt, int16_t offset);
|
void bz_h(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_h(MSARegister wt, Label* L) {
|
||||||
|
bz_h(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_w(MSARegister wt, int16_t offset);
|
void bz_w(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_w(MSARegister wt, Label* L) {
|
||||||
|
bz_w(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_d(MSARegister wt, int16_t offset);
|
void bz_d(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_d(MSARegister wt, Label* L) {
|
||||||
|
bz_d(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_v(MSARegister wt, int16_t offset);
|
void bnz_v(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_v(MSARegister wt, Label* L) {
|
||||||
|
bnz_v(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_b(MSARegister wt, int16_t offset);
|
void bnz_b(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_b(MSARegister wt, Label* L) {
|
||||||
|
bnz_b(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_h(MSARegister wt, int16_t offset);
|
void bnz_h(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_h(MSARegister wt, Label* L) {
|
||||||
|
bnz_h(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_w(MSARegister wt, int16_t offset);
|
void bnz_w(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_w(MSARegister wt, Label* L) {
|
||||||
|
bnz_w(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_d(MSARegister wt, int16_t offset);
|
void bnz_d(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_d(MSARegister wt, Label* L) {
|
||||||
|
bnz_d(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
|
|
||||||
void ld_b(MSARegister wd, const MemOperand& rs);
|
void ld_b(MSARegister wd, const MemOperand& rs);
|
||||||
void ld_h(MSARegister wd, const MemOperand& rs);
|
void ld_h(MSARegister wd, const MemOperand& rs);
|
||||||
@ -1767,6 +1797,7 @@ class Assembler : public AssemblerBase {
|
|||||||
|
|
||||||
// Check if an instruction is a branch of some kind.
|
// Check if an instruction is a branch of some kind.
|
||||||
static bool IsBranch(Instr instr);
|
static bool IsBranch(Instr instr);
|
||||||
|
static bool IsMsaBranch(Instr instr);
|
||||||
static bool IsBc(Instr instr);
|
static bool IsBc(Instr instr);
|
||||||
static bool IsBzc(Instr instr);
|
static bool IsBzc(Instr instr);
|
||||||
static bool IsBeq(Instr instr);
|
static bool IsBeq(Instr instr);
|
||||||
|
@ -1061,6 +1061,36 @@ inline Condition NegateFpuCondition(Condition cc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MSABranchCondition {
|
||||||
|
all_not_zero = 0, // Branch If All Elements Are Not Zero
|
||||||
|
one_elem_not_zero, // Branch If At Least One Element of Any Format Is Not
|
||||||
|
// Zero
|
||||||
|
one_elem_zero, // Branch If At Least One Element Is Zero
|
||||||
|
all_zero // Branch If All Elements of Any Format Are Zero
|
||||||
|
};
|
||||||
|
|
||||||
|
inline MSABranchCondition NegateMSABranchCondition(MSABranchCondition cond) {
|
||||||
|
switch (cond) {
|
||||||
|
case all_not_zero:
|
||||||
|
return one_elem_zero;
|
||||||
|
case one_elem_not_zero:
|
||||||
|
return all_zero;
|
||||||
|
case one_elem_zero:
|
||||||
|
return all_not_zero;
|
||||||
|
case all_zero:
|
||||||
|
return one_elem_not_zero;
|
||||||
|
default:
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MSABranchDF {
|
||||||
|
MSA_BRANCH_B = 0,
|
||||||
|
MSA_BRANCH_H,
|
||||||
|
MSA_BRANCH_W,
|
||||||
|
MSA_BRANCH_D,
|
||||||
|
MSA_BRANCH_V
|
||||||
|
};
|
||||||
|
|
||||||
// Commute a condition such that {a cond b == b cond' a}.
|
// Commute a condition such that {a cond b == b cond' a}.
|
||||||
inline Condition CommuteCondition(Condition cc) {
|
inline Condition CommuteCondition(Condition cc) {
|
||||||
@ -1840,6 +1870,16 @@ bool InstructionGetters<T>::IsForbiddenAfterBranchInstr(Instr instr) {
|
|||||||
case BC1:
|
case BC1:
|
||||||
case BC1EQZ:
|
case BC1EQZ:
|
||||||
case BC1NEZ:
|
case BC1NEZ:
|
||||||
|
case BZ_V:
|
||||||
|
case BZ_B:
|
||||||
|
case BZ_H:
|
||||||
|
case BZ_W:
|
||||||
|
case BZ_D:
|
||||||
|
case BNZ_V:
|
||||||
|
case BNZ_B:
|
||||||
|
case BNZ_H:
|
||||||
|
case BNZ_W:
|
||||||
|
case BNZ_D:
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2316,6 +2316,82 @@ void MacroAssembler::BranchShortF(SecondaryField sizeField, Label* target,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::BranchMSA(Label* target, MSABranchDF df,
|
||||||
|
MSABranchCondition cond, MSARegister wt,
|
||||||
|
BranchDelaySlot bd) {
|
||||||
|
{
|
||||||
|
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
bool long_branch =
|
||||||
|
target->is_bound() ? !is_near(target) : is_trampoline_emitted();
|
||||||
|
if (long_branch) {
|
||||||
|
Label skip;
|
||||||
|
MSABranchCondition neg_cond = NegateMSABranchCondition(cond);
|
||||||
|
BranchShortMSA(df, &skip, neg_cond, wt, bd);
|
||||||
|
BranchLong(target, bd);
|
||||||
|
bind(&skip);
|
||||||
|
} else {
|
||||||
|
BranchShortMSA(df, target, cond, wt, bd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::BranchShortMSA(MSABranchDF df, Label* target,
|
||||||
|
MSABranchCondition cond, MSARegister wt,
|
||||||
|
BranchDelaySlot bd) {
|
||||||
|
if (IsMipsArchVariant(kMips32r6)) {
|
||||||
|
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||||
|
if (target) {
|
||||||
|
switch (cond) {
|
||||||
|
case all_not_zero:
|
||||||
|
switch (df) {
|
||||||
|
case MSA_BRANCH_D:
|
||||||
|
bnz_d(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_W:
|
||||||
|
bnz_w(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_H:
|
||||||
|
bnz_h(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_B:
|
||||||
|
default:
|
||||||
|
bnz_b(wt, target);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case one_elem_not_zero:
|
||||||
|
bnz_v(wt, target);
|
||||||
|
break;
|
||||||
|
case one_elem_zero:
|
||||||
|
switch (df) {
|
||||||
|
case MSA_BRANCH_D:
|
||||||
|
bz_d(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_W:
|
||||||
|
bz_w(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_H:
|
||||||
|
bz_h(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_B:
|
||||||
|
default:
|
||||||
|
bz_b(wt, target);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case all_zero:
|
||||||
|
bz_v(wt, target);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bd == PROTECT) {
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MacroAssembler::FmoveLow(FPURegister dst, Register src_low) {
|
void MacroAssembler::FmoveLow(FPURegister dst, Register src_low) {
|
||||||
if (IsFp32Mode()) {
|
if (IsFp32Mode()) {
|
||||||
|
@ -913,6 +913,12 @@ class MacroAssembler: public Assembler {
|
|||||||
BranchF64(bd, target, nan, cc, cmp1, cmp2);
|
BranchF64(bd, target, nan, cc, cmp1, cmp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BranchMSA(Label* target, MSABranchDF df, MSABranchCondition cond,
|
||||||
|
MSARegister wt, BranchDelaySlot bd = PROTECT);
|
||||||
|
|
||||||
|
void BranchShortMSA(MSABranchDF df, Label* target, MSABranchCondition cond,
|
||||||
|
MSARegister wt, BranchDelaySlot bd = PROTECT);
|
||||||
|
|
||||||
// Truncates a double using a specific rounding mode, and writes the value
|
// Truncates a double using a specific rounding mode, and writes the value
|
||||||
// to the result register.
|
// to the result register.
|
||||||
// The except_flag will contain any exceptions caused by the instruction.
|
// The except_flag will contain any exceptions caused by the instruction.
|
||||||
|
@ -460,6 +460,29 @@ const int kEndOfChain = -4;
|
|||||||
// Determines the end of the Jump chain (a subset of the label link chain).
|
// Determines the end of the Jump chain (a subset of the label link chain).
|
||||||
const int kEndOfJumpChain = 0;
|
const int kEndOfJumpChain = 0;
|
||||||
|
|
||||||
|
bool Assembler::IsMsaBranch(Instr instr) {
|
||||||
|
uint32_t opcode = GetOpcodeField(instr);
|
||||||
|
uint32_t rs_field = GetRsField(instr);
|
||||||
|
if (opcode == COP1) {
|
||||||
|
switch (rs_field) {
|
||||||
|
case BZ_V:
|
||||||
|
case BZ_B:
|
||||||
|
case BZ_H:
|
||||||
|
case BZ_W:
|
||||||
|
case BZ_D:
|
||||||
|
case BNZ_V:
|
||||||
|
case BNZ_B:
|
||||||
|
case BNZ_H:
|
||||||
|
case BNZ_W:
|
||||||
|
case BNZ_D:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Assembler::IsBranch(Instr instr) {
|
bool Assembler::IsBranch(Instr instr) {
|
||||||
uint32_t opcode = GetOpcodeField(instr);
|
uint32_t opcode = GetOpcodeField(instr);
|
||||||
@ -473,7 +496,7 @@ bool Assembler::IsBranch(Instr instr) {
|
|||||||
rt_field == BLTZAL || rt_field == BGEZAL)) ||
|
rt_field == BLTZAL || rt_field == BGEZAL)) ||
|
||||||
(opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
|
(opcode == COP1 && rs_field == BC1) || // Coprocessor branch.
|
||||||
(opcode == COP1 && rs_field == BC1EQZ) ||
|
(opcode == COP1 && rs_field == BC1EQZ) ||
|
||||||
(opcode == COP1 && rs_field == BC1NEZ);
|
(opcode == COP1 && rs_field == BC1NEZ) || IsMsaBranch(instr);
|
||||||
if (!isBranch && kArchVariant == kMips64r6) {
|
if (!isBranch && kArchVariant == kMips64r6) {
|
||||||
// All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
|
// All the 3 variants of POP10 (BOVC, BEQC, BEQZALC) and
|
||||||
// POP30 (BNVC, BNEC, BNEZALC) are branch ops.
|
// POP30 (BNVC, BNEC, BNEZALC) are branch ops.
|
||||||
|
@ -1159,15 +1159,45 @@ class Assembler : public AssemblerBase {
|
|||||||
|
|
||||||
// MSA instructions
|
// MSA instructions
|
||||||
void bz_v(MSARegister wt, int16_t offset);
|
void bz_v(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_v(MSARegister wt, Label* L) {
|
||||||
|
bz_v(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_b(MSARegister wt, int16_t offset);
|
void bz_b(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_b(MSARegister wt, Label* L) {
|
||||||
|
bz_b(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_h(MSARegister wt, int16_t offset);
|
void bz_h(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_h(MSARegister wt, Label* L) {
|
||||||
|
bz_h(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_w(MSARegister wt, int16_t offset);
|
void bz_w(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_w(MSARegister wt, Label* L) {
|
||||||
|
bz_w(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bz_d(MSARegister wt, int16_t offset);
|
void bz_d(MSARegister wt, int16_t offset);
|
||||||
|
inline void bz_d(MSARegister wt, Label* L) {
|
||||||
|
bz_d(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_v(MSARegister wt, int16_t offset);
|
void bnz_v(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_v(MSARegister wt, Label* L) {
|
||||||
|
bnz_v(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_b(MSARegister wt, int16_t offset);
|
void bnz_b(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_b(MSARegister wt, Label* L) {
|
||||||
|
bnz_b(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_h(MSARegister wt, int16_t offset);
|
void bnz_h(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_h(MSARegister wt, Label* L) {
|
||||||
|
bnz_h(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_w(MSARegister wt, int16_t offset);
|
void bnz_w(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_w(MSARegister wt, Label* L) {
|
||||||
|
bnz_w(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
void bnz_d(MSARegister wt, int16_t offset);
|
void bnz_d(MSARegister wt, int16_t offset);
|
||||||
|
inline void bnz_d(MSARegister wt, Label* L) {
|
||||||
|
bnz_d(wt, shifted_branch_offset(L));
|
||||||
|
}
|
||||||
|
|
||||||
void ld_b(MSARegister wd, const MemOperand& rs);
|
void ld_b(MSARegister wd, const MemOperand& rs);
|
||||||
void ld_h(MSARegister wd, const MemOperand& rs);
|
void ld_h(MSARegister wd, const MemOperand& rs);
|
||||||
@ -1827,6 +1857,7 @@ class Assembler : public AssemblerBase {
|
|||||||
|
|
||||||
// Check if an instruction is a branch of some kind.
|
// Check if an instruction is a branch of some kind.
|
||||||
static bool IsBranch(Instr instr);
|
static bool IsBranch(Instr instr);
|
||||||
|
static bool IsMsaBranch(Instr instr);
|
||||||
static bool IsBc(Instr instr);
|
static bool IsBc(Instr instr);
|
||||||
static bool IsBzc(Instr instr);
|
static bool IsBzc(Instr instr);
|
||||||
|
|
||||||
|
@ -1092,6 +1092,36 @@ inline Condition NegateFpuCondition(Condition cc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum MSABranchCondition {
|
||||||
|
all_not_zero = 0, // Branch If All Elements Are Not Zero
|
||||||
|
one_elem_not_zero, // Branch If At Least One Element of Any Format Is Not
|
||||||
|
// Zero
|
||||||
|
one_elem_zero, // Branch If At Least One Element Is Zero
|
||||||
|
all_zero // Branch If All Elements of Any Format Are Zero
|
||||||
|
};
|
||||||
|
|
||||||
|
inline MSABranchCondition NegateMSABranchCondition(MSABranchCondition cond) {
|
||||||
|
switch (cond) {
|
||||||
|
case all_not_zero:
|
||||||
|
return one_elem_zero;
|
||||||
|
case one_elem_not_zero:
|
||||||
|
return all_zero;
|
||||||
|
case one_elem_zero:
|
||||||
|
return all_not_zero;
|
||||||
|
case all_zero:
|
||||||
|
return one_elem_not_zero;
|
||||||
|
default:
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MSABranchDF {
|
||||||
|
MSA_BRANCH_B = 0,
|
||||||
|
MSA_BRANCH_H,
|
||||||
|
MSA_BRANCH_W,
|
||||||
|
MSA_BRANCH_D,
|
||||||
|
MSA_BRANCH_V
|
||||||
|
};
|
||||||
|
|
||||||
// Commute a condition such that {a cond b == b cond' a}.
|
// Commute a condition such that {a cond b == b cond' a}.
|
||||||
inline Condition CommuteCondition(Condition cc) {
|
inline Condition CommuteCondition(Condition cc) {
|
||||||
@ -1918,6 +1948,16 @@ bool InstructionGetters<T>::IsForbiddenAfterBranchInstr(Instr instr) {
|
|||||||
case BC1:
|
case BC1:
|
||||||
case BC1EQZ:
|
case BC1EQZ:
|
||||||
case BC1NEZ:
|
case BC1NEZ:
|
||||||
|
case BZ_V:
|
||||||
|
case BZ_B:
|
||||||
|
case BZ_H:
|
||||||
|
case BZ_W:
|
||||||
|
case BZ_D:
|
||||||
|
case BNZ_V:
|
||||||
|
case BNZ_B:
|
||||||
|
case BNZ_H:
|
||||||
|
case BNZ_W:
|
||||||
|
case BNZ_D:
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -2735,6 +2735,82 @@ void MacroAssembler::BranchShortF(SecondaryField sizeField, Label* target,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::BranchMSA(Label* target, MSABranchDF df,
|
||||||
|
MSABranchCondition cond, MSARegister wt,
|
||||||
|
BranchDelaySlot bd) {
|
||||||
|
{
|
||||||
|
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
bool long_branch =
|
||||||
|
target->is_bound() ? !is_near(target) : is_trampoline_emitted();
|
||||||
|
if (long_branch) {
|
||||||
|
Label skip;
|
||||||
|
MSABranchCondition neg_cond = NegateMSABranchCondition(cond);
|
||||||
|
BranchShortMSA(df, &skip, neg_cond, wt, bd);
|
||||||
|
BranchLong(target, bd);
|
||||||
|
bind(&skip);
|
||||||
|
} else {
|
||||||
|
BranchShortMSA(df, target, cond, wt, bd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::BranchShortMSA(MSABranchDF df, Label* target,
|
||||||
|
MSABranchCondition cond, MSARegister wt,
|
||||||
|
BranchDelaySlot bd) {
|
||||||
|
if (kArchVariant == kMips64r6) {
|
||||||
|
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||||
|
if (target) {
|
||||||
|
switch (cond) {
|
||||||
|
case all_not_zero:
|
||||||
|
switch (df) {
|
||||||
|
case MSA_BRANCH_D:
|
||||||
|
bnz_d(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_W:
|
||||||
|
bnz_w(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_H:
|
||||||
|
bnz_h(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_B:
|
||||||
|
default:
|
||||||
|
bnz_b(wt, target);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case one_elem_not_zero:
|
||||||
|
bnz_v(wt, target);
|
||||||
|
break;
|
||||||
|
case one_elem_zero:
|
||||||
|
switch (df) {
|
||||||
|
case MSA_BRANCH_D:
|
||||||
|
bz_d(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_W:
|
||||||
|
bz_w(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_H:
|
||||||
|
bz_h(wt, target);
|
||||||
|
break;
|
||||||
|
case MSA_BRANCH_B:
|
||||||
|
default:
|
||||||
|
bz_b(wt, target);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case all_zero:
|
||||||
|
bz_v(wt, target);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bd == PROTECT) {
|
||||||
|
nop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MacroAssembler::FmoveLow(FPURegister dst, Register src_low) {
|
void MacroAssembler::FmoveLow(FPURegister dst, Register src_low) {
|
||||||
DCHECK(!src_low.is(at));
|
DCHECK(!src_low.is(at));
|
||||||
|
@ -977,6 +977,12 @@ class MacroAssembler: public Assembler {
|
|||||||
BranchF64(bd, target, nan, cc, cmp1, cmp2);
|
BranchF64(bd, target, nan, cc, cmp1, cmp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BranchMSA(Label* target, MSABranchDF df, MSABranchCondition cond,
|
||||||
|
MSARegister wt, BranchDelaySlot bd = PROTECT);
|
||||||
|
|
||||||
|
void BranchShortMSA(MSABranchDF df, Label* target, MSABranchCondition cond,
|
||||||
|
MSARegister wt, BranchDelaySlot bd = PROTECT);
|
||||||
|
|
||||||
// Truncates a double using a specific rounding mode, and writes the value
|
// Truncates a double using a specific rounding mode, and writes the value
|
||||||
// to the result register.
|
// to the result register.
|
||||||
// The except_flag will contain any exceptions caused by the instruction.
|
// The except_flag will contain any exceptions caused by the instruction.
|
||||||
|
@ -1131,14 +1131,16 @@ TEST(MSA_BRANCH) {
|
|||||||
32767);
|
32767);
|
||||||
COMPARE_MSA_BRANCH(bnz_d(w3, -32768), "47e38000 bnz.d w3, -32768",
|
COMPARE_MSA_BRANCH(bnz_d(w3, -32768), "47e38000 bnz.d w3, -32768",
|
||||||
-32768);
|
-32768);
|
||||||
COMPARE_MSA_BRANCH(bnz_v(w0, 0), "45e00000 bnz.v w0, 0", 0);
|
COMPARE_MSA_BRANCH(bnz_v(w0, static_cast<int16_t>(0)),
|
||||||
|
"45e00000 bnz.v w0, 0", 0);
|
||||||
COMPARE_MSA_BRANCH(bz_b(w0, 1), "47000001 bz.b w0, 1", 1);
|
COMPARE_MSA_BRANCH(bz_b(w0, 1), "47000001 bz.b w0, 1", 1);
|
||||||
COMPARE_MSA_BRANCH(bz_h(w1, -1), "4721ffff bz.h w1, -1", -1);
|
COMPARE_MSA_BRANCH(bz_h(w1, -1), "4721ffff bz.h w1, -1", -1);
|
||||||
COMPARE_MSA_BRANCH(bz_w(w2, 32767), "47427fff bz.w w2, 32767",
|
COMPARE_MSA_BRANCH(bz_w(w2, 32767), "47427fff bz.w w2, 32767",
|
||||||
32767);
|
32767);
|
||||||
COMPARE_MSA_BRANCH(bz_d(w3, -32768), "47638000 bz.d w3, -32768",
|
COMPARE_MSA_BRANCH(bz_d(w3, -32768), "47638000 bz.d w3, -32768",
|
||||||
-32768);
|
-32768);
|
||||||
COMPARE_MSA_BRANCH(bz_v(w0, 0), "45600000 bz.v w0, 0", 0);
|
COMPARE_MSA_BRANCH(bz_v(w0, static_cast<int16_t>(0)),
|
||||||
|
"45600000 bz.v w0, 0", 0);
|
||||||
}
|
}
|
||||||
VERIFY_RUN();
|
VERIFY_RUN();
|
||||||
}
|
}
|
||||||
|
@ -1332,14 +1332,16 @@ TEST(MSA_BRANCH) {
|
|||||||
32767);
|
32767);
|
||||||
COMPARE_MSA_BRANCH(bnz_d(w3, -32768), "47e38000 bnz.d w3, -32768",
|
COMPARE_MSA_BRANCH(bnz_d(w3, -32768), "47e38000 bnz.d w3, -32768",
|
||||||
-32768);
|
-32768);
|
||||||
COMPARE_MSA_BRANCH(bnz_v(w0, 0), "45e00000 bnz.v w0, 0", 0);
|
COMPARE_MSA_BRANCH(bnz_v(w0, static_cast<int16_t>(0)),
|
||||||
|
"45e00000 bnz.v w0, 0", 0);
|
||||||
COMPARE_MSA_BRANCH(bz_b(w0, 1), "47000001 bz.b w0, 1", 1);
|
COMPARE_MSA_BRANCH(bz_b(w0, 1), "47000001 bz.b w0, 1", 1);
|
||||||
COMPARE_MSA_BRANCH(bz_h(w1, -1), "4721ffff bz.h w1, -1", -1);
|
COMPARE_MSA_BRANCH(bz_h(w1, -1), "4721ffff bz.h w1, -1", -1);
|
||||||
COMPARE_MSA_BRANCH(bz_w(w2, 32767), "47427fff bz.w w2, 32767",
|
COMPARE_MSA_BRANCH(bz_w(w2, 32767), "47427fff bz.w w2, 32767",
|
||||||
32767);
|
32767);
|
||||||
COMPARE_MSA_BRANCH(bz_d(w3, -32768), "47638000 bz.d w3, -32768",
|
COMPARE_MSA_BRANCH(bz_d(w3, -32768), "47638000 bz.d w3, -32768",
|
||||||
-32768);
|
-32768);
|
||||||
COMPARE_MSA_BRANCH(bz_v(w0, 0), "45600000 bz.v w0, 0", 0);
|
COMPARE_MSA_BRANCH(bz_v(w0, static_cast<int16_t>(0)),
|
||||||
|
"45600000 bz.v w0, 0", 0);
|
||||||
}
|
}
|
||||||
VERIFY_RUN();
|
VERIFY_RUN();
|
||||||
}
|
}
|
||||||
|
@ -1800,7 +1800,9 @@ WASM_SIMD_TEST(S32x4Concat) { RunConcatOpTest<int32_t>(kExprS32x4Shuffle); }
|
|||||||
WASM_SIMD_TEST(S16x8Concat) { RunConcatOpTest<int16_t>(kExprS16x8Shuffle); }
|
WASM_SIMD_TEST(S16x8Concat) { RunConcatOpTest<int16_t>(kExprS16x8Shuffle); }
|
||||||
|
|
||||||
WASM_SIMD_TEST(S8x16Concat) { RunConcatOpTest<int8_t>(kExprS8x16Shuffle); }
|
WASM_SIMD_TEST(S8x16Concat) { RunConcatOpTest<int8_t>(kExprS8x16Shuffle); }
|
||||||
|
#endif // V8_TARGET_ARCH_ARM
|
||||||
|
|
||||||
|
#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
// Boolean unary operations are 'AllTrue' and 'AnyTrue', which return an integer
|
// Boolean unary operations are 'AllTrue' and 'AnyTrue', which return an integer
|
||||||
// result. Use relational ops on numeric vectors to create the boolean vector
|
// result. Use relational ops on numeric vectors to create the boolean vector
|
||||||
// test inputs. Test inputs with all true, all false, one true, and one false.
|
// test inputs. Test inputs with all true, all false, one true, and one false.
|
||||||
@ -1970,9 +1972,10 @@ WASM_SIMD_TEST(S1x16And) { RunS1x16BinOpTest(kExprS1x16And, And); }
|
|||||||
WASM_SIMD_TEST(S1x16Or) { RunS1x16BinOpTest(kExprS1x16Or, Or); }
|
WASM_SIMD_TEST(S1x16Or) { RunS1x16BinOpTest(kExprS1x16Or, Or); }
|
||||||
|
|
||||||
WASM_SIMD_TEST(S1x16Xor) { RunS1x16BinOpTest(kExprS1x16Xor, Xor); }
|
WASM_SIMD_TEST(S1x16Xor) { RunS1x16BinOpTest(kExprS1x16Xor, Xor); }
|
||||||
#endif // !V8_TARGET_ARCH_ARM
|
#endif // !V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET
|
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_MIPS || \
|
||||||
|
V8_TARGET_ARCH_MIPS64
|
||||||
WASM_SIMD_TEST(SimdI32x4ExtractWithF32x4) {
|
WASM_SIMD_TEST(SimdI32x4ExtractWithF32x4) {
|
||||||
WasmRunner<int32_t> r(kExecuteCompiled);
|
WasmRunner<int32_t> r(kExecuteCompiled);
|
||||||
BUILD(r, WASM_IF_ELSE_I(
|
BUILD(r, WASM_IF_ELSE_I(
|
||||||
@ -2026,9 +2029,11 @@ WASM_SIMD_TEST(SimdI32x4AddWithF32x4) {
|
|||||||
WASM_I32V(1), WASM_I32V(0)));
|
WASM_I32V(1), WASM_I32V(0)));
|
||||||
CHECK_EQ(1, r.Call());
|
CHECK_EQ(1, r.Call());
|
||||||
}
|
}
|
||||||
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET
|
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_MIPS ||
|
||||||
|
// V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64
|
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64 || \
|
||||||
|
V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
WASM_SIMD_TEST(SimdI32x4Local) {
|
WASM_SIMD_TEST(SimdI32x4Local) {
|
||||||
WasmRunner<int32_t> r(kExecuteCompiled);
|
WasmRunner<int32_t> r(kExecuteCompiled);
|
||||||
r.AllocateLocal(kWasmS128);
|
r.AllocateLocal(kWasmS128);
|
||||||
@ -2082,9 +2087,11 @@ WASM_SIMD_TEST(SimdI32x4For) {
|
|||||||
WASM_GET_LOCAL(0));
|
WASM_GET_LOCAL(0));
|
||||||
CHECK_EQ(1, r.Call());
|
CHECK_EQ(1, r.Call());
|
||||||
}
|
}
|
||||||
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64
|
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64 ||
|
||||||
|
// V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET
|
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_MIPS || \
|
||||||
|
V8_TARGET_ARCH_MIPS64
|
||||||
WASM_SIMD_TEST(SimdF32x4For) {
|
WASM_SIMD_TEST(SimdF32x4For) {
|
||||||
WasmRunner<int32_t> r(kExecuteCompiled);
|
WasmRunner<int32_t> r(kExecuteCompiled);
|
||||||
r.AllocateLocal(kWasmI32);
|
r.AllocateLocal(kWasmI32);
|
||||||
@ -2108,9 +2115,11 @@ WASM_SIMD_TEST(SimdF32x4For) {
|
|||||||
WASM_GET_LOCAL(0));
|
WASM_GET_LOCAL(0));
|
||||||
CHECK_EQ(1, r.Call());
|
CHECK_EQ(1, r.Call());
|
||||||
}
|
}
|
||||||
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET
|
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_MIPS ||
|
||||||
|
// V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64
|
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64 || \
|
||||||
|
V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
template <typename T, int numLanes = 4>
|
template <typename T, int numLanes = 4>
|
||||||
void SetVectorByLanes(T* v, const std::array<T, numLanes>& arr) {
|
void SetVectorByLanes(T* v, const std::array<T, numLanes>& arr) {
|
||||||
@ -2177,9 +2186,11 @@ WASM_SIMD_TEST(SimdI32x4SetGlobal) {
|
|||||||
CHECK_EQ(GetScalar(global, 2), 45);
|
CHECK_EQ(GetScalar(global, 2), 45);
|
||||||
CHECK_EQ(GetScalar(global, 3), 56);
|
CHECK_EQ(GetScalar(global, 3), 56);
|
||||||
}
|
}
|
||||||
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64
|
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64 ||
|
||||||
|
// V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET
|
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_MIPS || \
|
||||||
|
V8_TARGET_ARCH_MIPS64
|
||||||
WASM_SIMD_TEST(SimdF32x4GetGlobal) {
|
WASM_SIMD_TEST(SimdF32x4GetGlobal) {
|
||||||
WasmRunner<int32_t, int32_t> r(kExecuteCompiled);
|
WasmRunner<int32_t, int32_t> r(kExecuteCompiled);
|
||||||
float* global = r.module().AddGlobal<float>(kWasmS128);
|
float* global = r.module().AddGlobal<float>(kWasmS128);
|
||||||
@ -2220,9 +2231,11 @@ WASM_SIMD_TEST(SimdF32x4SetGlobal) {
|
|||||||
CHECK_EQ(GetScalar(global, 2), 32.25f);
|
CHECK_EQ(GetScalar(global, 2), 32.25f);
|
||||||
CHECK_EQ(GetScalar(global, 3), 65.0f);
|
CHECK_EQ(GetScalar(global, 3), 65.0f);
|
||||||
}
|
}
|
||||||
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET
|
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_MIPS ||
|
||||||
|
// V8_TARGET_ARCH_MIPS64
|
||||||
|
|
||||||
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64
|
#if V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64 || \
|
||||||
|
V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
WASM_SIMD_TEST(SimdLoadStoreLoad) {
|
WASM_SIMD_TEST(SimdLoadStoreLoad) {
|
||||||
WasmRunner<int32_t> r(kExecuteCompiled);
|
WasmRunner<int32_t> r(kExecuteCompiled);
|
||||||
int32_t* memory = r.module().AddMemoryElems<int32_t>(4);
|
int32_t* memory = r.module().AddMemoryElems<int32_t>(4);
|
||||||
@ -2239,4 +2252,5 @@ WASM_SIMD_TEST(SimdLoadStoreLoad) {
|
|||||||
CHECK_EQ(expected, r.Call());
|
CHECK_EQ(expected, r.Call());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64
|
#endif // V8_TARGET_ARCH_ARM || SIMD_LOWERING_TARGET || V8_TARGET_ARCH_X64 ||
|
||||||
|
// V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
|
||||||
|
Loading…
Reference in New Issue
Block a user