mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
64-bit atomic instructions.
llvm-svn: 144372
This commit is contained in:
parent
40d8c440ad
commit
3b1457c21d
@ -81,6 +81,28 @@ class Mult64<bits<6> func, string instr_asm, InstrItinClass itin>:
|
||||
class Div64<SDNode op, bits<6> func, string instr_asm, InstrItinClass itin>:
|
||||
Div<op, func, instr_asm, itin, CPU64Regs, [HI64, LO64]>;
|
||||
|
||||
multiclass Atomic2Ops64<PatFrag Op, string Opstr> {
|
||||
def #NAME# : Atomic2Ops<Op, Opstr, CPU64Regs, CPURegs>, Requires<[NotN64]>;
|
||||
def _P8 : Atomic2Ops<Op, Opstr, CPU64Regs, CPU64Regs>, Requires<[IsN64]>;
|
||||
}
|
||||
|
||||
multiclass AtomicCmpSwap64<PatFrag Op, string Width> {
|
||||
def #NAME# : AtomicCmpSwap<Op, Width, CPU64Regs, CPURegs>, Requires<[NotN64]>;
|
||||
def _P8 : AtomicCmpSwap<Op, Width, CPU64Regs, CPU64Regs>,
|
||||
Requires<[IsN64]>;
|
||||
}
|
||||
|
||||
let usesCustomInserter = 1, Predicates = [HasMips64] in {
|
||||
defm ATOMIC_LOAD_ADD_I64 : Atomic2Ops64<atomic_load_add_64, "load_add_64">;
|
||||
defm ATOMIC_LOAD_SUB_I64 : Atomic2Ops64<atomic_load_sub_64, "load_sub_64">;
|
||||
defm ATOMIC_LOAD_AND_I64 : Atomic2Ops64<atomic_load_and_64, "load_and_64">;
|
||||
defm ATOMIC_LOAD_OR_I64 : Atomic2Ops64<atomic_load_or_64, "load_or_64">;
|
||||
defm ATOMIC_LOAD_XOR_I64 : Atomic2Ops64<atomic_load_xor_64, "load_xor_64">;
|
||||
defm ATOMIC_LOAD_NAND_I64 : Atomic2Ops64<atomic_load_nand_64, "load_nand_64">;
|
||||
defm ATOMIC_SWAP_I64 : Atomic2Ops64<atomic_swap_64, "swap_64">;
|
||||
defm ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap64<atomic_cmp_swap_64, "64">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction definition
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -146,6 +168,12 @@ defm USW64 : StoreM64<0x2b, "usw", truncstorei32_u, 1>;
|
||||
defm ULD : LoadM64<0x37, "uld", load_u, 1>;
|
||||
defm USD : StoreM64<0x3f, "usd", store_u, 1>;
|
||||
|
||||
/// Load-linked, Store-conditional
|
||||
def LLD : LLBase<0x34, "lld", CPU64Regs, mem>, Requires<[NotN64]>;
|
||||
def LLD_P8 : LLBase<0x34, "lld", CPU64Regs, mem64>, Requires<[IsN64]>;
|
||||
def SCD : SCBase<0x3c, "scd", CPU64Regs, mem>, Requires<[NotN64]>;
|
||||
def SCD_P8 : SCBase<0x3c, "scd", CPU64Regs, mem64>, Requires<[IsN64]>;
|
||||
|
||||
/// Jump and Branch Instructions
|
||||
def JAL64 : JumpLink64<0x03, "jal">;
|
||||
def JALR64 : JumpLinkReg64<0x00, 0x09, "jalr">;
|
||||
|
@ -794,60 +794,108 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
assert(false && "Unexpected instr type to insert");
|
||||
return NULL;
|
||||
case Mips::ATOMIC_LOAD_ADD_I8:
|
||||
case Mips::ATOMIC_LOAD_ADD_I8_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu);
|
||||
case Mips::ATOMIC_LOAD_ADD_I16:
|
||||
case Mips::ATOMIC_LOAD_ADD_I16_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::ADDu);
|
||||
case Mips::ATOMIC_LOAD_ADD_I32:
|
||||
case Mips::ATOMIC_LOAD_ADD_I32_P8:
|
||||
return EmitAtomicBinary(MI, BB, 4, Mips::ADDu);
|
||||
case Mips::ATOMIC_LOAD_ADD_I64:
|
||||
case Mips::ATOMIC_LOAD_ADD_I64_P8:
|
||||
return EmitAtomicBinary(MI, BB, 8, Mips::DADDu);
|
||||
|
||||
case Mips::ATOMIC_LOAD_AND_I8:
|
||||
case Mips::ATOMIC_LOAD_AND_I8_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::AND);
|
||||
case Mips::ATOMIC_LOAD_AND_I16:
|
||||
case Mips::ATOMIC_LOAD_AND_I16_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::AND);
|
||||
case Mips::ATOMIC_LOAD_AND_I32:
|
||||
case Mips::ATOMIC_LOAD_AND_I32_P8:
|
||||
return EmitAtomicBinary(MI, BB, 4, Mips::AND);
|
||||
case Mips::ATOMIC_LOAD_AND_I64:
|
||||
case Mips::ATOMIC_LOAD_AND_I64_P8:
|
||||
return EmitAtomicBinary(MI, BB, 48, Mips::AND64);
|
||||
|
||||
case Mips::ATOMIC_LOAD_OR_I8:
|
||||
case Mips::ATOMIC_LOAD_OR_I8_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::OR);
|
||||
case Mips::ATOMIC_LOAD_OR_I16:
|
||||
case Mips::ATOMIC_LOAD_OR_I16_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::OR);
|
||||
case Mips::ATOMIC_LOAD_OR_I32:
|
||||
case Mips::ATOMIC_LOAD_OR_I32_P8:
|
||||
return EmitAtomicBinary(MI, BB, 4, Mips::OR);
|
||||
case Mips::ATOMIC_LOAD_OR_I64:
|
||||
case Mips::ATOMIC_LOAD_OR_I64_P8:
|
||||
return EmitAtomicBinary(MI, BB, 8, Mips::OR64);
|
||||
|
||||
case Mips::ATOMIC_LOAD_XOR_I8:
|
||||
case Mips::ATOMIC_LOAD_XOR_I8_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::XOR);
|
||||
case Mips::ATOMIC_LOAD_XOR_I16:
|
||||
case Mips::ATOMIC_LOAD_XOR_I16_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::XOR);
|
||||
case Mips::ATOMIC_LOAD_XOR_I32:
|
||||
case Mips::ATOMIC_LOAD_XOR_I32_P8:
|
||||
return EmitAtomicBinary(MI, BB, 4, Mips::XOR);
|
||||
case Mips::ATOMIC_LOAD_XOR_I64:
|
||||
case Mips::ATOMIC_LOAD_XOR_I64_P8:
|
||||
return EmitAtomicBinary(MI, BB, 8, Mips::XOR64);
|
||||
|
||||
case Mips::ATOMIC_LOAD_NAND_I8:
|
||||
case Mips::ATOMIC_LOAD_NAND_I8_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 1, 0, true);
|
||||
case Mips::ATOMIC_LOAD_NAND_I16:
|
||||
case Mips::ATOMIC_LOAD_NAND_I16_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 2, 0, true);
|
||||
case Mips::ATOMIC_LOAD_NAND_I32:
|
||||
case Mips::ATOMIC_LOAD_NAND_I32_P8:
|
||||
return EmitAtomicBinary(MI, BB, 4, 0, true);
|
||||
case Mips::ATOMIC_LOAD_NAND_I64:
|
||||
case Mips::ATOMIC_LOAD_NAND_I64_P8:
|
||||
return EmitAtomicBinary(MI, BB, 8, 0, true);
|
||||
|
||||
case Mips::ATOMIC_LOAD_SUB_I8:
|
||||
case Mips::ATOMIC_LOAD_SUB_I8_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 1, Mips::SUBu);
|
||||
case Mips::ATOMIC_LOAD_SUB_I16:
|
||||
case Mips::ATOMIC_LOAD_SUB_I16_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 2, Mips::SUBu);
|
||||
case Mips::ATOMIC_LOAD_SUB_I32:
|
||||
case Mips::ATOMIC_LOAD_SUB_I32_P8:
|
||||
return EmitAtomicBinary(MI, BB, 4, Mips::SUBu);
|
||||
case Mips::ATOMIC_LOAD_SUB_I64:
|
||||
case Mips::ATOMIC_LOAD_SUB_I64_P8:
|
||||
return EmitAtomicBinary(MI, BB, 8, Mips::DSUBu);
|
||||
|
||||
case Mips::ATOMIC_SWAP_I8:
|
||||
case Mips::ATOMIC_SWAP_I8_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 1, 0);
|
||||
case Mips::ATOMIC_SWAP_I16:
|
||||
case Mips::ATOMIC_SWAP_I16_P8:
|
||||
return EmitAtomicBinaryPartword(MI, BB, 2, 0);
|
||||
case Mips::ATOMIC_SWAP_I32:
|
||||
case Mips::ATOMIC_SWAP_I32_P8:
|
||||
return EmitAtomicBinary(MI, BB, 4, 0);
|
||||
case Mips::ATOMIC_SWAP_I64:
|
||||
case Mips::ATOMIC_SWAP_I64_P8:
|
||||
return EmitAtomicBinary(MI, BB, 8, 0);
|
||||
|
||||
case Mips::ATOMIC_CMP_SWAP_I8:
|
||||
case Mips::ATOMIC_CMP_SWAP_I8_P8:
|
||||
return EmitAtomicCmpSwapPartword(MI, BB, 1);
|
||||
case Mips::ATOMIC_CMP_SWAP_I16:
|
||||
case Mips::ATOMIC_CMP_SWAP_I16_P8:
|
||||
return EmitAtomicCmpSwapPartword(MI, BB, 2);
|
||||
case Mips::ATOMIC_CMP_SWAP_I32:
|
||||
case Mips::ATOMIC_CMP_SWAP_I32_P8:
|
||||
return EmitAtomicCmpSwap(MI, BB, 4);
|
||||
case Mips::ATOMIC_CMP_SWAP_I64:
|
||||
case Mips::ATOMIC_CMP_SWAP_I64_P8:
|
||||
return EmitAtomicCmpSwap(MI, BB, 8);
|
||||
}
|
||||
}
|
||||
|
||||
@ -857,13 +905,31 @@ MachineBasicBlock *
|
||||
MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
|
||||
unsigned Size, unsigned BinOpcode,
|
||||
bool Nand) const {
|
||||
assert(Size == 4 && "Unsupported size for EmitAtomicBinary.");
|
||||
assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicBinary.");
|
||||
|
||||
MachineFunction *MF = BB->getParent();
|
||||
MachineRegisterInfo &RegInfo = MF->getRegInfo();
|
||||
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
|
||||
const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8));
|
||||
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
|
||||
DebugLoc dl = MI->getDebugLoc();
|
||||
unsigned LL, SC, AND, NOR, ZERO, BEQ;
|
||||
|
||||
if (Size == 4) {
|
||||
LL = IsN64 ? Mips::LL_P8 : Mips::LL;
|
||||
SC = IsN64 ? Mips::SC_P8 : Mips::SC;
|
||||
AND = Mips::AND;
|
||||
NOR = Mips::NOR;
|
||||
ZERO = Mips::ZERO;
|
||||
BEQ = Mips::BEQ;
|
||||
}
|
||||
else {
|
||||
LL = IsN64 ? Mips::LLD_P8 : Mips::LLD;
|
||||
SC = IsN64 ? Mips::SCD_P8 : Mips::SCD;
|
||||
AND = Mips::AND64;
|
||||
NOR = Mips::NOR64;
|
||||
ZERO = Mips::ZERO_64;
|
||||
BEQ = Mips::BEQ64;
|
||||
}
|
||||
|
||||
unsigned OldVal = MI->getOperand(0).getReg();
|
||||
unsigned Ptr = MI->getOperand(1).getReg();
|
||||
@ -901,23 +967,20 @@ MipsTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
|
||||
// sc success, storeval, 0(ptr)
|
||||
// beq success, $0, loopMBB
|
||||
BB = loopMBB;
|
||||
BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(Ptr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(LL), OldVal).addReg(Ptr).addImm(0);
|
||||
if (Nand) {
|
||||
// and andres, oldval, incr
|
||||
// nor storeval, $0, andres
|
||||
BuildMI(BB, dl, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr);
|
||||
BuildMI(BB, dl, TII->get(Mips::NOR), StoreVal)
|
||||
.addReg(Mips::ZERO).addReg(AndRes);
|
||||
BuildMI(BB, dl, TII->get(AND), AndRes).addReg(OldVal).addReg(Incr);
|
||||
BuildMI(BB, dl, TII->get(NOR), StoreVal).addReg(ZERO).addReg(AndRes);
|
||||
} else if (BinOpcode) {
|
||||
// <binop> storeval, oldval, incr
|
||||
BuildMI(BB, dl, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr);
|
||||
} else {
|
||||
StoreVal = Incr;
|
||||
}
|
||||
BuildMI(BB, dl, TII->get(Mips::SC), Success)
|
||||
.addReg(StoreVal).addReg(Ptr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(Mips::BEQ))
|
||||
.addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB);
|
||||
BuildMI(BB, dl, TII->get(SC), Success).addReg(StoreVal).addReg(Ptr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(BEQ)).addReg(Success).addReg(ZERO).addMBB(loopMBB);
|
||||
|
||||
MI->eraseFromParent(); // The instruction is gone now.
|
||||
|
||||
@ -937,6 +1000,8 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI,
|
||||
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
|
||||
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
|
||||
DebugLoc dl = MI->getDebugLoc();
|
||||
unsigned LL = IsN64 ? Mips::LL_P8 : Mips::LL;
|
||||
unsigned SC = IsN64 ? Mips::SC_P8 : Mips::SC;
|
||||
|
||||
unsigned Dest = MI->getOperand(0).getReg();
|
||||
unsigned Ptr = MI->getOperand(1).getReg();
|
||||
@ -1028,7 +1093,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI,
|
||||
// beq success,$0,loopMBB
|
||||
|
||||
BB = loopMBB;
|
||||
BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0);
|
||||
if (Nand) {
|
||||
// and andres, oldval, incr2
|
||||
// nor binopres, $0, andres
|
||||
@ -1051,7 +1116,7 @@ MipsTargetLowering::EmitAtomicBinaryPartword(MachineInstr *MI,
|
||||
.addReg(OldVal).addReg(Mask2);
|
||||
BuildMI(BB, dl, TII->get(Mips::OR), StoreVal)
|
||||
.addReg(MaskedOldVal0).addReg(NewVal);
|
||||
BuildMI(BB, dl, TII->get(Mips::SC), Success)
|
||||
BuildMI(BB, dl, TII->get(SC), Success)
|
||||
.addReg(StoreVal).addReg(AlignedAddr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(Mips::BEQ))
|
||||
.addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB);
|
||||
@ -1082,13 +1147,29 @@ MachineBasicBlock *
|
||||
MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
|
||||
MachineBasicBlock *BB,
|
||||
unsigned Size) const {
|
||||
assert(Size == 4 && "Unsupported size for EmitAtomicCmpSwap.");
|
||||
assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicCmpSwap.");
|
||||
|
||||
MachineFunction *MF = BB->getParent();
|
||||
MachineRegisterInfo &RegInfo = MF->getRegInfo();
|
||||
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
|
||||
const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8));
|
||||
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
|
||||
DebugLoc dl = MI->getDebugLoc();
|
||||
unsigned LL, SC, ZERO, BNE, BEQ;
|
||||
|
||||
if (Size == 4) {
|
||||
LL = IsN64 ? Mips::LL_P8 : Mips::LL;
|
||||
SC = IsN64 ? Mips::SC_P8 : Mips::SC;
|
||||
ZERO = Mips::ZERO;
|
||||
BNE = Mips::BNE;
|
||||
BEQ = Mips::BEQ;
|
||||
}
|
||||
else {
|
||||
LL = IsN64 ? Mips::LLD_P8 : Mips::LLD;
|
||||
SC = IsN64 ? Mips::SCD_P8 : Mips::SCD;
|
||||
ZERO = Mips::ZERO_64;
|
||||
BNE = Mips::BNE64;
|
||||
BEQ = Mips::BEQ64;
|
||||
}
|
||||
|
||||
unsigned Dest = MI->getOperand(0).getReg();
|
||||
unsigned Ptr = MI->getOperand(1).getReg();
|
||||
@ -1127,18 +1208,18 @@ MipsTargetLowering::EmitAtomicCmpSwap(MachineInstr *MI,
|
||||
// ll dest, 0(ptr)
|
||||
// bne dest, oldval, exitMBB
|
||||
BB = loop1MBB;
|
||||
BuildMI(BB, dl, TII->get(Mips::LL), Dest).addReg(Ptr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(Mips::BNE))
|
||||
BuildMI(BB, dl, TII->get(LL), Dest).addReg(Ptr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(BNE))
|
||||
.addReg(Dest).addReg(OldVal).addMBB(exitMBB);
|
||||
|
||||
// loop2MBB:
|
||||
// sc success, newval, 0(ptr)
|
||||
// beq success, $0, loop1MBB
|
||||
BB = loop2MBB;
|
||||
BuildMI(BB, dl, TII->get(Mips::SC), Success)
|
||||
BuildMI(BB, dl, TII->get(SC), Success)
|
||||
.addReg(NewVal).addReg(Ptr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(Mips::BEQ))
|
||||
.addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB);
|
||||
BuildMI(BB, dl, TII->get(BEQ))
|
||||
.addReg(Success).addReg(ZERO).addMBB(loop1MBB);
|
||||
|
||||
MI->eraseFromParent(); // The instruction is gone now.
|
||||
|
||||
@ -1157,6 +1238,8 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI,
|
||||
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
|
||||
const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
|
||||
DebugLoc dl = MI->getDebugLoc();
|
||||
unsigned LL = IsN64 ? Mips::LL_P8 : Mips::LL;
|
||||
unsigned SC = IsN64 ? Mips::SC_P8 : Mips::SC;
|
||||
|
||||
unsigned Dest = MI->getOperand(0).getReg();
|
||||
unsigned Ptr = MI->getOperand(1).getReg();
|
||||
@ -1247,7 +1330,7 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI,
|
||||
// and maskedoldval0,oldval,mask
|
||||
// bne maskedoldval0,shiftedcmpval,sinkMBB
|
||||
BB = loop1MBB;
|
||||
BuildMI(BB, dl, TII->get(Mips::LL), OldVal).addReg(AlignedAddr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(Mips::AND), MaskedOldVal0)
|
||||
.addReg(OldVal).addReg(Mask);
|
||||
BuildMI(BB, dl, TII->get(Mips::BNE))
|
||||
@ -1263,7 +1346,7 @@ MipsTargetLowering::EmitAtomicCmpSwapPartword(MachineInstr *MI,
|
||||
.addReg(OldVal).addReg(Mask2);
|
||||
BuildMI(BB, dl, TII->get(Mips::OR), StoreVal)
|
||||
.addReg(MaskedOldVal1).addReg(ShiftedNewVal);
|
||||
BuildMI(BB, dl, TII->get(Mips::SC), Success)
|
||||
BuildMI(BB, dl, TII->get(SC), Success)
|
||||
.addReg(StoreVal).addReg(AlignedAddr).addImm(0);
|
||||
BuildMI(BB, dl, TII->get(Mips::BEQ))
|
||||
.addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB);
|
||||
|
@ -594,20 +594,41 @@ class ExtIns<bits<6> _funct, string instr_asm, dag outs, dag ins,
|
||||
}
|
||||
|
||||
// Atomic instructions with 2 source operands (ATOMIC_SWAP & ATOMIC_LOAD_*).
|
||||
class Atomic2Ops<PatFrag Op, string Opstr> :
|
||||
MipsPseudo<(outs CPURegs:$dst), (ins CPURegs:$ptr, CPURegs:$incr),
|
||||
class Atomic2Ops<PatFrag Op, string Opstr, RegisterClass DRC,
|
||||
RegisterClass PRC> :
|
||||
MipsPseudo<(outs DRC:$dst), (ins PRC:$ptr, DRC:$incr),
|
||||
!strconcat("atomic_", Opstr, "\t$dst, $ptr, $incr"),
|
||||
[(set CPURegs:$dst,
|
||||
(Op CPURegs:$ptr, CPURegs:$incr))]>;
|
||||
[(set DRC:$dst, (Op PRC:$ptr, DRC:$incr))]>;
|
||||
|
||||
multiclass Atomic2Ops32<PatFrag Op, string Opstr> {
|
||||
def #NAME# : Atomic2Ops<Op, Opstr, CPURegs, CPURegs>, Requires<[NotN64]>;
|
||||
def _P8 : Atomic2Ops<Op, Opstr, CPURegs, CPU64Regs>, Requires<[IsN64]>;
|
||||
}
|
||||
|
||||
// Atomic Compare & Swap.
|
||||
class AtomicCmpSwap<PatFrag Op, string Width> :
|
||||
MipsPseudo<(outs CPURegs:$dst),
|
||||
(ins CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap),
|
||||
!strconcat("atomic_cmp_swap_", Width,
|
||||
"\t$dst, $ptr, $cmp, $swap"),
|
||||
[(set CPURegs:$dst,
|
||||
(Op CPURegs:$ptr, CPURegs:$cmp, CPURegs:$swap))]>;
|
||||
class AtomicCmpSwap<PatFrag Op, string Width, RegisterClass DRC,
|
||||
RegisterClass PRC> :
|
||||
MipsPseudo<(outs DRC:$dst), (ins PRC:$ptr, DRC:$cmp, DRC:$swap),
|
||||
!strconcat("atomic_cmp_swap_", Width, "\t$dst, $ptr, $cmp, $swap"),
|
||||
[(set DRC:$dst, (Op PRC:$ptr, DRC:$cmp, DRC:$swap))]>;
|
||||
|
||||
multiclass AtomicCmpSwap32<PatFrag Op, string Width> {
|
||||
def #NAME# : AtomicCmpSwap<Op, Width, CPURegs, CPURegs>, Requires<[NotN64]>;
|
||||
def _P8 : AtomicCmpSwap<Op, Width, CPURegs, CPU64Regs>, Requires<[IsN64]>;
|
||||
}
|
||||
|
||||
class LLBase<bits<6> Opc, string opstring, RegisterClass RC, Operand Mem> :
|
||||
FMem<Opc, (outs RC:$rt), (ins Mem:$addr),
|
||||
!strconcat(opstring, "\t$rt, $addr"), [], IILoad> {
|
||||
let mayLoad = 1;
|
||||
}
|
||||
|
||||
class SCBase<bits<6> Opc, string opstring, RegisterClass RC, Operand Mem> :
|
||||
FMem<Opc, (outs RC:$dst), (ins RC:$rt, Mem:$addr),
|
||||
!strconcat(opstring, "\t$rt, $addr"), [], IIStore> {
|
||||
let mayStore = 1;
|
||||
let Constraints = "$rt = $dst";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Pseudo instructions
|
||||
@ -643,32 +664,32 @@ def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
|
||||
def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc", []>;
|
||||
|
||||
let usesCustomInserter = 1 in {
|
||||
def ATOMIC_LOAD_ADD_I8 : Atomic2Ops<atomic_load_add_8, "load_add_8">;
|
||||
def ATOMIC_LOAD_ADD_I16 : Atomic2Ops<atomic_load_add_16, "load_add_16">;
|
||||
def ATOMIC_LOAD_ADD_I32 : Atomic2Ops<atomic_load_add_32, "load_add_32">;
|
||||
def ATOMIC_LOAD_SUB_I8 : Atomic2Ops<atomic_load_sub_8, "load_sub_8">;
|
||||
def ATOMIC_LOAD_SUB_I16 : Atomic2Ops<atomic_load_sub_16, "load_sub_16">;
|
||||
def ATOMIC_LOAD_SUB_I32 : Atomic2Ops<atomic_load_sub_32, "load_sub_32">;
|
||||
def ATOMIC_LOAD_AND_I8 : Atomic2Ops<atomic_load_and_8, "load_and_8">;
|
||||
def ATOMIC_LOAD_AND_I16 : Atomic2Ops<atomic_load_and_16, "load_and_16">;
|
||||
def ATOMIC_LOAD_AND_I32 : Atomic2Ops<atomic_load_and_32, "load_and_32">;
|
||||
def ATOMIC_LOAD_OR_I8 : Atomic2Ops<atomic_load_or_8, "load_or_8">;
|
||||
def ATOMIC_LOAD_OR_I16 : Atomic2Ops<atomic_load_or_16, "load_or_16">;
|
||||
def ATOMIC_LOAD_OR_I32 : Atomic2Ops<atomic_load_or_32, "load_or_32">;
|
||||
def ATOMIC_LOAD_XOR_I8 : Atomic2Ops<atomic_load_xor_8, "load_xor_8">;
|
||||
def ATOMIC_LOAD_XOR_I16 : Atomic2Ops<atomic_load_xor_16, "load_xor_16">;
|
||||
def ATOMIC_LOAD_XOR_I32 : Atomic2Ops<atomic_load_xor_32, "load_xor_32">;
|
||||
def ATOMIC_LOAD_NAND_I8 : Atomic2Ops<atomic_load_nand_8, "load_nand_8">;
|
||||
def ATOMIC_LOAD_NAND_I16 : Atomic2Ops<atomic_load_nand_16, "load_nand_16">;
|
||||
def ATOMIC_LOAD_NAND_I32 : Atomic2Ops<atomic_load_nand_32, "load_nand_32">;
|
||||
defm ATOMIC_LOAD_ADD_I8 : Atomic2Ops32<atomic_load_add_8, "load_add_8">;
|
||||
defm ATOMIC_LOAD_ADD_I16 : Atomic2Ops32<atomic_load_add_16, "load_add_16">;
|
||||
defm ATOMIC_LOAD_ADD_I32 : Atomic2Ops32<atomic_load_add_32, "load_add_32">;
|
||||
defm ATOMIC_LOAD_SUB_I8 : Atomic2Ops32<atomic_load_sub_8, "load_sub_8">;
|
||||
defm ATOMIC_LOAD_SUB_I16 : Atomic2Ops32<atomic_load_sub_16, "load_sub_16">;
|
||||
defm ATOMIC_LOAD_SUB_I32 : Atomic2Ops32<atomic_load_sub_32, "load_sub_32">;
|
||||
defm ATOMIC_LOAD_AND_I8 : Atomic2Ops32<atomic_load_and_8, "load_and_8">;
|
||||
defm ATOMIC_LOAD_AND_I16 : Atomic2Ops32<atomic_load_and_16, "load_and_16">;
|
||||
defm ATOMIC_LOAD_AND_I32 : Atomic2Ops32<atomic_load_and_32, "load_and_32">;
|
||||
defm ATOMIC_LOAD_OR_I8 : Atomic2Ops32<atomic_load_or_8, "load_or_8">;
|
||||
defm ATOMIC_LOAD_OR_I16 : Atomic2Ops32<atomic_load_or_16, "load_or_16">;
|
||||
defm ATOMIC_LOAD_OR_I32 : Atomic2Ops32<atomic_load_or_32, "load_or_32">;
|
||||
defm ATOMIC_LOAD_XOR_I8 : Atomic2Ops32<atomic_load_xor_8, "load_xor_8">;
|
||||
defm ATOMIC_LOAD_XOR_I16 : Atomic2Ops32<atomic_load_xor_16, "load_xor_16">;
|
||||
defm ATOMIC_LOAD_XOR_I32 : Atomic2Ops32<atomic_load_xor_32, "load_xor_32">;
|
||||
defm ATOMIC_LOAD_NAND_I8 : Atomic2Ops32<atomic_load_nand_8, "load_nand_8">;
|
||||
defm ATOMIC_LOAD_NAND_I16 : Atomic2Ops32<atomic_load_nand_16, "load_nand_16">;
|
||||
defm ATOMIC_LOAD_NAND_I32 : Atomic2Ops32<atomic_load_nand_32, "load_nand_32">;
|
||||
|
||||
def ATOMIC_SWAP_I8 : Atomic2Ops<atomic_swap_8, "swap_8">;
|
||||
def ATOMIC_SWAP_I16 : Atomic2Ops<atomic_swap_16, "swap_16">;
|
||||
def ATOMIC_SWAP_I32 : Atomic2Ops<atomic_swap_32, "swap_32">;
|
||||
defm ATOMIC_SWAP_I8 : Atomic2Ops32<atomic_swap_8, "swap_8">;
|
||||
defm ATOMIC_SWAP_I16 : Atomic2Ops32<atomic_swap_16, "swap_16">;
|
||||
defm ATOMIC_SWAP_I32 : Atomic2Ops32<atomic_swap_32, "swap_32">;
|
||||
|
||||
def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap<atomic_cmp_swap_8, "8">;
|
||||
def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, "16">;
|
||||
def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, "32">;
|
||||
defm ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap32<atomic_cmp_swap_8, "8">;
|
||||
defm ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap32<atomic_cmp_swap_16, "16">;
|
||||
defm ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap32<atomic_cmp_swap_32, "32">;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -745,12 +766,10 @@ def SYNC : MipsInst<(outs), (ins i32imm:$stype), "sync $stype",
|
||||
}
|
||||
|
||||
/// Load-linked, Store-conditional
|
||||
let mayLoad = 1 in
|
||||
def LL : FMem<0x30, (outs CPURegs:$rt), (ins mem:$addr),
|
||||
"ll\t$rt, $addr", [], IILoad>;
|
||||
let mayStore = 1, Constraints = "$rt = $dst" in
|
||||
def SC : FMem<0x38, (outs CPURegs:$dst), (ins CPURegs:$rt, mem:$addr),
|
||||
"sc\t$rt, $addr", [], IIStore>;
|
||||
def LL : LLBase<0x30, "ll", CPURegs, mem>, Requires<[NotN64]>;
|
||||
def LL_P8 : LLBase<0x30, "ll", CPURegs, mem64>, Requires<[IsN64]>;
|
||||
def SC : SCBase<0x38, "sc", CPURegs, mem>, Requires<[NotN64]>;
|
||||
def SC_P8 : SCBase<0x38, "sc", CPURegs, mem64>, Requires<[IsN64]>;
|
||||
|
||||
/// Jump and Branch Instructions
|
||||
def J : JumpFJ<0x02, "j">;
|
||||
|
Loading…
Reference in New Issue
Block a user