HIR: Add opcode SET_ROUNDING_MODE (taking FPSCR as an argument)
This commit is contained in:
parent
dbece71945
commit
82efbd7bc5
|
@ -465,6 +465,7 @@ struct Sequence {
|
||||||
const REG_CONST_FN& reg_const_fn) {
|
const REG_CONST_FN& reg_const_fn) {
|
||||||
if (i.src1.is_constant) {
|
if (i.src1.is_constant) {
|
||||||
if (i.src2.is_constant) {
|
if (i.src2.is_constant) {
|
||||||
|
// Both constants.
|
||||||
if (i.src1.ConstantFitsIn32Reg()) {
|
if (i.src1.ConstantFitsIn32Reg()) {
|
||||||
e.mov(i.dest, i.src2.constant());
|
e.mov(i.dest, i.src2.constant());
|
||||||
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src1.constant()));
|
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src1.constant()));
|
||||||
|
@ -478,6 +479,7 @@ struct Sequence {
|
||||||
reg_reg_fn(e, i.dest, temp);
|
reg_reg_fn(e, i.dest, temp);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// src1 constant.
|
||||||
if (i.dest == i.src2) {
|
if (i.dest == i.src2) {
|
||||||
if (i.src1.ConstantFitsIn32Reg()) {
|
if (i.src1.ConstantFitsIn32Reg()) {
|
||||||
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src1.constant()));
|
reg_const_fn(e, i.dest, static_cast<int32_t>(i.src1.constant()));
|
||||||
|
@ -7588,6 +7590,25 @@ struct ATOMIC_COMPARE_EXCHANGE_I64
|
||||||
EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
EMITTER_OPCODE_TABLE(OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
||||||
ATOMIC_COMPARE_EXCHANGE_I32, ATOMIC_COMPARE_EXCHANGE_I64);
|
ATOMIC_COMPARE_EXCHANGE_I32, ATOMIC_COMPARE_EXCHANGE_I64);
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// OPCODE_SET_ROUNDING_MODE
|
||||||
|
// ============================================================================
|
||||||
|
// Input: FPSCR (PPC format)
|
||||||
|
static const uint32_t mxcsr_table[] = {
|
||||||
|
0x1F80, 0x7F80, 0x5F80, 0x3F80, 0x9F80, 0xFF80, 0xDF80, 0xBF80,
|
||||||
|
};
|
||||||
|
struct SET_ROUNDING_MODE_I32
|
||||||
|
: Sequence<SET_ROUNDING_MODE_I32,
|
||||||
|
I<OPCODE_SET_ROUNDING_MODE, VoidOp, I32Op>> {
|
||||||
|
static void Emit(X64Emitter& e, const EmitArgType& i) {
|
||||||
|
e.mov(e.rcx, i.src1);
|
||||||
|
e.and_(e.rcx, 0x7);
|
||||||
|
e.mov(e.rax, uintptr_t(mxcsr_table));
|
||||||
|
e.vldmxcsr(e.ptr[e.rax + e.rcx * 4]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EMITTER_OPCODE_TABLE(OPCODE_SET_ROUNDING_MODE, SET_ROUNDING_MODE_I32);
|
||||||
|
|
||||||
void RegisterSequences() {
|
void RegisterSequences() {
|
||||||
Register_OPCODE_COMMENT();
|
Register_OPCODE_COMMENT();
|
||||||
Register_OPCODE_NOP();
|
Register_OPCODE_NOP();
|
||||||
|
@ -7706,6 +7727,7 @@ void RegisterSequences() {
|
||||||
Register_OPCODE_UNPACK();
|
Register_OPCODE_UNPACK();
|
||||||
Register_OPCODE_ATOMIC_EXCHANGE();
|
Register_OPCODE_ATOMIC_EXCHANGE();
|
||||||
Register_OPCODE_ATOMIC_COMPARE_EXCHANGE();
|
Register_OPCODE_ATOMIC_COMPARE_EXCHANGE();
|
||||||
|
Register_OPCODE_SET_ROUNDING_MODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SelectSequence(X64Emitter* e, const Instr* i, const Instr** new_tail) {
|
bool SelectSequence(X64Emitter* e, const Instr* i, const Instr** new_tail) {
|
||||||
|
|
|
@ -1269,6 +1269,12 @@ void HIRBuilder::Prefetch(Value* address, size_t length,
|
||||||
|
|
||||||
void HIRBuilder::MemoryBarrier() { AppendInstr(OPCODE_MEMORY_BARRIER_info, 0); }
|
void HIRBuilder::MemoryBarrier() { AppendInstr(OPCODE_MEMORY_BARRIER_info, 0); }
|
||||||
|
|
||||||
|
void HIRBuilder::SetRoundingMode(Value* value) {
|
||||||
|
ASSERT_INTEGER_TYPE(value);
|
||||||
|
Instr* i = AppendInstr(OPCODE_SET_ROUNDING_MODE_info, 0);
|
||||||
|
i->set_src1(value);
|
||||||
|
}
|
||||||
|
|
||||||
Value* HIRBuilder::Max(Value* value1, Value* value2) {
|
Value* HIRBuilder::Max(Value* value1, Value* value2) {
|
||||||
ASSERT_TYPES_EQUAL(value1, value2);
|
ASSERT_TYPES_EQUAL(value1, value2);
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,7 @@ class HIRBuilder {
|
||||||
void Prefetch(Value* address, size_t length, uint32_t prefetch_flags = 0);
|
void Prefetch(Value* address, size_t length, uint32_t prefetch_flags = 0);
|
||||||
void MemoryBarrier();
|
void MemoryBarrier();
|
||||||
|
|
||||||
|
void SetRoundingMode(Value* value);
|
||||||
Value* Max(Value* value1, Value* value2);
|
Value* Max(Value* value1, Value* value2);
|
||||||
Value* VectorMax(Value* value1, Value* value2, TypeName part_type,
|
Value* VectorMax(Value* value1, Value* value2, TypeName part_type,
|
||||||
uint32_t arithmetic_flags = 0);
|
uint32_t arithmetic_flags = 0);
|
||||||
|
|
|
@ -225,6 +225,7 @@ enum Opcode {
|
||||||
OPCODE_UNPACK,
|
OPCODE_UNPACK,
|
||||||
OPCODE_ATOMIC_EXCHANGE,
|
OPCODE_ATOMIC_EXCHANGE,
|
||||||
OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
OPCODE_ATOMIC_COMPARE_EXCHANGE,
|
||||||
|
OPCODE_SET_ROUNDING_MODE,
|
||||||
__OPCODE_MAX_VALUE, // Keep at end.
|
__OPCODE_MAX_VALUE, // Keep at end.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -649,3 +649,9 @@ DEFINE_OPCODE(
|
||||||
"atomic_compare_exchange",
|
"atomic_compare_exchange",
|
||||||
OPCODE_SIG_V_V_V_V,
|
OPCODE_SIG_V_V_V_V,
|
||||||
OPCODE_FLAG_VOLATILE)
|
OPCODE_FLAG_VOLATILE)
|
||||||
|
|
||||||
|
DEFINE_OPCODE(
|
||||||
|
OPCODE_SET_ROUNDING_MODE,
|
||||||
|
"set_rounding_mode",
|
||||||
|
OPCODE_SIG_X_V,
|
||||||
|
0)
|
||||||
|
|
Loading…
Reference in New Issue