HIR: Add opcode SET_ROUNDING_MODE (taking FPSCR as an argument)

This commit is contained in:
Dr. Chat 2017-05-12 14:05:27 -05:00
parent dbece71945
commit 82efbd7bc5
5 changed files with 36 additions and 0 deletions

View File

@ -465,6 +465,7 @@ struct Sequence {
const REG_CONST_FN& reg_const_fn) {
if (i.src1.is_constant) {
if (i.src2.is_constant) {
// Both constants.
if (i.src1.ConstantFitsIn32Reg()) {
e.mov(i.dest, i.src2.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);
}
} else {
// src1 constant.
if (i.dest == i.src2) {
if (i.src1.ConstantFitsIn32Reg()) {
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,
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() {
Register_OPCODE_COMMENT();
Register_OPCODE_NOP();
@ -7706,6 +7727,7 @@ void RegisterSequences() {
Register_OPCODE_UNPACK();
Register_OPCODE_ATOMIC_EXCHANGE();
Register_OPCODE_ATOMIC_COMPARE_EXCHANGE();
Register_OPCODE_SET_ROUNDING_MODE();
}
bool SelectSequence(X64Emitter* e, const Instr* i, const Instr** new_tail) {

View File

@ -1269,6 +1269,12 @@ void HIRBuilder::Prefetch(Value* address, size_t length,
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) {
ASSERT_TYPES_EQUAL(value1, value2);

View File

@ -153,6 +153,7 @@ class HIRBuilder {
void Prefetch(Value* address, size_t length, uint32_t prefetch_flags = 0);
void MemoryBarrier();
void SetRoundingMode(Value* value);
Value* Max(Value* value1, Value* value2);
Value* VectorMax(Value* value1, Value* value2, TypeName part_type,
uint32_t arithmetic_flags = 0);

View File

@ -225,6 +225,7 @@ enum Opcode {
OPCODE_UNPACK,
OPCODE_ATOMIC_EXCHANGE,
OPCODE_ATOMIC_COMPARE_EXCHANGE,
OPCODE_SET_ROUNDING_MODE,
__OPCODE_MAX_VALUE, // Keep at end.
};

View File

@ -649,3 +649,9 @@ DEFINE_OPCODE(
"atomic_compare_exchange",
OPCODE_SIG_V_V_V_V,
OPCODE_FLAG_VOLATILE)
DEFINE_OPCODE(
OPCODE_SET_ROUNDING_MODE,
"set_rounding_mode",
OPCODE_SIG_X_V,
0)