Commit 4ab8215e authored by andrew-cc-chen's avatar andrew-cc-chen Committed by Commit Bot

[ppc] Implemented Atomic64 operations

Change-Id: Ic99e2e02ae644382873d9cf0621145bcde23b6b2
Reviewed-on: https://chromium-review.googlesource.com/1257807Reviewed-by: 's avatarJunliang Yan <jyan@ca.ibm.com>
Reviewed-by: 's avatarDeepti Gandluri <gdeepti@chromium.org>
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#56353}
parent 28a9235c
......@@ -2428,7 +2428,7 @@ void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) {
#endif // !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM
#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS64 && \
!V8_TARGET_ARCH_S390
!V8_TARGET_ARCH_S390 && !V8_TARGET_ARCH_PPC
void InstructionSelector::VisitWord64AtomicLoad(Node* node) { UNIMPLEMENTED(); }
void InstructionSelector::VisitWord64AtomicStore(Node* node) {
......@@ -2452,7 +2452,7 @@ void InstructionSelector::VisitWord64AtomicExchange(Node* node) {
void InstructionSelector::VisitWord64AtomicCompareExchange(Node* node) {
UNIMPLEMENTED();
}
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 &&
#endif // !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_PPC
// !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_S390
#if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \
......
......@@ -1979,32 +1979,45 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_ATOMIC_LOAD_INTEGER(lbz, lbzx);
__ extsb(i.OutputRegister(), i.OutputRegister());
break;
case kPPC_Word64AtomicLoadUint8:
case kWord32AtomicLoadUint8:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lbz, lbzx);
break;
case kWord32AtomicLoadInt16:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lha, lhax);
break;
case kPPC_Word64AtomicLoadUint16:
case kWord32AtomicLoadUint16:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lhz, lhzx);
break;
case kPPC_Word64AtomicLoadUint32:
case kWord32AtomicLoadWord32:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lwz, lwzx);
break;
case kPPC_Word64AtomicLoadUint64:
ASSEMBLE_ATOMIC_LOAD_INTEGER(ld, ldx);
break;
case kPPC_Word64AtomicStoreUint8:
case kWord32AtomicStoreWord8:
ASSEMBLE_ATOMIC_STORE_INTEGER(stb, stbx);
break;
case kPPC_Word64AtomicStoreUint16:
case kWord32AtomicStoreWord16:
ASSEMBLE_ATOMIC_STORE_INTEGER(sth, sthx);
break;
case kPPC_Word64AtomicStoreUint32:
case kWord32AtomicStoreWord32:
ASSEMBLE_ATOMIC_STORE_INTEGER(stw, stwx);
break;
case kPPC_Word64AtomicStoreUint64:
ASSEMBLE_ATOMIC_STORE_INTEGER(std, stdx);
break;
case kWord32AtomicExchangeInt8:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lbarx, stbcx);
__ extsb(i.OutputRegister(0), i.OutputRegister(0));
break;
case kPPC_Word64AtomicExchangeUint8:
case kWord32AtomicExchangeUint8:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lbarx, stbcx);
break;
......@@ -2012,44 +2025,57 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lharx, sthcx);
__ extsh(i.OutputRegister(0), i.OutputRegister(0));
break;
case kPPC_Word64AtomicExchangeUint16:
case kWord32AtomicExchangeUint16:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lharx, sthcx);
break;
case kPPC_Word64AtomicExchangeUint32:
case kWord32AtomicExchangeWord32:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(lwarx, stwcx);
break;
case kPPC_Word64AtomicExchangeUint64:
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldarx, stdcx);
break;
case kWord32AtomicCompareExchangeInt8:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_SIGN_EXT(cmp, lbarx, stbcx, extsb);
break;
case kPPC_Word64AtomicCompareExchangeUint8:
case kWord32AtomicCompareExchangeUint8:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmp, lbarx, stbcx);
break;
case kWord32AtomicCompareExchangeInt16:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_SIGN_EXT(cmp, lharx, sthcx, extsh);
break;
case kPPC_Word64AtomicCompareExchangeUint16:
case kWord32AtomicCompareExchangeUint16:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmp, lharx, sthcx);
break;
case kPPC_Word64AtomicCompareExchangeUint32:
case kWord32AtomicCompareExchangeWord32:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmpw, lwarx, stwcx);
break;
#define ATOMIC_BINOP_CASE(op, inst) \
case kWord32Atomic##op##Int8: \
ASSEMBLE_ATOMIC_BINOP_SIGN_EXT(inst, lbarx, stbcx, extsb); \
break; \
case kWord32Atomic##op##Uint8: \
ASSEMBLE_ATOMIC_BINOP(inst, lbarx, stbcx); \
break; \
case kWord32Atomic##op##Int16: \
ASSEMBLE_ATOMIC_BINOP_SIGN_EXT(inst, lharx, sthcx, extsh); \
break; \
case kWord32Atomic##op##Uint16: \
ASSEMBLE_ATOMIC_BINOP(inst, lharx, sthcx); \
break; \
case kWord32Atomic##op##Word32: \
ASSEMBLE_ATOMIC_BINOP(inst, lwarx, stwcx); \
case kPPC_Word64AtomicCompareExchangeUint64:
ASSEMBLE_ATOMIC_COMPARE_EXCHANGE(cmp, ldarx, stdcx);
break;
#define ATOMIC_BINOP_CASE(op, inst) \
case kWord32Atomic##op##Int8: \
ASSEMBLE_ATOMIC_BINOP_SIGN_EXT(inst, lbarx, stbcx, extsb); \
break; \
case kPPC_Word64Atomic##op##Uint8: \
case kWord32Atomic##op##Uint8: \
ASSEMBLE_ATOMIC_BINOP(inst, lbarx, stbcx); \
break; \
case kWord32Atomic##op##Int16: \
ASSEMBLE_ATOMIC_BINOP_SIGN_EXT(inst, lharx, sthcx, extsh); \
break; \
case kPPC_Word64Atomic##op##Uint16: \
case kWord32Atomic##op##Uint16: \
ASSEMBLE_ATOMIC_BINOP(inst, lharx, sthcx); \
break; \
case kPPC_Word64Atomic##op##Uint32: \
case kWord32Atomic##op##Word32: \
ASSEMBLE_ATOMIC_BINOP(inst, lwarx, stwcx); \
break;
ATOMIC_BINOP_CASE(Add, add)
ATOMIC_BINOP_CASE(Sub, sub)
......@@ -2058,6 +2084,17 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ATOMIC_BINOP_CASE(Xor, xor_)
#undef ATOMIC_BINOP_CASE
#define ATOMIC64_BINOP_CASE(op, inst) \
case kPPC_Word64Atomic##op##Uint64: \
ASSEMBLE_ATOMIC_BINOP(inst, ldarx, stdcx); \
break;
ATOMIC64_BINOP_CASE(Add, add)
ATOMIC64_BINOP_CASE(Sub, sub)
ATOMIC64_BINOP_CASE(And, and_)
ATOMIC64_BINOP_CASE(Or, orx)
ATOMIC64_BINOP_CASE(Xor, xor_)
#undef ATOMIC64_BINOP_CASE
case kPPC_ByteRev32: {
Register input = i.InputRegister(0);
Register output = i.OutputRegister();
......
......@@ -11,122 +11,158 @@ namespace compiler {
// PPC-specific opcodes that specify which assembly sequence to emit.
// Most opcodes specify a single instruction.
#define TARGET_ARCH_OPCODE_LIST(V) \
V(PPC_And) \
V(PPC_AndComplement) \
V(PPC_Or) \
V(PPC_OrComplement) \
V(PPC_Xor) \
V(PPC_ShiftLeft32) \
V(PPC_ShiftLeft64) \
V(PPC_ShiftLeftPair) \
V(PPC_ShiftRight32) \
V(PPC_ShiftRight64) \
V(PPC_ShiftRightPair) \
V(PPC_ShiftRightAlg32) \
V(PPC_ShiftRightAlg64) \
V(PPC_ShiftRightAlgPair) \
V(PPC_RotRight32) \
V(PPC_RotRight64) \
V(PPC_Not) \
V(PPC_RotLeftAndMask32) \
V(PPC_RotLeftAndClear64) \
V(PPC_RotLeftAndClearLeft64) \
V(PPC_RotLeftAndClearRight64) \
V(PPC_Add32) \
V(PPC_Add64) \
V(PPC_AddWithOverflow32) \
V(PPC_AddPair) \
V(PPC_AddDouble) \
V(PPC_Sub) \
V(PPC_SubWithOverflow32) \
V(PPC_SubPair) \
V(PPC_SubDouble) \
V(PPC_Mul32) \
V(PPC_Mul32WithHigh32) \
V(PPC_Mul64) \
V(PPC_MulHigh32) \
V(PPC_MulHighU32) \
V(PPC_MulPair) \
V(PPC_MulDouble) \
V(PPC_Div32) \
V(PPC_Div64) \
V(PPC_DivU32) \
V(PPC_DivU64) \
V(PPC_DivDouble) \
V(PPC_Mod32) \
V(PPC_Mod64) \
V(PPC_ModU32) \
V(PPC_ModU64) \
V(PPC_ModDouble) \
V(PPC_Neg) \
V(PPC_NegDouble) \
V(PPC_SqrtDouble) \
V(PPC_FloorDouble) \
V(PPC_CeilDouble) \
V(PPC_TruncateDouble) \
V(PPC_RoundDouble) \
V(PPC_MaxDouble) \
V(PPC_MinDouble) \
V(PPC_AbsDouble) \
V(PPC_Cntlz32) \
V(PPC_Cntlz64) \
V(PPC_Popcnt32) \
V(PPC_Popcnt64) \
V(PPC_Cmp32) \
V(PPC_Cmp64) \
V(PPC_CmpDouble) \
V(PPC_Tst32) \
V(PPC_Tst64) \
V(PPC_Push) \
V(PPC_PushFrame) \
V(PPC_StoreToStackSlot) \
V(PPC_ExtendSignWord8) \
V(PPC_ExtendSignWord16) \
V(PPC_ExtendSignWord32) \
V(PPC_Uint32ToUint64) \
V(PPC_Int64ToInt32) \
V(PPC_Int64ToFloat32) \
V(PPC_Int64ToDouble) \
V(PPC_Uint64ToFloat32) \
V(PPC_Uint64ToDouble) \
V(PPC_Int32ToFloat32) \
V(PPC_Int32ToDouble) \
V(PPC_Uint32ToFloat32) \
V(PPC_Uint32ToDouble) \
V(PPC_Float32ToDouble) \
V(PPC_Float64SilenceNaN) \
V(PPC_DoubleToInt32) \
V(PPC_DoubleToUint32) \
V(PPC_DoubleToInt64) \
V(PPC_DoubleToUint64) \
V(PPC_DoubleToFloat32) \
V(PPC_DoubleExtractLowWord32) \
V(PPC_DoubleExtractHighWord32) \
V(PPC_DoubleInsertLowWord32) \
V(PPC_DoubleInsertHighWord32) \
V(PPC_DoubleConstruct) \
V(PPC_BitcastInt32ToFloat32) \
V(PPC_BitcastFloat32ToInt32) \
V(PPC_BitcastInt64ToDouble) \
V(PPC_BitcastDoubleToInt64) \
V(PPC_LoadWordS8) \
V(PPC_LoadWordU8) \
V(PPC_LoadWordS16) \
V(PPC_LoadWordU16) \
V(PPC_LoadWordS32) \
V(PPC_LoadWordU32) \
V(PPC_LoadWord64) \
V(PPC_LoadFloat32) \
V(PPC_LoadDouble) \
V(PPC_StoreWord8) \
V(PPC_StoreWord16) \
V(PPC_StoreWord32) \
V(PPC_StoreWord64) \
V(PPC_StoreFloat32) \
V(PPC_StoreDouble) \
V(PPC_ByteRev32) \
V(PPC_ByteRev64)
#define TARGET_ARCH_OPCODE_LIST(V) \
V(PPC_And) \
V(PPC_AndComplement) \
V(PPC_Or) \
V(PPC_OrComplement) \
V(PPC_Xor) \
V(PPC_ShiftLeft32) \
V(PPC_ShiftLeft64) \
V(PPC_ShiftLeftPair) \
V(PPC_ShiftRight32) \
V(PPC_ShiftRight64) \
V(PPC_ShiftRightPair) \
V(PPC_ShiftRightAlg32) \
V(PPC_ShiftRightAlg64) \
V(PPC_ShiftRightAlgPair) \
V(PPC_RotRight32) \
V(PPC_RotRight64) \
V(PPC_Not) \
V(PPC_RotLeftAndMask32) \
V(PPC_RotLeftAndClear64) \
V(PPC_RotLeftAndClearLeft64) \
V(PPC_RotLeftAndClearRight64) \
V(PPC_Add32) \
V(PPC_Add64) \
V(PPC_AddWithOverflow32) \
V(PPC_AddPair) \
V(PPC_AddDouble) \
V(PPC_Sub) \
V(PPC_SubWithOverflow32) \
V(PPC_SubPair) \
V(PPC_SubDouble) \
V(PPC_Mul32) \
V(PPC_Mul32WithHigh32) \
V(PPC_Mul64) \
V(PPC_MulHigh32) \
V(PPC_MulHighU32) \
V(PPC_MulPair) \
V(PPC_MulDouble) \
V(PPC_Div32) \
V(PPC_Div64) \
V(PPC_DivU32) \
V(PPC_DivU64) \
V(PPC_DivDouble) \
V(PPC_Mod32) \
V(PPC_Mod64) \
V(PPC_ModU32) \
V(PPC_ModU64) \
V(PPC_ModDouble) \
V(PPC_Neg) \
V(PPC_NegDouble) \
V(PPC_SqrtDouble) \
V(PPC_FloorDouble) \
V(PPC_CeilDouble) \
V(PPC_TruncateDouble) \
V(PPC_RoundDouble) \
V(PPC_MaxDouble) \
V(PPC_MinDouble) \
V(PPC_AbsDouble) \
V(PPC_Cntlz32) \
V(PPC_Cntlz64) \
V(PPC_Popcnt32) \
V(PPC_Popcnt64) \
V(PPC_Cmp32) \
V(PPC_Cmp64) \
V(PPC_CmpDouble) \
V(PPC_Tst32) \
V(PPC_Tst64) \
V(PPC_Push) \
V(PPC_PushFrame) \
V(PPC_StoreToStackSlot) \
V(PPC_ExtendSignWord8) \
V(PPC_ExtendSignWord16) \
V(PPC_ExtendSignWord32) \
V(PPC_Uint32ToUint64) \
V(PPC_Int64ToInt32) \
V(PPC_Int64ToFloat32) \
V(PPC_Int64ToDouble) \
V(PPC_Uint64ToFloat32) \
V(PPC_Uint64ToDouble) \
V(PPC_Int32ToFloat32) \
V(PPC_Int32ToDouble) \
V(PPC_Uint32ToFloat32) \
V(PPC_Uint32ToDouble) \
V(PPC_Float32ToDouble) \
V(PPC_Float64SilenceNaN) \
V(PPC_DoubleToInt32) \
V(PPC_DoubleToUint32) \
V(PPC_DoubleToInt64) \
V(PPC_DoubleToUint64) \
V(PPC_DoubleToFloat32) \
V(PPC_DoubleExtractLowWord32) \
V(PPC_DoubleExtractHighWord32) \
V(PPC_DoubleInsertLowWord32) \
V(PPC_DoubleInsertHighWord32) \
V(PPC_DoubleConstruct) \
V(PPC_BitcastInt32ToFloat32) \
V(PPC_BitcastFloat32ToInt32) \
V(PPC_BitcastInt64ToDouble) \
V(PPC_BitcastDoubleToInt64) \
V(PPC_LoadWordS8) \
V(PPC_LoadWordU8) \
V(PPC_LoadWordS16) \
V(PPC_LoadWordU16) \
V(PPC_LoadWordS32) \
V(PPC_LoadWordU32) \
V(PPC_LoadWord64) \
V(PPC_LoadFloat32) \
V(PPC_LoadDouble) \
V(PPC_StoreWord8) \
V(PPC_StoreWord16) \
V(PPC_StoreWord32) \
V(PPC_StoreWord64) \
V(PPC_StoreFloat32) \
V(PPC_StoreDouble) \
V(PPC_ByteRev32) \
V(PPC_ByteRev64) \
V(PPC_Word64AtomicStoreUint8) \
V(PPC_Word64AtomicStoreUint16) \
V(PPC_Word64AtomicStoreUint32) \
V(PPC_Word64AtomicStoreUint64) \
V(PPC_Word64AtomicLoadUint8) \
V(PPC_Word64AtomicLoadUint16) \
V(PPC_Word64AtomicLoadUint32) \
V(PPC_Word64AtomicLoadUint64) \
V(PPC_Word64AtomicExchangeUint8) \
V(PPC_Word64AtomicExchangeUint16) \
V(PPC_Word64AtomicExchangeUint32) \
V(PPC_Word64AtomicExchangeUint64) \
V(PPC_Word64AtomicCompareExchangeUint8) \
V(PPC_Word64AtomicCompareExchangeUint16) \
V(PPC_Word64AtomicCompareExchangeUint32) \
V(PPC_Word64AtomicCompareExchangeUint64) \
V(PPC_Word64AtomicAddUint8) \
V(PPC_Word64AtomicAddUint16) \
V(PPC_Word64AtomicAddUint32) \
V(PPC_Word64AtomicAddUint64) \
V(PPC_Word64AtomicSubUint8) \
V(PPC_Word64AtomicSubUint16) \
V(PPC_Word64AtomicSubUint32) \
V(PPC_Word64AtomicSubUint64) \
V(PPC_Word64AtomicAndUint8) \
V(PPC_Word64AtomicAndUint16) \
V(PPC_Word64AtomicAndUint32) \
V(PPC_Word64AtomicAndUint64) \
V(PPC_Word64AtomicOrUint8) \
V(PPC_Word64AtomicOrUint16) \
V(PPC_Word64AtomicOrUint32) \
V(PPC_Word64AtomicOrUint64) \
V(PPC_Word64AtomicXorUint8) \
V(PPC_Word64AtomicXorUint16) \
V(PPC_Word64AtomicXorUint32) \
V(PPC_Word64AtomicXorUint64)
// Addressing modes represent the "shape" of inputs to an instruction.
// Many instructions support multiple addressing modes. Addressing modes
......
......@@ -135,6 +135,46 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kPPC_StoreToStackSlot:
return kHasSideEffect;
case kPPC_Word64AtomicLoadUint8:
case kPPC_Word64AtomicLoadUint16:
case kPPC_Word64AtomicLoadUint32:
case kPPC_Word64AtomicLoadUint64:
return kIsLoadOperation;
case kPPC_Word64AtomicStoreUint8:
case kPPC_Word64AtomicStoreUint16:
case kPPC_Word64AtomicStoreUint32:
case kPPC_Word64AtomicStoreUint64:
case kPPC_Word64AtomicExchangeUint8:
case kPPC_Word64AtomicExchangeUint16:
case kPPC_Word64AtomicExchangeUint32:
case kPPC_Word64AtomicExchangeUint64:
case kPPC_Word64AtomicCompareExchangeUint8:
case kPPC_Word64AtomicCompareExchangeUint16:
case kPPC_Word64AtomicCompareExchangeUint32:
case kPPC_Word64AtomicCompareExchangeUint64:
case kPPC_Word64AtomicAddUint8:
case kPPC_Word64AtomicAddUint16:
case kPPC_Word64AtomicAddUint32:
case kPPC_Word64AtomicAddUint64:
case kPPC_Word64AtomicSubUint8:
case kPPC_Word64AtomicSubUint16:
case kPPC_Word64AtomicSubUint32:
case kPPC_Word64AtomicSubUint64:
case kPPC_Word64AtomicAndUint8:
case kPPC_Word64AtomicAndUint16:
case kPPC_Word64AtomicAndUint32:
case kPPC_Word64AtomicAndUint64:
case kPPC_Word64AtomicOrUint8:
case kPPC_Word64AtomicOrUint16:
case kPPC_Word64AtomicOrUint32:
case kPPC_Word64AtomicOrUint64:
case kPPC_Word64AtomicXorUint8:
case kPPC_Word64AtomicXorUint16:
case kPPC_Word64AtomicXorUint32:
case kPPC_Word64AtomicXorUint64:
return kHasSideEffect;
#define CASE(Name) case k##Name:
COMMON_ARCH_OPCODE_LIST(CASE)
#undef CASE
......
......@@ -1956,6 +1956,33 @@ void InstructionSelector::VisitWord32AtomicLoad(Node* node) {
g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
}
void InstructionSelector::VisitWord64AtomicLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
PPCOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
ArchOpcode opcode = kArchNop;
switch (load_rep.representation()) {
case MachineRepresentation::kWord8:
opcode = kPPC_Word64AtomicLoadUint8;
break;
case MachineRepresentation::kWord16:
opcode = kPPC_Word64AtomicLoadUint16;
break;
case MachineRepresentation::kWord32:
opcode = kPPC_Word64AtomicLoadUint32;
break;
case MachineRepresentation::kWord64:
opcode = kPPC_Word64AtomicLoadUint64;
break;
default:
UNREACHABLE();
return;
}
Emit(opcode | AddressingModeField::encode(kMode_MRR),
g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
}
void InstructionSelector::VisitWord32AtomicStore(Node* node) {
MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
PPCOperandGenerator g(this);
......@@ -1987,11 +2014,60 @@ void InstructionSelector::VisitWord32AtomicStore(Node* node) {
0, nullptr, input_count, inputs);
}
void InstructionSelector::VisitWord32AtomicExchange(Node* node) {
void InstructionSelector::VisitWord64AtomicStore(Node* node) {
MachineRepresentation rep = AtomicStoreRepresentationOf(node->op());
PPCOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* value = node->InputAt(2);
ArchOpcode opcode = kArchNop;
switch (rep) {
case MachineRepresentation::kWord8:
opcode = kPPC_Word64AtomicStoreUint8;
break;
case MachineRepresentation::kWord16:
opcode = kPPC_Word64AtomicStoreUint16;
break;
case MachineRepresentation::kWord32:
opcode = kPPC_Word64AtomicStoreUint32;
break;
case MachineRepresentation::kWord64:
opcode = kPPC_Word64AtomicStoreUint64;
break;
default:
UNREACHABLE();
return;
}
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(value);
Emit(opcode | AddressingModeField::encode(kMode_MRR), 0, nullptr, input_count,
inputs);
}
void VisitAtomicExchange(InstructionSelector* selector, Node* node,
ArchOpcode opcode) {
PPCOperandGenerator g(selector);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* value = node->InputAt(2);
AddressingMode addressing_mode = kMode_MRR;
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);
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
selector->Emit(code, 1, outputs, input_count, inputs);
}
void InstructionSelector::VisitWord32AtomicExchange(Node* node) {
ArchOpcode opcode = kArchNop;
MachineType type = AtomicOpType(node->op());
if (type == MachineType::Int8()) {
......@@ -2008,26 +2084,53 @@ void InstructionSelector::VisitWord32AtomicExchange(Node* node) {
UNREACHABLE();
return;
}
VisitAtomicExchange(this, node, opcode);
}
void InstructionSelector::VisitWord64AtomicExchange(Node* node) {
ArchOpcode opcode = kArchNop;
MachineType type = AtomicOpType(node->op());
if (type == MachineType::Uint8()) {
opcode = kPPC_Word64AtomicExchangeUint8;
} else if (type == MachineType::Uint16()) {
opcode = kPPC_Word64AtomicExchangeUint16;
} else if (type == MachineType::Uint32()) {
opcode = kPPC_Word64AtomicExchangeUint32;
} else if (type == MachineType::Uint64()) {
opcode = kPPC_Word64AtomicExchangeUint64;
} else {
UNREACHABLE();
return;
}
VisitAtomicExchange(this, node, opcode);
}
void VisitAtomicCompareExchange(InstructionSelector* selector, Node* node,
ArchOpcode opcode) {
PPCOperandGenerator g(selector);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* old_value = node->InputAt(2);
Node* new_value = node->InputAt(3);
AddressingMode addressing_mode = kMode_MRR;
InstructionOperand inputs[3];
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
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(value);
inputs[input_count++] = g.UseUniqueRegister(old_value);
inputs[input_count++] = g.UseUniqueRegister(new_value);
InstructionOperand outputs[1];
outputs[0] = g.UseUniqueRegister(node);
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
Emit(code, 1, outputs, input_count, inputs);
size_t output_count = 0;
outputs[output_count++] = g.DefineAsRegister(node);
selector->Emit(code, output_count, outputs, input_count, inputs);
}
void InstructionSelector::VisitWord32AtomicCompareExchange(Node* node) {
PPCOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* old_value = node->InputAt(2);
Node* new_value = node->InputAt(3);
MachineType type = AtomicOpType(node->op());
ArchOpcode opcode = kArchNop;
if (type == MachineType::Int8()) {
......@@ -2044,31 +2147,53 @@ void InstructionSelector::VisitWord32AtomicCompareExchange(Node* node) {
UNREACHABLE();
return;
}
VisitAtomicCompareExchange(this, node, opcode);
}
void InstructionSelector::VisitWord64AtomicCompareExchange(Node* node) {
MachineType type = AtomicOpType(node->op());
ArchOpcode opcode = kArchNop;
if (type == MachineType::Uint8()) {
opcode = kPPC_Word64AtomicCompareExchangeUint8;
} else if (type == MachineType::Uint16()) {
opcode = kPPC_Word64AtomicCompareExchangeUint16;
} else if (type == MachineType::Uint32()) {
opcode = kPPC_Word64AtomicCompareExchangeUint32;
} else if (type == MachineType::Uint64()) {
opcode = kPPC_Word64AtomicCompareExchangeUint64;
} else {
UNREACHABLE();
return;
}
VisitAtomicCompareExchange(this, node, opcode);
}
void VisitAtomicBinaryOperation(InstructionSelector* selector, Node* node,
ArchOpcode opcode) {
PPCOperandGenerator g(selector);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* value = node->InputAt(2);
AddressingMode addressing_mode = kMode_MRR;
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
InstructionOperand inputs[3];
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);
inputs[input_count++] = g.UseUniqueRegister(value);
InstructionOperand outputs[1];
size_t output_count = 0;
outputs[output_count++] = g.DefineAsRegister(node);
Emit(code, output_count, outputs, input_count, inputs);
selector->Emit(code, output_count, outputs, input_count, inputs);
}
void InstructionSelector::VisitWord32AtomicBinaryOperation(
Node* node, ArchOpcode int8_op, ArchOpcode uint8_op, ArchOpcode int16_op,
ArchOpcode uint16_op, ArchOpcode word32_op) {
PPCOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
Node* value = node->InputAt(2);
MachineType type = AtomicOpType(node->op());
ArchOpcode opcode = kArchNop;
......@@ -2086,20 +2211,7 @@ void InstructionSelector::VisitWord32AtomicBinaryOperation(
UNREACHABLE();
return;
}
AddressingMode addressing_mode = kMode_MRR;
InstructionCode code = opcode | AddressingModeField::encode(addressing_mode);
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];
size_t output_count = 0;
outputs[output_count++] = g.DefineAsRegister(node);
Emit(code, output_count, outputs, input_count, inputs);
VisitAtomicBinaryOperation(this, node, opcode);
}
#define VISIT_ATOMIC_BINOP(op) \
......@@ -2116,6 +2228,39 @@ VISIT_ATOMIC_BINOP(Or)
VISIT_ATOMIC_BINOP(Xor)
#undef VISIT_ATOMIC_BINOP
void InstructionSelector::VisitWord64AtomicBinaryOperation(
Node* node, ArchOpcode uint8_op, ArchOpcode uint16_op, ArchOpcode uint32_op,
ArchOpcode uint64_op) {
MachineType type = AtomicOpType(node->op());
ArchOpcode opcode = kArchNop;
if (type == MachineType::Uint8()) {
opcode = uint8_op;
} else if (type == MachineType::Uint16()) {
opcode = uint16_op;
} else if (type == MachineType::Uint32()) {
opcode = uint32_op;
} else if (type == MachineType::Uint64()) {
opcode = uint64_op;
} else {
UNREACHABLE();
return;
}
VisitAtomicBinaryOperation(this, node, opcode);
}
#define VISIT_ATOMIC64_BINOP(op) \
void InstructionSelector::VisitWord64Atomic##op(Node* node) { \
VisitWord64AtomicBinaryOperation( \
node, kPPC_Word64Atomic##op##Uint8, kPPC_Word64Atomic##op##Uint16, \
kPPC_Word64Atomic##op##Uint32, kPPC_Word64Atomic##op##Uint64); \
}
VISIT_ATOMIC64_BINOP(Add)
VISIT_ATOMIC64_BINOP(Sub)
VISIT_ATOMIC64_BINOP(And)
VISIT_ATOMIC64_BINOP(Or)
VISIT_ATOMIC64_BINOP(Xor)
#undef VISIT_ATOMIC64_BINOP
void InstructionSelector::VisitInt32AbsWithOverflow(Node* node) {
UNREACHABLE();
......
......@@ -1201,13 +1201,15 @@ typedef uint32_t Instr;
/* Compare Logical */ \
V(cmpl, CMPL, 0x7C000040)
#define PPC_X_OPCODE_EH_S_FORM_LIST(V) \
/* Store Byte Conditional Indexed */ \
V(stbcx, STBCX, 0x7C00056D) \
/* Store Halfword Conditional Indexed Xform */ \
V(sthcx, STHCX, 0x7C0005AD) \
/* Store Word Conditional Indexed & record CR0 */ \
V(stwcx, STWCX, 0x7C00012D)
#define PPC_X_OPCODE_EH_S_FORM_LIST(V) \
/* Store Byte Conditional Indexed */ \
V(stbcx, STBCX, 0x7C00056D) \
/* Store Halfword Conditional Indexed Xform */ \
V(sthcx, STHCX, 0x7C0005AD) \
/* Store Word Conditional Indexed & record CR0 */ \
V(stwcx, STWCX, 0x7C00012D) \
/* Store Doubleword Conditional Indexed & record CR0 */ \
V(stdcx, STDCX, 0x7C0001AD)
#define PPC_X_OPCODE_EH_L_FORM_LIST(V) \
/* Load Byte And Reserve Indexed */ \
......@@ -1215,15 +1217,15 @@ typedef uint32_t Instr;
/* Load Halfword And Reserve Indexed Xform */ \
V(lharx, LHARX, 0x7C0000E8) \
/* Load Word and Reserve Indexed */ \
V(lwarx, LWARX, 0x7C000028)
V(lwarx, LWARX, 0x7C000028) \
/* Load Doubleword And Reserve Indexed */ \
V(ldarx, LDARX, 0x7C0000A8)
#define PPC_X_OPCODE_UNUSED_LIST(V) \
/* Bit Permute Doubleword */ \
V(bpermd, BPERMD, 0x7C0001F8) \
/* Extend Sign Word */ \
V(extsw, EXTSW, 0x7C0007B4) \
/* Load Doubleword And Reserve Indexed */ \
V(ldarx, LDARX, 0x7C0000A8) \
/* Load Word Algebraic with Update Indexed */ \
V(lwaux, LWAUX, 0x7C0002EA) \
/* Load Word Algebraic Indexed */ \
......@@ -1232,8 +1234,6 @@ typedef uint32_t Instr;
V(prtyd, PRTYD, 0x7C000174) \
/* Store Doubleword Byte-Reverse Indexed */ \
V(stdbrx, STDBRX, 0x7C000528) \
/* Store Doubleword Conditional Indexed & record CR0 */ \
V(stdcx, STDCX, 0x7C0001AD) \
/* Trap Doubleword */ \
V(td, TD, 0x7C000088) \
/* Branch Conditional to Branch Target Address Register */ \
......
......@@ -665,6 +665,10 @@ void Decoder::DecodeExt2(Instruction* instr) {
Format(instr, "stwcx 'rs, 'ra, 'rb");
return;
}
case STDCX: {
Format(instr, "stdcx 'rs, 'ra, 'rb");
return;
}
}
// ?? are all of these xo_form?
......@@ -898,6 +902,10 @@ void Decoder::DecodeExt2(Instruction* instr) {
Format(instr, "ldux 'rt, 'ra, 'rb");
return;
}
case LDARX: {
Format(instr, "ldarx 'rt, 'ra, 'rb");
return;
}
case STDX: {
Format(instr, "stdx 'rt, 'ra, 'rb");
return;
......
......@@ -870,6 +870,27 @@ void Simulator::TrashCallerSaveRegisters() {
#endif
}
int Simulator::WriteExDW(intptr_t addr, uint64_t value, Instruction* instr) {
base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
if (local_monitor_.NotifyStoreExcl(addr, TransactionSize::Word) &&
global_monitor_.Pointer()->NotifyStoreExcl_Locked(
addr, &global_monitor_processor_)) {
uint64_t* ptr = reinterpret_cast<uint64_t*>(addr);
*ptr = value;
return 0;
} else {
return 1;
}
}
uint64_t Simulator::ReadExDWU(intptr_t addr, Instruction* instr) {
base::LockGuard<base::Mutex> lock_guard(&global_monitor_.Pointer()->mutex);
local_monitor_.NotifyLoadExcl(addr, TransactionSize::Word);
global_monitor_.Pointer()->NotifyLoadExcl_Locked(addr,
&global_monitor_processor_);
uint64_t* ptr = reinterpret_cast<uint64_t*>(addr);
return *ptr;
}
uint32_t Simulator::ReadWU(intptr_t addr, Instruction* instr) {
// All supported PPC targets allow unaligned accesses, so we don't need to
......@@ -2320,6 +2341,16 @@ void Simulator::ExecuteGeneric(Instruction* instr) {
SetCR0(WriteExW(ra_val + rb_val, rs_val, instr));
break;
}
case STDCX: {
int rs = instr->RSValue();
int ra = instr->RAValue();
int rb = instr->RBValue();
intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
int64_t rs_val = get_register(rs);
intptr_t rb_val = get_register(rb);
SetCR0(WriteExDW(ra_val + rb_val, rs_val, instr));
break;
}
case TW: {
// used for call redirection in simulation mode
SoftwareInterrupt(instr);
......@@ -3087,6 +3118,15 @@ void Simulator::ExecuteGeneric(Instruction* instr) {
set_register(rt, ReadExWU(ra_val + rb_val, instr));
break;
}
case LDARX: {
int rt = instr->RTValue();
int ra = instr->RAValue();
int rb = instr->RBValue();
intptr_t ra_val = ra == 0 ? 0 : get_register(ra);
intptr_t rb_val = get_register(rb);
set_register(rt, ReadExDWU(ra_val + rb_val, instr));
break;
}
case DCBF: {
// todo - simulate dcbf
break;
......
......@@ -265,6 +265,8 @@ class Simulator : public SimulatorBase {
intptr_t* ReadDW(intptr_t addr);
void WriteDW(intptr_t addr, int64_t value);
inline int WriteExDW(intptr_t addr, uint64_t value, Instruction* instr);
inline uint64_t ReadExDWU(intptr_t addr, Instruction* instr);
void Trace(Instruction* instr);
void SetCR0(intptr_t result, bool setSO = false);
......
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