MIPS[64]: Implement Round, Ceil, Floor and Trunc in LiftOff
Change-Id: I13c58a462ec844b6df0e55bbbbf9134a476363c4 Reviewed-on: https://chromium-review.googlesource.com/1009908 Reviewed-by: Sreten Kovacevic <sreten.kovacevic@mips.com> Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com> Cr-Commit-Position: refs/heads/master@{#52575}
This commit is contained in:
parent
5874911bc7
commit
e184dcae96
@ -143,41 +143,6 @@ static inline bool HasRegisterInput(Instruction* instr, size_t index) {
|
||||
|
||||
namespace {
|
||||
|
||||
class OutOfLineRound : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRound(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineCode(gen), result_(result) {}
|
||||
|
||||
void Generate() final {
|
||||
// Handle rounding to zero case where sign has to be preserved.
|
||||
// High bits of double input already in kScratchReg.
|
||||
__ srl(at, kScratchReg, 31);
|
||||
__ sll(at, at, 31);
|
||||
__ Mthc1(at, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
DoubleRegister const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineRound32 : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRound32(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineCode(gen), result_(result) {}
|
||||
|
||||
void Generate() final {
|
||||
// Handle rounding to zero case where sign has to be preserved.
|
||||
// High bits of float input already in kScratchReg.
|
||||
__ srl(at, kScratchReg, 31);
|
||||
__ sll(at, at, 31);
|
||||
__ mtc1(at, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
DoubleRegister const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
public:
|
||||
@ -367,57 +332,6 @@ void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
|
||||
|
||||
} // namespace
|
||||
|
||||
#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(mode) \
|
||||
if (IsMipsArchVariant(kMips32r6)) { \
|
||||
__ cfc1(kScratchReg, FCSR); \
|
||||
__ li(at, Operand(mode_##mode)); \
|
||||
__ ctc1(at, FCSR); \
|
||||
__ rint_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ ctc1(kScratchReg, FCSR); \
|
||||
} else { \
|
||||
auto ool = new (zone()) OutOfLineRound(this, i.OutputDoubleRegister()); \
|
||||
Label done; \
|
||||
__ Mfhc1(kScratchReg, i.InputDoubleRegister(0)); \
|
||||
__ Ext(at, kScratchReg, HeapNumber::kExponentShift, \
|
||||
HeapNumber::kExponentBits); \
|
||||
__ Branch(USE_DELAY_SLOT, &done, hs, at, \
|
||||
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \
|
||||
__ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ mode##_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ Move(at, kScratchReg2, i.OutputDoubleRegister()); \
|
||||
__ or_(at, at, kScratchReg2); \
|
||||
__ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \
|
||||
__ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
|
||||
__ bind(ool->exit()); \
|
||||
__ bind(&done); \
|
||||
}
|
||||
|
||||
|
||||
#define ASSEMBLE_ROUND_FLOAT_TO_FLOAT(mode) \
|
||||
if (IsMipsArchVariant(kMips32r6)) { \
|
||||
__ cfc1(kScratchReg, FCSR); \
|
||||
__ li(at, Operand(mode_##mode)); \
|
||||
__ ctc1(at, FCSR); \
|
||||
__ rint_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ ctc1(kScratchReg, FCSR); \
|
||||
} else { \
|
||||
int32_t kFloat32ExponentBias = 127; \
|
||||
int32_t kFloat32MantissaBits = 23; \
|
||||
int32_t kFloat32ExponentBits = 8; \
|
||||
auto ool = new (zone()) OutOfLineRound32(this, i.OutputDoubleRegister()); \
|
||||
Label done; \
|
||||
__ mfc1(kScratchReg, i.InputDoubleRegister(0)); \
|
||||
__ Ext(at, kScratchReg, kFloat32MantissaBits, kFloat32ExponentBits); \
|
||||
__ Branch(USE_DELAY_SLOT, &done, hs, at, \
|
||||
Operand(kFloat32ExponentBias + kFloat32MantissaBits)); \
|
||||
__ mov_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ mode##_w_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ mfc1(at, i.OutputDoubleRegister()); \
|
||||
__ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \
|
||||
__ cvt_s_w(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
|
||||
__ bind(ool->exit()); \
|
||||
__ bind(&done); \
|
||||
}
|
||||
|
||||
#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \
|
||||
do { \
|
||||
@ -1351,35 +1265,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
i.InputDoubleRegister(1));
|
||||
break;
|
||||
case kMipsFloat64RoundDown: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor);
|
||||
__ Floor_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat32RoundDown: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(floor);
|
||||
__ Floor_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat64RoundTruncate: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc);
|
||||
__ Trunc_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat32RoundTruncate: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(trunc);
|
||||
__ Trunc_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat64RoundUp: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil);
|
||||
__ Ceil_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat32RoundUp: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(ceil);
|
||||
__ Ceil_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat64RoundTiesEven: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(round);
|
||||
__ Round_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat32RoundTiesEven: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(round);
|
||||
__ Round_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMipsFloat32Max: {
|
||||
|
@ -143,41 +143,6 @@ static inline bool HasRegisterInput(Instruction* instr, size_t index) {
|
||||
|
||||
namespace {
|
||||
|
||||
class OutOfLineRound : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRound(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineCode(gen), result_(result) {}
|
||||
|
||||
void Generate() final {
|
||||
// Handle rounding to zero case where sign has to be preserved.
|
||||
// High bits of double input already in kScratchReg.
|
||||
__ dsrl(at, kScratchReg, 31);
|
||||
__ dsll(at, at, 31);
|
||||
__ mthc1(at, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
DoubleRegister const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineRound32 : public OutOfLineCode {
|
||||
public:
|
||||
OutOfLineRound32(CodeGenerator* gen, DoubleRegister result)
|
||||
: OutOfLineCode(gen), result_(result) {}
|
||||
|
||||
void Generate() final {
|
||||
// Handle rounding to zero case where sign has to be preserved.
|
||||
// High bits of float input already in kScratchReg.
|
||||
__ srl(at, kScratchReg, 31);
|
||||
__ sll(at, at, 31);
|
||||
__ mtc1(at, result_);
|
||||
}
|
||||
|
||||
private:
|
||||
DoubleRegister const result_;
|
||||
};
|
||||
|
||||
|
||||
class OutOfLineRecordWrite final : public OutOfLineCode {
|
||||
public:
|
||||
@ -375,56 +340,6 @@ void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen,
|
||||
|
||||
} // namespace
|
||||
|
||||
#define ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(mode) \
|
||||
if (kArchVariant == kMips64r6) { \
|
||||
__ cfc1(kScratchReg, FCSR); \
|
||||
__ li(at, Operand(mode_##mode)); \
|
||||
__ ctc1(at, FCSR); \
|
||||
__ rint_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ ctc1(kScratchReg, FCSR); \
|
||||
} else { \
|
||||
auto ool = new (zone()) OutOfLineRound(this, i.OutputDoubleRegister()); \
|
||||
Label done; \
|
||||
__ mfhc1(kScratchReg, i.InputDoubleRegister(0)); \
|
||||
__ Ext(at, kScratchReg, HeapNumber::kExponentShift, \
|
||||
HeapNumber::kExponentBits); \
|
||||
__ Branch(USE_DELAY_SLOT, &done, hs, at, \
|
||||
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits)); \
|
||||
__ mov_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ mode##_l_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ dmfc1(at, i.OutputDoubleRegister()); \
|
||||
__ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \
|
||||
__ cvt_d_l(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
|
||||
__ bind(ool->exit()); \
|
||||
__ bind(&done); \
|
||||
}
|
||||
|
||||
#define ASSEMBLE_ROUND_FLOAT_TO_FLOAT(mode) \
|
||||
if (kArchVariant == kMips64r6) { \
|
||||
__ cfc1(kScratchReg, FCSR); \
|
||||
__ li(at, Operand(mode_##mode)); \
|
||||
__ ctc1(at, FCSR); \
|
||||
__ rint_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ ctc1(kScratchReg, FCSR); \
|
||||
} else { \
|
||||
int32_t kFloat32ExponentBias = 127; \
|
||||
int32_t kFloat32MantissaBits = 23; \
|
||||
int32_t kFloat32ExponentBits = 8; \
|
||||
auto ool = new (zone()) OutOfLineRound32(this, i.OutputDoubleRegister()); \
|
||||
Label done; \
|
||||
__ mfc1(kScratchReg, i.InputDoubleRegister(0)); \
|
||||
__ Ext(at, kScratchReg, kFloat32MantissaBits, kFloat32ExponentBits); \
|
||||
__ Branch(USE_DELAY_SLOT, &done, hs, at, \
|
||||
Operand(kFloat32ExponentBias + kFloat32MantissaBits)); \
|
||||
__ mov_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ mode##_w_s(i.OutputDoubleRegister(), i.InputDoubleRegister(0)); \
|
||||
__ mfc1(at, i.OutputDoubleRegister()); \
|
||||
__ Branch(USE_DELAY_SLOT, ool->entry(), eq, at, Operand(zero_reg)); \
|
||||
__ cvt_s_w(i.OutputDoubleRegister(), i.OutputDoubleRegister()); \
|
||||
__ bind(ool->exit()); \
|
||||
__ bind(&done); \
|
||||
}
|
||||
|
||||
#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \
|
||||
do { \
|
||||
__ asm_instr(i.OutputRegister(), i.MemoryOperand()); \
|
||||
@ -1458,35 +1373,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
i.InputDoubleRegister(1));
|
||||
break;
|
||||
case kMips64Float64RoundDown: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(floor);
|
||||
__ Floor_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float32RoundDown: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(floor);
|
||||
__ Floor_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float64RoundTruncate: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(trunc);
|
||||
__ Trunc_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float32RoundTruncate: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(trunc);
|
||||
__ Trunc_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float64RoundUp: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(ceil);
|
||||
__ Ceil_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float32RoundUp: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(ceil);
|
||||
__ Ceil_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float64RoundTiesEven: {
|
||||
ASSEMBLE_ROUND_DOUBLE_TO_DOUBLE(round);
|
||||
__ Round_d_d(i.OutputDoubleRegister(), i.InputDoubleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float32RoundTiesEven: {
|
||||
ASSEMBLE_ROUND_FLOAT_TO_FLOAT(round);
|
||||
__ Round_s_s(i.OutputSingleRegister(), i.InputSingleRegister(0));
|
||||
break;
|
||||
}
|
||||
case kMips64Float32Max: {
|
||||
|
@ -1905,6 +1905,125 @@ void TurboAssembler::Trunc_uw_s(FPURegister fd, Register rs,
|
||||
bind(&done);
|
||||
}
|
||||
|
||||
template <typename RoundFunc>
|
||||
void TurboAssembler::RoundDouble(FPURegister dst, FPURegister src,
|
||||
FPURoundingMode mode, RoundFunc round) {
|
||||
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||
Register scratch = t8;
|
||||
Register scratch2 = t9;
|
||||
if (IsMipsArchVariant(kMips32r6)) {
|
||||
cfc1(scratch, FCSR);
|
||||
li(at, Operand(mode));
|
||||
ctc1(at, FCSR);
|
||||
rint_d(dst, src);
|
||||
ctc1(scratch, FCSR);
|
||||
} else {
|
||||
Label done;
|
||||
Mfhc1(scratch, src);
|
||||
Ext(at, scratch, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
|
||||
Branch(USE_DELAY_SLOT, &done, hs, at,
|
||||
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits));
|
||||
mov_d(dst, src);
|
||||
round(this, dst, src);
|
||||
Move(at, scratch2, dst);
|
||||
or_(at, at, scratch2);
|
||||
Branch(USE_DELAY_SLOT, &done, ne, at, Operand(zero_reg));
|
||||
cvt_d_l(dst, dst);
|
||||
srl(at, scratch, 31);
|
||||
sll(at, at, 31);
|
||||
Mthc1(at, dst);
|
||||
bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
void TurboAssembler::Floor_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_floor,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->floor_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Ceil_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_ceil,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->ceil_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Trunc_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_trunc,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->trunc_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Round_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_round,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->round_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename RoundFunc>
|
||||
void TurboAssembler::RoundFloat(FPURegister dst, FPURegister src,
|
||||
FPURoundingMode mode, RoundFunc round) {
|
||||
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||
Register scratch = t8;
|
||||
if (IsMipsArchVariant(kMips32r6)) {
|
||||
cfc1(scratch, FCSR);
|
||||
li(at, Operand(mode));
|
||||
ctc1(at, FCSR);
|
||||
rint_s(dst, src);
|
||||
ctc1(scratch, FCSR);
|
||||
} else {
|
||||
int32_t kFloat32ExponentBias = 127;
|
||||
int32_t kFloat32MantissaBits = 23;
|
||||
int32_t kFloat32ExponentBits = 8;
|
||||
Label done;
|
||||
mfc1(scratch, src);
|
||||
Ext(at, scratch, kFloat32MantissaBits, kFloat32ExponentBits);
|
||||
Branch(USE_DELAY_SLOT, &done, hs, at,
|
||||
Operand(kFloat32ExponentBias + kFloat32MantissaBits));
|
||||
mov_s(dst, src);
|
||||
round(this, dst, src);
|
||||
mfc1(at, dst);
|
||||
Branch(USE_DELAY_SLOT, &done, ne, at, Operand(zero_reg));
|
||||
cvt_s_w(dst, dst);
|
||||
srl(at, scratch, 31);
|
||||
sll(at, at, 31);
|
||||
mtc1(at, dst);
|
||||
bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
void TurboAssembler::Floor_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_floor,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->floor_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Ceil_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_ceil,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->ceil_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Trunc_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_trunc,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->trunc_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Round_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_round,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->round_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Mthc1(Register rt, FPURegister fs) {
|
||||
if (IsFp32Mode()) {
|
||||
mtc1(rt, fs.high());
|
||||
|
@ -626,6 +626,18 @@ class TurboAssembler : public Assembler {
|
||||
void Floor_w_d(FPURegister fd, FPURegister fs);
|
||||
void Ceil_w_d(FPURegister fd, FPURegister fs);
|
||||
|
||||
// Round double functions
|
||||
void Trunc_d_d(FPURegister fd, FPURegister fs);
|
||||
void Round_d_d(FPURegister fd, FPURegister fs);
|
||||
void Floor_d_d(FPURegister fd, FPURegister fs);
|
||||
void Ceil_d_d(FPURegister fd, FPURegister fs);
|
||||
|
||||
// Round float functions
|
||||
void Trunc_s_s(FPURegister fd, FPURegister fs);
|
||||
void Round_s_s(FPURegister fd, FPURegister fs);
|
||||
void Floor_s_s(FPURegister fd, FPURegister fs);
|
||||
void Ceil_s_s(FPURegister fd, FPURegister fs);
|
||||
|
||||
// FP32 mode: Move the general purpose register into
|
||||
// the high part of the double-register pair.
|
||||
// FP64 mode: Move the general-purpose register into
|
||||
@ -867,6 +879,14 @@ class TurboAssembler : public Assembler {
|
||||
BranchDelaySlot bdslot);
|
||||
void BranchAndLinkLong(Label* L, BranchDelaySlot bdslot);
|
||||
|
||||
template <typename RoundFunc>
|
||||
void RoundDouble(FPURegister dst, FPURegister src, FPURoundingMode mode,
|
||||
RoundFunc round);
|
||||
|
||||
template <typename RoundFunc>
|
||||
void RoundFloat(FPURegister dst, FPURegister src, FPURoundingMode mode,
|
||||
RoundFunc round);
|
||||
|
||||
// Push a fixed frame, consisting of ra, fp.
|
||||
void PushCommonFrame(Register marker_reg = no_reg);
|
||||
};
|
||||
|
@ -2474,6 +2474,123 @@ void TurboAssembler::Trunc_ul_s(FPURegister fd, Register rs,
|
||||
bind(&fail);
|
||||
}
|
||||
|
||||
template <typename RoundFunc>
|
||||
void TurboAssembler::RoundDouble(FPURegister dst, FPURegister src,
|
||||
FPURoundingMode mode, RoundFunc round) {
|
||||
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||
Register scratch = t8;
|
||||
if (kArchVariant == kMips64r6) {
|
||||
cfc1(scratch, FCSR);
|
||||
li(at, Operand(mode));
|
||||
ctc1(at, FCSR);
|
||||
rint_d(dst, src);
|
||||
ctc1(scratch, FCSR);
|
||||
} else {
|
||||
Label done;
|
||||
mfhc1(scratch, src);
|
||||
Ext(at, scratch, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
|
||||
Branch(USE_DELAY_SLOT, &done, hs, at,
|
||||
Operand(HeapNumber::kExponentBias + HeapNumber::kMantissaBits));
|
||||
mov_d(dst, src);
|
||||
round(this, dst, src);
|
||||
dmfc1(at, dst);
|
||||
Branch(USE_DELAY_SLOT, &done, ne, at, Operand(zero_reg));
|
||||
cvt_d_l(dst, dst);
|
||||
srl(at, scratch, 31);
|
||||
sll(at, at, 31);
|
||||
mthc1(at, dst);
|
||||
bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
void TurboAssembler::Floor_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_floor,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->floor_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Ceil_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_ceil,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->ceil_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Trunc_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_trunc,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->trunc_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Round_d_d(FPURegister dst, FPURegister src) {
|
||||
RoundDouble(dst, src, mode_round,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->round_l_d(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename RoundFunc>
|
||||
void TurboAssembler::RoundFloat(FPURegister dst, FPURegister src,
|
||||
FPURoundingMode mode, RoundFunc round) {
|
||||
BlockTrampolinePoolScope block_trampoline_pool(this);
|
||||
Register scratch = t8;
|
||||
if (kArchVariant == kMips64r6) {
|
||||
cfc1(scratch, FCSR);
|
||||
li(at, Operand(mode));
|
||||
ctc1(at, FCSR);
|
||||
rint_s(dst, src);
|
||||
ctc1(scratch, FCSR);
|
||||
} else {
|
||||
int32_t kFloat32ExponentBias = 127;
|
||||
int32_t kFloat32MantissaBits = 23;
|
||||
int32_t kFloat32ExponentBits = 8;
|
||||
Label done;
|
||||
mfc1(scratch, src);
|
||||
Ext(at, scratch, kFloat32MantissaBits, kFloat32ExponentBits);
|
||||
Branch(USE_DELAY_SLOT, &done, hs, at,
|
||||
Operand(kFloat32ExponentBias + kFloat32MantissaBits));
|
||||
mov_s(dst, src);
|
||||
round(this, dst, src);
|
||||
mfc1(at, dst);
|
||||
Branch(USE_DELAY_SLOT, &done, ne, at, Operand(zero_reg));
|
||||
cvt_s_w(dst, dst);
|
||||
srl(at, scratch, 31);
|
||||
sll(at, at, 31);
|
||||
mtc1(at, dst);
|
||||
bind(&done);
|
||||
}
|
||||
}
|
||||
|
||||
void TurboAssembler::Floor_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_floor,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->floor_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Ceil_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_ceil,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->ceil_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Trunc_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_trunc,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->trunc_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void TurboAssembler::Round_s_s(FPURegister dst, FPURegister src) {
|
||||
RoundFloat(dst, src, mode_round,
|
||||
[](TurboAssembler* tasm, FPURegister dst, FPURegister src) {
|
||||
tasm->round_w_s(dst, src);
|
||||
});
|
||||
}
|
||||
|
||||
void MacroAssembler::Madd_s(FPURegister fd, FPURegister fr, FPURegister fs,
|
||||
FPURegister ft, FPURegister scratch) {
|
||||
DCHECK(fr != scratch && fs != scratch && ft != scratch);
|
||||
|
@ -824,6 +824,18 @@ class TurboAssembler : public Assembler {
|
||||
void Trunc_ul_s(FPURegister fd, Register rs, FPURegister scratch,
|
||||
Register result = no_reg);
|
||||
|
||||
// Round double functions
|
||||
void Trunc_d_d(FPURegister fd, FPURegister fs);
|
||||
void Round_d_d(FPURegister fd, FPURegister fs);
|
||||
void Floor_d_d(FPURegister fd, FPURegister fs);
|
||||
void Ceil_d_d(FPURegister fd, FPURegister fs);
|
||||
|
||||
// Round float functions
|
||||
void Trunc_s_s(FPURegister fd, FPURegister fs);
|
||||
void Round_s_s(FPURegister fd, FPURegister fs);
|
||||
void Floor_s_s(FPURegister fd, FPURegister fs);
|
||||
void Ceil_s_s(FPURegister fd, FPURegister fs);
|
||||
|
||||
// Jump the register contains a smi.
|
||||
void JumpIfSmi(Register value, Label* smi_label, Register scratch = at,
|
||||
BranchDelaySlot bd = PROTECT);
|
||||
@ -900,6 +912,14 @@ class TurboAssembler : public Assembler {
|
||||
void BranchLong(Label* L, BranchDelaySlot bdslot);
|
||||
void BranchAndLinkLong(Label* L, BranchDelaySlot bdslot);
|
||||
|
||||
template <typename RoundFunc>
|
||||
void RoundDouble(FPURegister dst, FPURegister src, FPURoundingMode mode,
|
||||
RoundFunc round);
|
||||
|
||||
template <typename RoundFunc>
|
||||
void RoundFloat(FPURegister dst, FPURegister src, FPURoundingMode mode,
|
||||
RoundFunc round);
|
||||
|
||||
// Push a fixed frame, consisting of ra, fp.
|
||||
void PushCommonFrame(Register marker_reg = no_reg);
|
||||
};
|
||||
|
@ -674,10 +674,10 @@ FP_BINOP(f32_mul, mul_s)
|
||||
FP_BINOP(f32_div, div_s)
|
||||
FP_UNOP(f32_abs, abs_s)
|
||||
FP_UNOP(f32_neg, neg_s)
|
||||
FP_UNOP(f32_ceil, ceil_w_s)
|
||||
FP_UNOP(f32_floor, floor_w_s)
|
||||
FP_UNOP(f32_trunc, trunc_w_s)
|
||||
FP_UNOP(f32_nearest_int, rint_s)
|
||||
FP_UNOP(f32_ceil, Ceil_s_s)
|
||||
FP_UNOP(f32_floor, Floor_s_s)
|
||||
FP_UNOP(f32_trunc, Trunc_s_s)
|
||||
FP_UNOP(f32_nearest_int, Round_s_s)
|
||||
FP_UNOP(f32_sqrt, sqrt_s)
|
||||
FP_BINOP(f64_add, add_d)
|
||||
FP_BINOP(f64_sub, sub_d)
|
||||
@ -685,15 +685,48 @@ FP_BINOP(f64_mul, mul_d)
|
||||
FP_BINOP(f64_div, div_d)
|
||||
FP_UNOP(f64_abs, abs_d)
|
||||
FP_UNOP(f64_neg, neg_d)
|
||||
FP_UNOP(f64_ceil, ceil_w_d)
|
||||
FP_UNOP(f64_floor, floor_w_d)
|
||||
FP_UNOP(f64_trunc, trunc_w_d)
|
||||
FP_UNOP(f64_nearest_int, rint_d)
|
||||
FP_UNOP(f64_sqrt, sqrt_d)
|
||||
|
||||
#undef FP_BINOP
|
||||
#undef FP_UNOP
|
||||
|
||||
void LiftoffAssembler::emit_f64_ceil(DoubleRegister dst, DoubleRegister src) {
|
||||
if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
|
||||
IsFp64Mode()) {
|
||||
Ceil_d_d(dst, src);
|
||||
} else {
|
||||
BAILOUT("emit_f64_ceil");
|
||||
}
|
||||
}
|
||||
|
||||
void LiftoffAssembler::emit_f64_floor(DoubleRegister dst, DoubleRegister src) {
|
||||
if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
|
||||
IsFp64Mode()) {
|
||||
Floor_d_d(dst, src);
|
||||
} else {
|
||||
BAILOUT("emit_f64_floor");
|
||||
}
|
||||
}
|
||||
|
||||
void LiftoffAssembler::emit_f64_trunc(DoubleRegister dst, DoubleRegister src) {
|
||||
if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
|
||||
IsFp64Mode()) {
|
||||
Trunc_d_d(dst, src);
|
||||
} else {
|
||||
BAILOUT("emit_f64_trunc");
|
||||
}
|
||||
}
|
||||
|
||||
void LiftoffAssembler::emit_f64_nearest_int(DoubleRegister dst,
|
||||
DoubleRegister src) {
|
||||
if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) &&
|
||||
IsFp64Mode()) {
|
||||
Round_d_d(dst, src);
|
||||
} else {
|
||||
BAILOUT("emit_f64_nearest_int");
|
||||
}
|
||||
}
|
||||
|
||||
bool LiftoffAssembler::emit_type_conversion(WasmOpcode opcode,
|
||||
LiftoffRegister dst,
|
||||
LiftoffRegister src) {
|
||||
|
@ -561,10 +561,10 @@ FP_BINOP(f32_mul, mul_s)
|
||||
FP_BINOP(f32_div, div_s)
|
||||
FP_UNOP(f32_abs, abs_s)
|
||||
FP_UNOP(f32_neg, neg_s)
|
||||
FP_UNOP(f32_ceil, ceil_w_s)
|
||||
FP_UNOP(f32_floor, floor_w_s)
|
||||
FP_UNOP(f32_trunc, trunc_w_s)
|
||||
FP_UNOP(f32_nearest_int, rint_s)
|
||||
FP_UNOP(f32_ceil, Ceil_s_s)
|
||||
FP_UNOP(f32_floor, Floor_s_s)
|
||||
FP_UNOP(f32_trunc, Trunc_s_s)
|
||||
FP_UNOP(f32_nearest_int, Round_s_s)
|
||||
FP_UNOP(f32_sqrt, sqrt_s)
|
||||
FP_BINOP(f64_add, add_d)
|
||||
FP_BINOP(f64_sub, sub_d)
|
||||
@ -572,10 +572,10 @@ FP_BINOP(f64_mul, mul_d)
|
||||
FP_BINOP(f64_div, div_d)
|
||||
FP_UNOP(f64_abs, abs_d)
|
||||
FP_UNOP(f64_neg, neg_d)
|
||||
FP_UNOP(f64_ceil, ceil_w_d)
|
||||
FP_UNOP(f64_floor, floor_w_d)
|
||||
FP_UNOP(f64_trunc, trunc_w_d)
|
||||
FP_UNOP(f64_nearest_int, rint_d)
|
||||
FP_UNOP(f64_ceil, Ceil_d_d)
|
||||
FP_UNOP(f64_floor, Floor_d_d)
|
||||
FP_UNOP(f64_trunc, Trunc_d_d)
|
||||
FP_UNOP(f64_nearest_int, Round_d_d)
|
||||
FP_UNOP(f64_sqrt, sqrt_d)
|
||||
|
||||
#undef FP_BINOP
|
||||
|
Loading…
Reference in New Issue
Block a user