Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -272,6 +272,11 @@ uint64_t Address, const void *Decoder); +static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSimm16(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1014,6 +1019,27 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int64_t Offset = SignExtend64<9>((Insn >> 7) & 0x1ff); + unsigned Rt = fieldFromInstruction(Insn, 16, 5); + unsigned Base = fieldFromInstruction(Insn, 21, 5); + + Rt = getReg(Decoder, Mips::GPR32RegClassID, Rt); + Base = getReg(Decoder, Mips::GPR32RegClassID, Base); + + if(Inst.getOpcode() == Mips::SC_R6 || Inst.getOpcode() == Mips::SCD_R6){ + Inst.addOperand(MCOperand::CreateReg(Rt)); + } + + Inst.addOperand(MCOperand::CreateReg(Rt)); + Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::CreateImm(Offset)); + + return MCDisassembler::Success; +} static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst, unsigned RegNo, Index: lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -203,6 +203,7 @@ case Mips::LWC1: case Mips::LDC1: case Mips::LL: + case Mips::LL_R6: case Mips::LWL: case Mips::LWR: *AddrIdx = 1; @@ -223,6 +224,7 @@ // Store instructions with base address register in position 2. case Mips::SC: + case Mips::SC_R6: *AddrIdx = 2; if (IsStore) *IsStore = true; Index: lib/Target/Mips/Mips32r6InstrFormats.td =================================================================== --- lib/Target/Mips/Mips32r6InstrFormats.td +++ lib/Target/Mips/Mips32r6InstrFormats.td @@ -39,6 +39,7 @@ def OPGROUP_PCREL : OPGROUP<0b111011>; def OPGROUP_REGIMM : OPGROUP<0b000001>; def OPGROUP_SPECIAL : OPGROUP<0b000000>; +// The spec occasionally names this value LL, LLD, SC, or SCD. def OPGROUP_SPECIAL3 : OPGROUP<0b011111>; // The spec names this constant LWC2, LDC2, SWC2, and SDC2 in different places. def OPGROUP_COP2LDST : OPGROUP<0b010010>; @@ -84,6 +85,12 @@ def OPCODE6_JALR : OPCODE6<0b001001>; def OPCODE6_CACHE : OPCODE6<0b100101>; def OPCODE6_PREF : OPCODE6<0b110101>; +// The next four constants are unnamed in the spec. These names are taken from +// the OPGROUP names they are used with. +def OPCODE6_LL : OPCODE6<0b110110>; +def OPCODE6_LLD : OPCODE6<0b110111>; +def OPCODE6_SC : OPCODE6<0b100110>; +def OPCODE6_SCD : OPCODE6<0b100111>; class FIELD_FMT Val> { bits<5> Value = Val; @@ -411,6 +418,23 @@ let Inst{5-0} = Operation.Value; } +class SPECIAL3_LL_SC_FM : MipsR6Inst { + bits<5> rt; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<9> offset = addr{8-0}; + + bits<32> Inst; + + let Inst{31-26} = OPGROUP_SPECIAL3.Value; + let Inst{25-21} = base; + let Inst{20-16} = rt; + let Inst{15-7} = offset; + let Inst{5-0} = Operation.Value; + + string DecoderMethod = "DecodeSpecial3LlSc"; +} + class REGIMM_FM : MipsR6Inst { bits<5> rs; bits<16> imm; Index: lib/Target/Mips/Mips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips32r6InstrInfo.td +++ lib/Target/Mips/Mips32r6InstrInfo.td @@ -18,7 +18,6 @@ // Reencoded: clo, clz // Reencoded: jr -> jalr // Reencoded: jr.hb -> jalr.hb -// Reencoded: ll, sc // Reencoded: sdbbp def brtarget21 : Operand { @@ -152,6 +151,9 @@ class SDC2_R6_ENC : COP2LDST_FM; class SWC2_R6_ENC : COP2LDST_FM; +class LL_R6_ENC : SPECIAL3_LL_SC_FM; +class SC_R6_ENC : SPECIAL3_LL_SC_FM; + class CMP_CONDN_DESC_BASE { @@ -555,6 +557,27 @@ class SDC2_R6_DESC : COP2ST_DESC_BASE<"sdc2", COP2Opnd>; class SWC2_R6_DESC : COP2ST_DESC_BASE<"swc2", COP2Opnd>; +class LL_R6_DESC_BASE { + dag OutOperandList = (outs GPROpnd:$rt); + dag InOperandList = (ins mem_simm9:$addr); + string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); + list Pattern = []; + bit mayLoad = 1; +} + +class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd>; + +class SC_R6_DESC_BASE { + dag OutOperandList = (outs GPROpnd:$dst); + dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); + string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); + list Pattern = []; + bit mayStore = 1; + string Constraints = "$rt = $dst"; +} + +class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -605,6 +628,7 @@ def JIC : JIC_ENC, JIC_DESC, ISA_MIPS32R6; def JR_HB_R6 : JR_HB_R6_ENC, JR_HB_R6_DESC, ISA_MIPS32R6; def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6; +def LL_R6 : LL_R6_ENC, LL_R6_DESC, ISA_MIPS32R6; // def LSA; // See MSA def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6; def LWPC : LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; @@ -631,6 +655,7 @@ def PREF_R6 : PREF_ENC, PREF_DESC, ISA_MIPS32R6; def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6; def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6; +def SC_R6 : SC_R6_ENC, SC_R6_DESC, ISA_MIPS32R6; def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6; def SELEQZ : SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32; def SELEQZ_D : SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6; Index: lib/Target/Mips/Mips64InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64InstrInfo.td +++ lib/Target/Mips/Mips64InstrInfo.td @@ -167,8 +167,8 @@ ISA_MIPS3_NOT_32R6_64R6; /// Load-linked, Store-conditional -def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3; -def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3; +def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3_NOT_32R6_64R6; +def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6; /// Jump and Branch Instructions let isCodeGenOnly = 1 in { Index: lib/Target/Mips/Mips64r6InstrInfo.td =================================================================== --- lib/Target/Mips/Mips64r6InstrInfo.td +++ lib/Target/Mips/Mips64r6InstrInfo.td @@ -13,7 +13,6 @@ // Notes about removals/changes from MIPS32r6: // Reencoded: dclo, dclz -// Reencoded: lld, scd //===----------------------------------------------------------------------===// // @@ -35,6 +34,8 @@ class DMUL_R6_ENC : SPECIAL_3R_FM<0b00010, 0b111000>; class DMULU_ENC : SPECIAL_3R_FM<0b00010, 0b111001>; class LDPC_ENC : PCREL18_FM; +class LLD_R6_ENC : SPECIAL3_LL_SC_FM; +class SCD_R6_ENC : SPECIAL3_LL_SC_FM; //===----------------------------------------------------------------------===// // @@ -63,7 +64,8 @@ class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, mul>; class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd>; class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3>; - +class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd>; +class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd>; class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>; class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>; @@ -88,6 +90,8 @@ def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6; def DMULU: DMULU_ENC, DMULU_DESC, ISA_MIPS64R6; def LDPC: LDPC_ENC, LDPC_DESC, ISA_MIPS64R6; +def LLD_R6 : LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS32R6; +def SCD_R6 : SCD_R6_ENC, SCD_R6_DESC, ISA_MIPS32R6; let DecoderNamespace = "Mips32r6_64r6_GP64" in { def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64; def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64; Index: lib/Target/Mips/MipsISelLowering.h =================================================================== --- lib/Target/Mips/MipsISelLowering.h +++ lib/Target/Mips/MipsISelLowering.h @@ -598,6 +598,12 @@ unsigned getJumpTableEncoding() const override; + /// Emit a sign-extension using sll/sra, seb, or seh appropriately. + MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr *MI, + MachineBasicBlock *BB, + unsigned Size, unsigned DstReg, + unsigned SrcRec) const; + MachineBasicBlock *emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, bool Nand = false) const; MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr *MI, Index: lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- lib/Target/Mips/MipsISelLowering.cpp +++ lib/Target/Mips/MipsISelLowering.cpp @@ -958,16 +958,20 @@ unsigned LL, SC, AND, NOR, ZERO, BEQ; if (Size == 4) { - LL = isMicroMips ? Mips::LL_MM : Mips::LL; - SC = isMicroMips ? Mips::SC_MM : Mips::SC; + if (isMicroMips) { + LL = Mips::LL_MM; + SC = Mips::SC_MM; + } else { + LL = Subtarget->hasMips32r6() ? Mips::LL : Mips::LL_R6; + SC = Subtarget->hasMips32r6() ? Mips::SC : Mips::SC_R6; + } AND = Mips::AND; NOR = Mips::NOR; ZERO = Mips::ZERO; BEQ = Mips::BEQ; - } - else { - LL = Mips::LLD; - SC = Mips::SCD; + } else { + LL = Subtarget->hasMips64r6() ? Mips::LLD : Mips::LLD_R6; + SC = Subtarget->hasMips64r6() ? Mips::SCD : Mips::SCD_R6; AND = Mips::AND64; NOR = Mips::NOR64; ZERO = Mips::ZERO_64; @@ -1029,11 +1033,39 @@ return exitMBB; } -MachineBasicBlock * -MipsTargetLowering::emitAtomicBinaryPartword(MachineInstr *MI, - MachineBasicBlock *BB, - unsigned Size, unsigned BinOpcode, - bool Nand) const { +MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( + MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, + unsigned SrcReg) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + + if (Subtarget->hasMips32r2() && Size == 1) { + BuildMI(BB, DL, TII->get(Mips::SEB), DstReg).addReg(SrcReg); + return BB; + } + + if (Subtarget->hasMips32r2() && Size == 2) { + BuildMI(BB, DL, TII->get(Mips::SEH), DstReg).addReg(SrcReg); + return BB; + } + + MachineFunction *MF = BB->getParent(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetRegisterClass *RC = getRegClassFor(MVT::i32); + unsigned ScrReg = RegInfo.createVirtualRegister(RC); + + assert(Size < 32); + int64_t ShiftImm = 32 - (Size * 8); + + BuildMI(BB, DL, TII->get(Mips::SLL), ScrReg).addReg(SrcReg).addImm(ShiftImm); + BuildMI(BB, DL, TII->get(Mips::SRA), DstReg).addReg(ScrReg).addImm(ShiftImm); + + return BB; +} + +MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( + MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, + bool Nand) const { assert((Size == 1 || Size == 2) && "Unsupported size for EmitAtomicBinaryPartial."); @@ -1063,7 +1095,6 @@ unsigned StoreVal = RegInfo.createVirtualRegister(RC); unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC); unsigned SrlRes = RegInfo.createVirtualRegister(RC); - unsigned SllRes = RegInfo.createVirtualRegister(RC); unsigned Success = RegInfo.createVirtualRegister(RC); // insert new blocks after the current block @@ -1169,19 +1200,14 @@ // sinkMBB: // and maskedoldval1,oldval,mask // srl srlres,maskedoldval1,shiftamt - // sll sllres,srlres,24 - // sra dest,sllres,24 + // sign_extend dest,srlres BB = sinkMBB; - int64_t ShiftImm = (Size == 1) ? 24 : 16; BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1) .addReg(OldVal).addReg(Mask); BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes) .addReg(MaskedOldVal1).addReg(ShiftAmt); - BuildMI(BB, DL, TII->get(Mips::SLL), SllRes) - .addReg(SrlRes).addImm(ShiftImm); - BuildMI(BB, DL, TII->get(Mips::SRA), Dest) - .addReg(SllRes).addImm(ShiftImm); + BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); MI->eraseFromParent(); // The instruction is gone now. @@ -1302,7 +1328,6 @@ unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC); unsigned StoreVal = RegInfo.createVirtualRegister(RC); unsigned SrlRes = RegInfo.createVirtualRegister(RC); - unsigned SllRes = RegInfo.createVirtualRegister(RC); unsigned Success = RegInfo.createVirtualRegister(RC); // insert new blocks after the current block @@ -1399,17 +1424,12 @@ // sinkMBB: // srl srlres,maskedoldval0,shiftamt - // sll sllres,srlres,24 - // sra dest,sllres,24 + // sign_extend dest,srlres BB = sinkMBB; - int64_t ShiftImm = (Size == 1) ? 24 : 16; BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes) .addReg(MaskedOldVal0).addReg(ShiftAmt); - BuildMI(BB, DL, TII->get(Mips::SLL), SllRes) - .addReg(SrlRes).addImm(ShiftImm); - BuildMI(BB, DL, TII->get(Mips::SRA), Dest) - .addReg(SllRes).addImm(ShiftImm); + BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); MI->eraseFromParent(); // The instruction is gone now. Index: lib/Target/Mips/MipsInstrInfo.td =================================================================== --- lib/Target/Mips/MipsInstrInfo.td +++ lib/Target/Mips/MipsInstrInfo.td @@ -1187,8 +1187,8 @@ def WAIT : WAIT_FT<"wait">, WAIT_FM; /// Load-linked, Store-conditional -def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2; -def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2; +def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2_NOT_32R6_64R6; +def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2_NOT_32R6_64R6; } /// Jump and Branch Instructions Index: lib/Target/Mips/MipsSubtarget.h =================================================================== --- lib/Target/Mips/MipsSubtarget.h +++ lib/Target/Mips/MipsSubtarget.h @@ -161,7 +161,7 @@ bool hasMips32() const { return MipsArchVersion >= Mips32; } bool hasMips32r2() const { return MipsArchVersion == Mips32r2 || MipsArchVersion == Mips32r6 || - MipsArchVersion == Mips64r2; + MipsArchVersion == Mips64r2 || MipsArchVersion == Mips64r6; } bool hasMips32r6() const { return MipsArchVersion == Mips32r6 || MipsArchVersion == Mips64r6; Index: test/CodeGen/Mips/atomic.ll =================================================================== --- test/CodeGen/Mips/atomic.ll +++ test/CodeGen/Mips/atomic.ll @@ -1,5 +1,14 @@ -; RUN: llc -march=mipsel --disable-machine-licm < %s | FileCheck %s -check-prefix=ALL -check-prefix=CHECK-EL -; RUN: llc -march=mips --disable-machine-licm < %s | FileCheck %s -check-prefix=ALL -check-prefix=CHECK-EB +; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL +; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL +; RUN: llc -march=mipsel --disable-machine-licm -mcpu=mips32r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL +; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips4 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL +; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=NO-SEB-SEH -check-prefix=CHECK-EL +; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r2 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL +; RUN: llc -march=mips64el --disable-machine-licm -mcpu=mips64r6 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS64-ANY -check-prefix=HAS-SEB-SEH -check-prefix=CHECK-EL + +; Keep one big-endian check so that we don't reduce testing, but don't add more +; since endianness doesn't affect the body of the atomic operations. +; RUN: llc -march=mips --disable-machine-licm -mcpu=mips32 < %s | FileCheck %s -check-prefix=ALL -check-prefix=MIPS32-ANY -check-prefix=CHECK-EB @x = common global i32 0, align 4 @@ -10,7 +19,9 @@ ; ALL-LABEL: AtomicLoadAdd32: -; ALL: lw $[[R0:[0-9]+]], %got(x) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( + ; ALL: $[[BB0:[A-Z_0-9]+]]: ; ALL: ll $[[R1:[0-9]+]], 0($[[R0]]) ; ALL: addu $[[R2:[0-9]+]], $[[R1]], $4 @@ -25,7 +36,9 @@ ; ALL-LABEL: AtomicLoadNand32: -; ALL: lw $[[R0:[0-9]+]], %got(x) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( + ; ALL: $[[BB0:[A-Z_0-9]+]]: ; ALL: ll $[[R1:[0-9]+]], 0($[[R0]]) ; ALL: and $[[R3:[0-9]+]], $[[R1]], $4 @@ -44,7 +57,9 @@ ; ALL-LABEL: AtomicSwap32: -; ALL: lw $[[R0:[0-9]+]], %got(x) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x) + ; ALL: $[[BB0:[A-Z_0-9]+]]: ; ALL: ll ${{[0-9]+}}, 0($[[R0]]) ; ALL: sc $[[R2:[0-9]+]], 0($[[R0]]) @@ -61,7 +76,9 @@ ; ALL-LABEL: AtomicCmpSwap32: -; ALL: lw $[[R0:[0-9]+]], %got(x) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( + ; ALL: $[[BB0:[A-Z_0-9]+]]: ; ALL: ll $2, 0($[[R0]]) ; ALL: bne $2, $4, $[[BB1:[A-Z_0-9]+]] @@ -81,7 +98,9 @@ ; ALL-LABEL: AtomicLoadAdd8: -; ALL: lw $[[R0:[0-9]+]], %got(y) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( + ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 @@ -104,8 +123,11 @@ ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] -; ALL: sll $[[R17:[0-9]+]], $[[R16]], 24 -; ALL: sra $2, $[[R17]], 24 + +; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 +; NO-SEB-SEH: sra $2, $[[R17]], 24 + +; HAS-SEB-SEH: seb $2, $[[R16]] } define signext i8 @AtomicLoadSub8(i8 signext %incr) nounwind { @@ -115,7 +137,9 @@ ; ALL-LABEL: AtomicLoadSub8: -; ALL: lw $[[R0:[0-9]+]], %got(y) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( + ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 @@ -138,8 +162,11 @@ ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] -; ALL: sll $[[R17:[0-9]+]], $[[R16]], 24 -; ALL: sra $2, $[[R17]], 24 + +; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 +; NO-SEB-SEH: sra $2, $[[R17]], 24 + +; HAS-SEB-SEH:seb $2, $[[R16]] } define signext i8 @AtomicLoadNand8(i8 signext %incr) nounwind { @@ -149,7 +176,9 @@ ; ALL-LABEL: AtomicLoadNand8: -; ALL: lw $[[R0:[0-9]+]], %got(y) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( + ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 @@ -173,8 +202,11 @@ ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] -; ALL: sll $[[R17:[0-9]+]], $[[R16]], 24 -; ALL: sra $2, $[[R17]], 24 + +; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 +; NO-SEB-SEH: sra $2, $[[R17]], 24 + +; HAS-SEB-SEH: seb $2, $[[R16]] } define signext i8 @AtomicSwap8(i8 signext %newval) nounwind { @@ -184,7 +216,9 @@ ; ALL-LABEL: AtomicSwap8: -; ALL: lw $[[R0:[0-9]+]], %got(y) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( + ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 @@ -206,8 +240,11 @@ ; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] ; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] -; ALL: sll $[[R17:[0-9]+]], $[[R16]], 24 -; ALL: sra $2, $[[R17]], 24 + +; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 24 +; NO-SEB-SEH: sra $2, $[[R17]], 24 + +; HAS-SEB-SEH: seb $2, $[[R16]] } define signext i8 @AtomicCmpSwap8(i8 signext %oldval, i8 signext %newval) nounwind { @@ -217,7 +254,9 @@ ; ALL-LABEL: AtomicCmpSwap8: -; ALL: lw $[[R0:[0-9]+]], %got(y) +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(y) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(y)( + ; ALL: addiu $[[R1:[0-9]+]], $zero, -4 ; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] ; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 @@ -244,10 +283,56 @@ ; ALL: $[[BB1]]: ; ALL: srlv $[[R17:[0-9]+]], $[[R14]], $[[R5]] -; ALL: sll $[[R18:[0-9]+]], $[[R17]], 24 -; ALL: sra $2, $[[R18]], 24 + +; NO-SEB-SEH: sll $[[R18:[0-9]+]], $[[R17]], 24 +; NO-SEB-SEH: sra $2, $[[R18]], 24 + +; HAS-SEB-SEH: seb $2, $[[R17]] } +; Check one i16 so that we cover the seh sign extend +@z = common global i16 0, align 1 + +define signext i16 @AtomicLoadAdd16(i16 signext %incr) nounwind { +entry: + %0 = atomicrmw add i16* @z, i16 %incr monotonic + ret i16 %0 + +; ALL-LABEL: AtomicLoadAdd16: + +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(z) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(z)( + +; ALL: addiu $[[R1:[0-9]+]], $zero, -4 +; ALL: and $[[R2:[0-9]+]], $[[R0]], $[[R1]] +; ALL: andi $[[R3:[0-9]+]], $[[R0]], 3 +; CHECK-EB: xori $[[R4:[0-9]+]], $[[R3]], 2 +; CHECK-EB: sll $[[R5:[0-9]+]], $[[R4]], 3 +; CHECK-EL: sll $[[R5:[0-9]+]], $[[R3]], 3 +; ALL: ori $[[R6:[0-9]+]], $zero, 65535 +; ALL: sllv $[[R7:[0-9]+]], $[[R6]], $[[R5]] +; ALL: nor $[[R8:[0-9]+]], $zero, $[[R7]] +; ALL: sllv $[[R9:[0-9]+]], $4, $[[R5]] + +; ALL: $[[BB0:[A-Z_0-9]+]]: +; ALL: ll $[[R10:[0-9]+]], 0($[[R2]]) +; ALL: addu $[[R11:[0-9]+]], $[[R10]], $[[R9]] +; ALL: and $[[R12:[0-9]+]], $[[R11]], $[[R7]] +; ALL: and $[[R13:[0-9]+]], $[[R10]], $[[R8]] +; ALL: or $[[R14:[0-9]+]], $[[R13]], $[[R12]] +; ALL: sc $[[R14]], 0($[[R2]]) +; ALL: beqz $[[R14]], $[[BB0]] + +; ALL: and $[[R15:[0-9]+]], $[[R10]], $[[R7]] +; ALL: srlv $[[R16:[0-9]+]], $[[R15]], $[[R5]] + +; NO-SEB-SEH: sll $[[R17:[0-9]+]], $[[R16]], 16 +; NO-SEB-SEH: sra $2, $[[R17]], 16 + +; MIPS32R2: seh $2, $[[R16]] +} + + @countsint = common global i32 0, align 4 define i32 @CheckSync(i32 %v) nounwind noinline { @@ -280,3 +365,23 @@ %conv = zext i1 %1 to i32 ret i32 %conv } + +; Check that MIPS32R6 has the correct offset range. +; FIXME: At the moment, we don't seem to do addr+offset for any atomic load/store. +define i32 @AtomicLoadAdd32_OffGt9Bit(i32 %incr) nounwind { +entry: + %0 = atomicrmw add i32* getelementptr(i32* @x, i32 256), i32 %incr monotonic + ret i32 %0 + +; ALL-LABEL: AtomicLoadAdd32_OffGt9Bit: + +; MIPS32-ANY: lw $[[R0:[0-9]+]], %got(x) +; MIPS64-ANY: ld $[[R0:[0-9]+]], %got_disp(x)( + +; ALL: addiu $[[PTR:[0-9]+]], $[[R0]], 1024 +; ALL: $[[BB0:[A-Z_0-9]+]]: +; ALL: ll $[[R1:[0-9]+]], 0($[[PTR]]) +; ALL: addu $[[R2:[0-9]+]], $[[R1]], $4 +; ALL: sc $[[R2]], 0($[[PTR]]) +; ALL: beqz $[[R2]], $[[BB0]] +} Index: test/MC/Disassembler/Mips/mips32r6.txt =================================================================== --- test/MC/Disassembler/Mips/mips32r6.txt +++ test/MC/Disassembler/Mips/mips32r6.txt @@ -117,3 +117,5 @@ 0x00 0x80 0x04 0x09 # CHECK: jr.hb $4 0x00 0x80 0xfc 0x09 # CHECK: jalr.hb $4 0x00 0xa0 0x24 0x09 # CHECK: jalr.hb $4, $5 +0x7e 0x42 0xb3 0xb6 # CHECK: ll $2, -153($18) +0x7e 0x6f 0xec 0x26 # CHECK: sc $15, -40($19) Index: test/MC/Disassembler/Mips/mips64r6.txt =================================================================== --- test/MC/Disassembler/Mips/mips64r6.txt +++ test/MC/Disassembler/Mips/mips64r6.txt @@ -131,3 +131,7 @@ 0x00 0x80 0x04 0x09 # CHECK: jr.hb $4 0x00 0x80 0xfc 0x09 # CHECK: jalr.hb $4 0x00 0xa0 0x24 0x09 # CHECK: jalr.hb $4, $5 +0x7e 0x42 0xb3 0xb6 # CHECK: ll $2, -153($18) +0x7f 0xe0 0x38 0x37 # CHECK: lld $zero, 112($ra) +0x7e 0x6f 0xec 0x26 # CHECK: sc $15, -40($19) +0x7f 0xaf 0xe6 0xa7 # CHECK: scd $15, -51($sp) Index: test/MC/Mips/mips2/valid.s =================================================================== --- test/MC/Mips/mips2/valid.s +++ test/MC/Mips/mips2/valid.s @@ -49,7 +49,7 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] lw $8,5674($a1) lwc1 $f16,10225($k0) lwc2 $18,-841($a2) # CHECK: lwc2 $18, -841($6) # encoding: [0xc8,0xd2,0xfc,0xb7] @@ -84,7 +84,7 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] sdc3 $12,5835($10) Index: test/MC/Mips/mips3/valid.s =================================================================== --- test/MC/Mips/mips3/valid.s +++ test/MC/Mips/mips3/valid.s @@ -99,8 +99,8 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) - lld $zero,-14736($ra) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] + lld $zero,-14736($ra) # CHECK: lld $zero, -14736($ra) # encoding: [0xd3,0xe0,0xc6,0x70] lw $8,5674($a1) lwc1 $f16,10225($k0) lwc2 $18,-841($a2) # CHECK: lwc2 $18, -841($6) # encoding: [0xc8,0xd2,0xfc,0xb7] @@ -139,8 +139,8 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) - scd $15,-8243($sp) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] + scd $15,-8243($sp) # CHECK: scd $15, -8243($sp) # encoding: [0xf3,0xaf,0xdf,0xcd] sd $12,5835($10) sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] Index: test/MC/Mips/mips32/valid.s =================================================================== --- test/MC/Mips/mips32/valid.s +++ test/MC/Mips/mips32/valid.s @@ -55,7 +55,7 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] lw $8,5674($a1) lwc1 $f16,10225($k0) lwc2 $18,-841($a2) # CHECK: lwc2 $18, -841($6) # encoding: [0xc8,0xd2,0xfc,0xb7] @@ -111,7 +111,7 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] sh $14,-6704($15) Index: test/MC/Mips/mips32r2/valid.s =================================================================== --- test/MC/Mips/mips32r2/valid.s +++ test/MC/Mips/mips32r2/valid.s @@ -63,7 +63,7 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] luxc1 $f19,$s6($s5) lw $8,5674($a1) lwc1 $f16,10225($k0) @@ -136,7 +136,7 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] sdxc1 $f11,$10($14) Index: test/MC/Mips/mips32r6/valid.s =================================================================== --- test/MC/Mips/mips32r6/valid.s +++ test/MC/Mips/mips32r6/valid.s @@ -134,3 +134,5 @@ lwc2 $18,-841($a2) # CHECK: lwc2 $18, -841($6) # encoding: [0x49,0x52,0x34,0xb7] sdc2 $20,629($s2) # CHECK: sdc2 $20, 629($18) # encoding: [0x49,0xf4,0x92,0x75] swc2 $25,304($s0) # CHECK: swc2 $25, 304($16) # encoding: [0x49,0x79,0x81,0x30] + ll $v0,-153($s2) # CHECK: ll $2, -153($18) # encoding: [0x7e,0x42,0xb3,0xb6] + sc $15,-40($s3) # CHECK: sc $15, -40($19) # encoding: [0x7e,0x6f,0xec,0x26] Index: test/MC/Mips/mips4/valid.s =================================================================== --- test/MC/Mips/mips4/valid.s +++ test/MC/Mips/mips4/valid.s @@ -102,8 +102,8 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) - lld $zero,-14736($ra) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] + lld $zero,-14736($ra) # CHECK: lld $zero, -14736($ra) # encoding: [0xd3,0xe0,0xc6,0x70] lw $8,5674($a1) lwc1 $f16,10225($k0) lwc2 $18,-841($a2) # CHECK: lwc2 $18, -841($6) # encoding: [0xc8,0xd2,0xfc,0xb7] @@ -156,8 +156,8 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) - scd $15,-8243($sp) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] + scd $15,-8243($sp) # CHECK: scd $15, -8243($sp) # encoding: [0xf3,0xaf,0xdf,0xcd] sd $12,5835($10) sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] Index: test/MC/Mips/mips5/valid.s =================================================================== --- test/MC/Mips/mips5/valid.s +++ test/MC/Mips/mips5/valid.s @@ -102,8 +102,8 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) - lld $zero,-14736($ra) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] + lld $zero,-14736($ra) # CHECK: lld $zero, -14736($ra) # encoding: [0xd3,0xe0,0xc6,0x70] luxc1 $f19,$s6($s5) lw $8,5674($a1) lwc1 $f16,10225($k0) @@ -157,8 +157,8 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) - scd $15,-8243($sp) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] + scd $15,-8243($sp) # CHECK: scd $15, -8243($sp) # encoding: [0xf3,0xaf,0xdf,0xcd] sd $12,5835($10) sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] Index: test/MC/Mips/mips64/valid.s =================================================================== --- test/MC/Mips/mips64/valid.s +++ test/MC/Mips/mips64/valid.s @@ -107,8 +107,8 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) - lld $zero,-14736($ra) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] + lld $zero,-14736($ra) # CHECK: lld $zero, -14736($ra) # encoding: [0xd3,0xe0,0xc6,0x70] luxc1 $f19,$s6($s5) lw $8,5674($a1) lwc1 $f16,10225($k0) @@ -171,8 +171,8 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) - scd $15,-8243($sp) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] + scd $15,-8243($sp) # CHECK: scd $15, -8243($sp) # encoding: [0xf3,0xaf,0xdf,0xcd] sd $12,5835($10) sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] Index: test/MC/Mips/mips64r2/valid.s =================================================================== --- test/MC/Mips/mips64r2/valid.s +++ test/MC/Mips/mips64r2/valid.s @@ -121,8 +121,8 @@ lhu $s3,-22851($v0) li $at,-29773 li $zero,-29889 - ll $v0,-7321($s2) - lld $zero,-14736($ra) + ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67] + lld $zero,-14736($ra) # CHECK: lld $zero, -14736($ra) # encoding: [0xd3,0xe0,0xc6,0x70] luxc1 $f19,$s6($s5) lw $8,5674($a1) lwc1 $f16,10225($k0) @@ -196,8 +196,8 @@ round.w.d $f6,$f4 round.w.s $f27,$f28 sb $s6,-19857($14) - sc $15,18904($s3) - scd $15,-8243($sp) + sc $15,18904($s3) # CHECK: sc $15, 18904($19) # encoding: [0xe2,0x6f,0x49,0xd8] + scd $15,-8243($sp) # CHECK: scd $15, -8243($sp) # encoding: [0xf3,0xaf,0xdf,0xcd] sd $12,5835($10) sdc1 $f31,30574($13) sdc2 $20,23157($s2) # CHECK: sdc2 $20, 23157($18) # encoding: [0xfa,0x54,0x5a,0x75] Index: test/MC/Mips/mips64r6/valid.s =================================================================== --- test/MC/Mips/mips64r6/valid.s +++ test/MC/Mips/mips64r6/valid.s @@ -148,3 +148,7 @@ lwc2 $18,-841($a2) # CHECK: lwc2 $18, -841($6) # encoding: [0x49,0x52,0x34,0xb7] sdc2 $20,629($s2) # CHECK: sdc2 $20, 629($18) # encoding: [0x49,0xf4,0x92,0x75] swc2 $25,304($s0) # CHECK: swc2 $25, 304($16) # encoding: [0x49,0x79,0x81,0x30] + ll $v0,-153($s2) # CHECK: ll $2, -153($18) # encoding: [0x7e,0x42,0xb3,0xb6] + lld $zero,112($ra) # CHECK: lld $zero, 112($ra) # encoding: [0x7f,0xe0,0x38,0x37] + sc $15,-40($s3) # CHECK: sc $15, -40($19) # encoding: [0x7e,0x6f,0xec,0x26] + scd $15,-51($sp) # CHECK: scd $15, -51($sp) # encoding: [0x7f,0xaf,0xe6,0xa7]