Commit 8f3ba46a authored by sreten.kovacevic's avatar sreten.kovacevic Committed by Commit Bot

MIPS[64]: Port: `[Atomics] Make Atomics.exchange a builtin using TF` and...

MIPS[64]: Port: `[Atomics] Make Atomics.exchange a builtin using TF` and `[Atomics] Make Atomics.compareExchange a builtin using TF`

Port 301c1237 and 82b5c8c9

Implemented exchange and compareExchange atomics.

Bug: 
Change-Id: I11a0d3d608ecf809c7947dd560884c6451dcdb3c
Reviewed-on: https://chromium-review.googlesource.com/649186Reviewed-by: 's avatarIvica Bogosavljevic <ivica.bogosavljevic@imgtec.com>
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@imgtec.com>
Cr-Commit-Position: refs/heads/master@{#47846}
parent ae28e0cf
......@@ -594,6 +594,78 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER() \
do { \
Label exchange; \
__ sync(); \
__ bind(&exchange); \
__ addu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ Ll(i.OutputRegister(0), MemOperand(i.TempRegister(0), 0)); \
__ Sc(i.InputRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&exchange, eq, i.InputRegister(2), Operand(zero_reg)); \
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(sign_extend, size) \
do { \
Label exchange; \
__ addu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ andi(i.TempRegister(1), i.TempRegister(0), 0x3); \
__ Subu(i.TempRegister(0), i.TempRegister(0), Operand(i.TempRegister(1))); \
__ sll(i.TempRegister(1), i.TempRegister(1), 3); \
__ sync(); \
__ bind(&exchange); \
__ Ll(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ ExtractBits(i.OutputRegister(0), i.TempRegister(2), i.TempRegister(1), \
size, sign_extend); \
__ InsertBits(i.TempRegister(2), i.InputRegister(2), i.TempRegister(1), \
size); \
__ Sc(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&exchange, eq, i.TempRegister(2), Operand(zero_reg)); \
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER() \
do { \
Label compareExchange; \
Label exit; \
__ addu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ sync(); \
__ bind(&compareExchange); \
__ Ll(i.OutputRegister(0), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&exit, ne, i.InputRegister(2), \
Operand(i.OutputRegister(0))); \
__ Sc(i.InputRegister(3), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&compareExchange, eq, i.InputRegister(3), \
Operand(zero_reg)); \
__ bind(&exit); \
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(sign_extend, size) \
do { \
Label compareExchange; \
Label exit; \
__ addu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ andi(i.TempRegister(1), i.TempRegister(0), 0x3); \
__ Subu(i.TempRegister(0), i.TempRegister(0), Operand(i.TempRegister(1))); \
__ sll(i.TempRegister(1), i.TempRegister(1), 3); \
__ sync(); \
__ bind(&compareExchange); \
__ Ll(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ ExtractBits(i.OutputRegister(0), i.TempRegister(2), i.TempRegister(1), \
size, sign_extend); \
__ BranchShort(&exit, ne, i.InputRegister(2), \
Operand(i.OutputRegister(0))); \
__ InsertBits(i.TempRegister(2), i.InputRegister(3), i.TempRegister(1), \
size); \
__ Sc(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&compareExchange, eq, i.TempRegister(2), \
Operand(zero_reg)); \
__ bind(&exit); \
__ sync(); \
} while (0)
#define ASSEMBLE_IEEE754_BINOP(name) \
do { \
FrameScope scope(tasm(), StackFrame::MANUAL); \
......@@ -1754,16 +1826,34 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_ATOMIC_STORE_INTEGER(sw);
break;
case kAtomicExchangeInt8:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(true, 8);
break;
case kAtomicExchangeUint8:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(false, 8);
break;
case kAtomicExchangeInt16:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(true, 16);
break;
case kAtomicExchangeUint16:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(false, 16);
break;
case kAtomicExchangeWord32:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER();
break;
case kAtomicCompareExchangeInt8:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(true, 8);
break;
case kAtomicCompareExchangeUint8:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(false, 8);
break;
case kAtomicCompareExchangeInt16:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(true, 16);
break;
case kAtomicCompareExchangeUint16:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(false, 16);
break;
case kAtomicCompareExchangeWord32:
UNREACHABLE();
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER();
break;
#define ATOMIC_BINOP_CASE(op, inst) \
case kAtomic##op##Int8: \
......
......@@ -1917,10 +1917,82 @@ void InstructionSelector::VisitAtomicStore(Node* node) {
}
}
void InstructionSelector::VisitAtomicExchange(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitAtomicExchange(Node* node) {
MipsOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* value = node->InputAt(2);
ArchOpcode opcode = kArchNop;
MachineType type = AtomicOpRepresentationOf(node->op());
if (type == MachineType::Int8()) {
opcode = kAtomicExchangeInt8;
} else if (type == MachineType::Uint8()) {
opcode = kAtomicExchangeUint8;
} else if (type == MachineType::Int16()) {
opcode = kAtomicExchangeInt16;
} else if (type == MachineType::Uint16()) {
opcode = kAtomicExchangeUint16;
} else if (type == MachineType::Int32() || type == MachineType::Uint32()) {
opcode = kAtomicExchangeWord32;
} else {
UNREACHABLE();
return;
}
AddressingMode addressing_mode = kMode_MRI;
InstructionOperand inputs[3];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(base);
inputs[input_count++] = g.UseUniqueRegister(index);
inputs[input_count++] = g.UseUniqueRegister(value);
InstructionOperand outputs[1];
outputs[0] = g.UseUniqueRegister(node);
InstructionOperand temp[3];
temp[0] = g.TempRegister();
temp[1] = g.TempRegister();
temp[2] = g.TempRegister();
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
Emit(code, 1, outputs, input_count, inputs, 3, temp);
}
void InstructionSelector::VisitAtomicCompareExchange(Node* node) {
UNIMPLEMENTED();
MipsOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* old_value = node->InputAt(2);
Node* new_value = node->InputAt(3);
ArchOpcode opcode = kArchNop;
MachineType type = AtomicOpRepresentationOf(node->op());
if (type == MachineType::Int8()) {
opcode = kAtomicCompareExchangeInt8;
} else if (type == MachineType::Uint8()) {
opcode = kAtomicCompareExchangeUint8;
} else if (type == MachineType::Int16()) {
opcode = kAtomicCompareExchangeInt16;
} else if (type == MachineType::Uint16()) {
opcode = kAtomicCompareExchangeUint16;
} else if (type == MachineType::Int32() || type == MachineType::Uint32()) {
opcode = kAtomicCompareExchangeWord32;
} else {
UNREACHABLE();
return;
}
AddressingMode addressing_mode = kMode_MRI;
InstructionOperand inputs[4];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(base);
inputs[input_count++] = g.UseUniqueRegister(index);
inputs[input_count++] = g.UseUniqueRegister(old_value);
inputs[input_count++] = g.UseUniqueRegister(new_value);
InstructionOperand outputs[1];
outputs[0] = g.UseUniqueRegister(node);
InstructionOperand temp[3];
temp[0] = g.TempRegister();
temp[1] = g.TempRegister();
temp[2] = g.TempRegister();
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
Emit(code, 1, outputs, input_count, inputs, 3, temp);
}
void InstructionSelector::VisitAtomicBinaryOperation(
......
......@@ -631,6 +631,80 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER() \
do { \
Label exchange; \
__ sync(); \
__ bind(&exchange); \
__ daddu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ Ll(i.OutputRegister(0), MemOperand(i.TempRegister(0), 0)); \
__ Sc(i.InputRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&exchange, eq, i.InputRegister(2), Operand(zero_reg)); \
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(sign_extend, size) \
do { \
Label exchange; \
__ daddu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ andi(i.TempRegister(1), i.TempRegister(0), 0x3); \
__ Dsubu(i.TempRegister(0), i.TempRegister(0), \
Operand(i.TempRegister(1))); \
__ sll(i.TempRegister(1), i.TempRegister(1), 3); \
__ sync(); \
__ bind(&exchange); \
__ Ll(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ ExtractBits(i.OutputRegister(0), i.TempRegister(2), i.TempRegister(1), \
size, sign_extend); \
__ InsertBits(i.TempRegister(2), i.InputRegister(2), i.TempRegister(1), \
size); \
__ Sc(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&exchange, eq, i.TempRegister(2), Operand(zero_reg)); \
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER() \
do { \
Label compareExchange; \
Label exit; \
__ daddu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ sync(); \
__ bind(&compareExchange); \
__ Ll(i.OutputRegister(0), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&exit, ne, i.InputRegister(2), \
Operand(i.OutputRegister(0))); \
__ Sc(i.InputRegister(3), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&compareExchange, eq, i.InputRegister(3), \
Operand(zero_reg)); \
__ bind(&exit); \
__ sync(); \
} while (0)
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(sign_extend, size) \
do { \
Label compareExchange; \
Label exit; \
__ daddu(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \
__ andi(i.TempRegister(1), i.TempRegister(0), 0x3); \
__ Dsubu(i.TempRegister(0), i.TempRegister(0), \
Operand(i.TempRegister(1))); \
__ sll(i.TempRegister(1), i.TempRegister(1), 3); \
__ sync(); \
__ bind(&compareExchange); \
__ Ll(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ ExtractBits(i.OutputRegister(0), i.TempRegister(2), i.TempRegister(1), \
size, sign_extend); \
__ BranchShort(&exit, ne, i.InputRegister(2), \
Operand(i.OutputRegister(0))); \
__ InsertBits(i.TempRegister(2), i.InputRegister(3), i.TempRegister(1), \
size); \
__ Sc(i.TempRegister(2), MemOperand(i.TempRegister(0), 0)); \
__ BranchShort(&compareExchange, eq, i.TempRegister(2), \
Operand(zero_reg)); \
__ bind(&exit); \
__ sync(); \
} while (0)
#define ASSEMBLE_IEEE754_BINOP(name) \
do { \
FrameScope scope(tasm(), StackFrame::MANUAL); \
......@@ -2035,16 +2109,35 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_ATOMIC_STORE_INTEGER(Sw);
break;
case kAtomicExchangeInt8:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(true, 8);
break;
case kAtomicExchangeUint8:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(false, 8);
break;
case kAtomicExchangeInt16:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(true, 16);
break;
case kAtomicExchangeUint16:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER_EXT(false, 16);
break;
case kAtomicExchangeWord32:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER();
break;
case kAtomicCompareExchangeInt8:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(true, 8);
break;
case kAtomicCompareExchangeUint8:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(false, 8);
break;
case kAtomicCompareExchangeInt16:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(true, 16);
break;
case kAtomicCompareExchangeUint16:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER_EXT(false, 16);
break;
case kAtomicCompareExchangeWord32:
UNREACHABLE();
__ sll(i.InputRegister(2), i.InputRegister(2), 0);
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER();
break;
#define ATOMIC_BINOP_CASE(op, inst) \
case kAtomic##op##Int8: \
......
......@@ -2610,10 +2610,82 @@ void InstructionSelector::VisitAtomicStore(Node* node) {
}
}
void InstructionSelector::VisitAtomicExchange(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitAtomicExchange(Node* node) {
Mips64OperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* value = node->InputAt(2);
ArchOpcode opcode = kArchNop;
MachineType type = AtomicOpRepresentationOf(node->op());
if (type == MachineType::Int8()) {
opcode = kAtomicExchangeInt8;
} else if (type == MachineType::Uint8()) {
opcode = kAtomicExchangeUint8;
} else if (type == MachineType::Int16()) {
opcode = kAtomicExchangeInt16;
} else if (type == MachineType::Uint16()) {
opcode = kAtomicExchangeUint16;
} else if (type == MachineType::Int32() || type == MachineType::Uint32()) {
opcode = kAtomicExchangeWord32;
} else {
UNREACHABLE();
return;
}
AddressingMode addressing_mode = kMode_MRI;
InstructionOperand inputs[3];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(base);
inputs[input_count++] = g.UseUniqueRegister(index);
inputs[input_count++] = g.UseUniqueRegister(value);
InstructionOperand outputs[1];
outputs[0] = g.UseUniqueRegister(node);
InstructionOperand temp[3];
temp[0] = g.TempRegister();
temp[1] = g.TempRegister();
temp[2] = g.TempRegister();
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
Emit(code, 1, outputs, input_count, inputs, 3, temp);
}
void InstructionSelector::VisitAtomicCompareExchange(Node* node) {
UNIMPLEMENTED();
Mips64OperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* old_value = node->InputAt(2);
Node* new_value = node->InputAt(3);
ArchOpcode opcode = kArchNop;
MachineType type = AtomicOpRepresentationOf(node->op());
if (type == MachineType::Int8()) {
opcode = kAtomicCompareExchangeInt8;
} else if (type == MachineType::Uint8()) {
opcode = kAtomicCompareExchangeUint8;
} else if (type == MachineType::Int16()) {
opcode = kAtomicCompareExchangeInt16;
} else if (type == MachineType::Uint16()) {
opcode = kAtomicCompareExchangeUint16;
} else if (type == MachineType::Int32() || type == MachineType::Uint32()) {
opcode = kAtomicCompareExchangeWord32;
} else {
UNREACHABLE();
return;
}
AddressingMode addressing_mode = kMode_MRI;
InstructionOperand inputs[4];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(base);
inputs[input_count++] = g.UseUniqueRegister(index);
inputs[input_count++] = g.UseUniqueRegister(old_value);
inputs[input_count++] = g.UseUniqueRegister(new_value);
InstructionOperand outputs[1];
outputs[0] = g.UseUniqueRegister(node);
InstructionOperand temp[3];
temp[0] = g.TempRegister();
temp[1] = g.TempRegister();
temp[2] = g.TempRegister();
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
Emit(code, 1, outputs, input_count, inputs, 3, temp);
}
void InstructionSelector::VisitAtomicBinaryOperation(
......
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