diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 6acdcd4bef0..a51f0168a9e 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -1701,6 +1701,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(UDIVREM32); OPCODE(UDIVREM64); OPCODE(MVC); + OPCODE(CLC); OPCODE(ATOMIC_SWAPW); OPCODE(ATOMIC_LOADW_ADD); OPCODE(ATOMIC_LOADW_SUB); diff --git a/lib/Target/SystemZ/SystemZISelLowering.h b/lib/Target/SystemZ/SystemZISelLowering.h index c0dbe493c0f..4098ff34b38 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.h +++ b/lib/Target/SystemZ/SystemZISelLowering.h @@ -80,6 +80,10 @@ namespace SystemZISD { // MachineMemOperands rather than one. MVC, + // Use CLC to compare two blocks of memory, with the same comments + // as for MVC. + CLC, + // Wrappers around the inner loop of an 8- or 16-bit ATOMIC_SWAP or // ATOMIC_LOAD_. // diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index 2af8e83aed5..2d18e03eb50 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -1386,3 +1386,22 @@ class AtomicLoadWBinaryReg : AtomicLoadWBinary; class AtomicLoadWBinaryImm : AtomicLoadWBinary; + +// Define an instruction that operates on two fixed-length blocks of memory. +// The real instruction uses a bdladdr12onlylen8 for the first operand and a +// bdaddr12only for the second, with the length of the second operand being +// implicitly the same as the first. This arrangement matches the underlying +// assembly syntax. However, for instruction selection it's easier to have +// two normal bdaddr12onlys and a separate length operand, so define a pseudo +// instruction for that too. +multiclass MemorySS opcode, + SDPatternOperator operator> { + def "" : InstSS; + let usesCustomInserter = 1 in + def Wrapper : Pseudo<(outs), (ins bdaddr12only:$dest, bdaddr12only:$src, + imm32len8:$length), + [(operator bdaddr12only:$dest, bdaddr12only:$src, + imm32len8:$length)]>; +} diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 5371e8ad4db..a7181d68a7f 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -334,15 +334,7 @@ def MVGHI : StoreSIL<"mvghi", 0xE548, store, imm64sx16>; // Memory-to-memory moves. let mayLoad = 1, mayStore = 1 in - def MVC : InstSS<0xD2, (outs), (ins bdladdr12onlylen8:$BDL1, - bdaddr12only:$BD2), - "mvc\t$BDL1, $BD2", []>; - -let mayLoad = 1, mayStore = 1, usesCustomInserter = 1 in - def MVCWrapper : Pseudo<(outs), (ins bdaddr12only:$dest, bdaddr12only:$src, - imm32len8:$length), - [(z_mvc bdaddr12only:$dest, bdaddr12only:$src, - imm32len8:$length)]>; + defm MVC : MemorySS<"mvc", 0xD2, z_mvc>; defm LoadStore8_32 : MVCLoadStore; @@ -1000,6 +992,10 @@ let Defs = [CC], CCValues = 0xE, IsLogical = 1 in { } defm : ZXB; +// Memory-to-memory comparison. +let mayLoad = 1, Defs = [CC] in + defm CLC : MemorySS<"clc", 0xD5, z_clc>; + //===----------------------------------------------------------------------===// // Atomic operations //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZOperators.td b/lib/Target/SystemZ/SystemZOperators.td index 6a3af2b8905..dae04de02b7 100644 --- a/lib/Target/SystemZ/SystemZOperators.td +++ b/lib/Target/SystemZ/SystemZOperators.td @@ -54,7 +54,7 @@ def SDT_ZAtomicCmpSwapW : SDTypeProfile<1, 6, SDTCisVT<4, i32>, SDTCisVT<5, i32>, SDTCisVT<6, i32>]>; -def SDT_ZCopy : SDTypeProfile<0, 3, +def SDT_ZMemMemLength : SDTypeProfile<0, 3, [SDTCisPtrTy<0>, SDTCisPtrTy<1>, SDTCisVT<2, i32>]>; @@ -109,8 +109,10 @@ def z_atomic_loadw_umin : AtomicWOp<"ATOMIC_LOADW_UMIN">; def z_atomic_loadw_umax : AtomicWOp<"ATOMIC_LOADW_UMAX">; def z_atomic_cmp_swapw : AtomicWOp<"ATOMIC_CMP_SWAPW", SDT_ZAtomicCmpSwapW>; -def z_mvc : SDNode<"SystemZISD::MVC", SDT_ZCopy, +def z_mvc : SDNode<"SystemZISD::MVC", SDT_ZMemMemLength, [SDNPHasChain, SDNPMayStore, SDNPMayLoad]>; +def z_clc : SDNode<"SystemZISD::CLC", SDT_ZMemMemLength, + [SDNPHasChain, SDNPMayLoad]>; //===----------------------------------------------------------------------===// // Pattern fragments diff --git a/test/MC/Disassembler/SystemZ/insns.txt b/test/MC/Disassembler/SystemZ/insns.txt index 97e41fee121..f76c83a1252 100644 --- a/test/MC/Disassembler/SystemZ/insns.txt +++ b/test/MC/Disassembler/SystemZ/insns.txt @@ -1333,6 +1333,42 @@ # CHECK: chy %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x79 +# CHECK: clc 0(1), 0 +0xd5 0x00 0x00 0x00 0x00 0x00 + +# CHECK: clc 0(1), 0(%r1) +0xd5 0x00 0x00 0x00 0x10 0x00 + +# CHECK: clc 0(1), 0(%r15) +0xd5 0x00 0x00 0x00 0xf0 0x00 + +# CHECK: clc 0(1), 4095 +0xd5 0x00 0x00 0x00 0x0f 0xff + +# CHECK: clc 0(1), 4095(%r1) +0xd5 0x00 0x00 0x00 0x1f 0xff + +# CHECK: clc 0(1), 4095(%r15) +0xd5 0x00 0x00 0x00 0xff 0xff + +# CHECK: clc 0(1,%r1), 0 +0xd5 0x00 0x10 0x00 0x00 0x00 + +# CHECK: clc 0(1,%r15), 0 +0xd5 0x00 0xf0 0x00 0x00 0x00 + +# CHECK: clc 4095(1,%r1), 0 +0xd5 0x00 0x1f 0xff 0x00 0x00 + +# CHECK: clc 4095(1,%r15), 0 +0xd5 0x00 0xff 0xff 0x00 0x00 + +# CHECK: clc 0(256,%r1), 0 +0xd5 0xff 0x10 0x00 0x00 0x00 + +# CHECK: clc 0(256,%r15), 0 +0xd5 0xff 0xf0 0x00 0x00 0x00 + # CHECK: clfhsi 0, 0 0xe5 0x5d 0x00 0x00 0x00 0x00 @@ -4444,6 +4480,42 @@ # CHECK: msy %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x51 +# CHECK: mvc 0(1), 0 +0xd2 0x00 0x00 0x00 0x00 0x00 + +# CHECK: mvc 0(1), 0(%r1) +0xd2 0x00 0x00 0x00 0x10 0x00 + +# CHECK: mvc 0(1), 0(%r15) +0xd2 0x00 0x00 0x00 0xf0 0x00 + +# CHECK: mvc 0(1), 4095 +0xd2 0x00 0x00 0x00 0x0f 0xff + +# CHECK: mvc 0(1), 4095(%r1) +0xd2 0x00 0x00 0x00 0x1f 0xff + +# CHECK: mvc 0(1), 4095(%r15) +0xd2 0x00 0x00 0x00 0xff 0xff + +# CHECK: mvc 0(1,%r1), 0 +0xd2 0x00 0x10 0x00 0x00 0x00 + +# CHECK: mvc 0(1,%r15), 0 +0xd2 0x00 0xf0 0x00 0x00 0x00 + +# CHECK: mvc 4095(1,%r1), 0 +0xd2 0x00 0x1f 0xff 0x00 0x00 + +# CHECK: mvc 4095(1,%r15), 0 +0xd2 0x00 0xff 0xff 0x00 0x00 + +# CHECK: mvc 0(256,%r1), 0 +0xd2 0xff 0x10 0x00 0x00 0x00 + +# CHECK: mvc 0(256,%r15), 0 +0xd2 0xff 0xf0 0x00 0x00 0x00 + # CHECK: mvghi 0, 0 0xe5 0x48 0x00 0x00 0x00 0x00 diff --git a/test/MC/SystemZ/insn-bad.s b/test/MC/SystemZ/insn-bad.s index b730637cd37..228467004b1 100644 --- a/test/MC/SystemZ/insn-bad.s +++ b/test/MC/SystemZ/insn-bad.s @@ -712,6 +712,50 @@ cl %r0, -1 cl %r0, 4096 +#CHECK: error: missing length in address +#CHECK: clc 0, 0 +#CHECK: error: missing length in address +#CHECK: clc 0(%r1), 0(%r1) +#CHECK: error: invalid use of length addressing +#CHECK: clc 0(1,%r1), 0(2,%r1) +#CHECK: error: invalid operand +#CHECK: clc 0(0,%r1), 0(%r1) +#CHECK: error: invalid operand +#CHECK: clc 0(257,%r1), 0(%r1) +#CHECK: error: invalid operand +#CHECK: clc -1(1,%r1), 0(%r1) +#CHECK: error: invalid operand +#CHECK: clc 4096(1,%r1), 0(%r1) +#CHECK: error: invalid operand +#CHECK: clc 0(1,%r1), -1(%r1) +#CHECK: error: invalid operand +#CHECK: clc 0(1,%r1), 4096(%r1) +#CHECK: error: %r0 used in an address +#CHECK: clc 0(1,%r0), 0(%r1) +#CHECK: error: %r0 used in an address +#CHECK: clc 0(1,%r1), 0(%r0) +#CHECK: error: invalid use of indexed addressing +#CHECK: clc 0(%r1,%r2), 0(%r1) +#CHECK: error: invalid use of indexed addressing +#CHECK: clc 0(1,%r2), 0(%r1,%r2) +#CHECK: error: unknown token in expression +#CHECK: clc 0(-), 0 + + clc 0, 0 + clc 0(%r1), 0(%r1) + clc 0(1,%r1), 0(2,%r1) + clc 0(0,%r1), 0(%r1) + clc 0(257,%r1), 0(%r1) + clc -1(1,%r1), 0(%r1) + clc 4096(1,%r1), 0(%r1) + clc 0(1,%r1), -1(%r1) + clc 0(1,%r1), 4096(%r1) + clc 0(1,%r0), 0(%r1) + clc 0(1,%r1), 0(%r0) + clc 0(%r1,%r2), 0(%r1) + clc 0(1,%r2), 0(%r1,%r2) + clc 0(-), 0 + #CHECK: error: invalid operand #CHECK: clfhsi -1, 0 #CHECK: error: invalid operand diff --git a/test/MC/SystemZ/insn-good.s b/test/MC/SystemZ/insn-good.s index c4e09e47783..9fd0d0c7dc7 100644 --- a/test/MC/SystemZ/insn-good.s +++ b/test/MC/SystemZ/insn-good.s @@ -2454,6 +2454,32 @@ cl %r0, 4095(%r15,%r1) cl %r15, 0 +#CHECK: clc 0(1), 0 # encoding: [0xd5,0x00,0x00,0x00,0x00,0x00] +#CHECK: clc 0(1), 0(%r1) # encoding: [0xd5,0x00,0x00,0x00,0x10,0x00] +#CHECK: clc 0(1), 0(%r15) # encoding: [0xd5,0x00,0x00,0x00,0xf0,0x00] +#CHECK: clc 0(1), 4095 # encoding: [0xd5,0x00,0x00,0x00,0x0f,0xff] +#CHECK: clc 0(1), 4095(%r1) # encoding: [0xd5,0x00,0x00,0x00,0x1f,0xff] +#CHECK: clc 0(1), 4095(%r15) # encoding: [0xd5,0x00,0x00,0x00,0xff,0xff] +#CHECK: clc 0(1,%r1), 0 # encoding: [0xd5,0x00,0x10,0x00,0x00,0x00] +#CHECK: clc 0(1,%r15), 0 # encoding: [0xd5,0x00,0xf0,0x00,0x00,0x00] +#CHECK: clc 4095(1,%r1), 0 # encoding: [0xd5,0x00,0x1f,0xff,0x00,0x00] +#CHECK: clc 4095(1,%r15), 0 # encoding: [0xd5,0x00,0xff,0xff,0x00,0x00] +#CHECK: clc 0(256,%r1), 0 # encoding: [0xd5,0xff,0x10,0x00,0x00,0x00] +#CHECK: clc 0(256,%r15), 0 # encoding: [0xd5,0xff,0xf0,0x00,0x00,0x00] + + clc 0(1), 0 + clc 0(1), 0(%r1) + clc 0(1), 0(%r15) + clc 0(1), 4095 + clc 0(1), 4095(%r1) + clc 0(1), 4095(%r15) + clc 0(1,%r1), 0 + clc 0(1,%r15), 0 + clc 4095(1,%r1), 0 + clc 4095(1,%r15), 0 + clc 0(256,%r1), 0 + clc 0(256,%r15), 0 + #CHECK: clfhsi 0, 0 # encoding: [0xe5,0x5d,0x00,0x00,0x00,0x00] #CHECK: clfhsi 4095, 0 # encoding: [0xe5,0x5d,0x0f,0xff,0x00,0x00] #CHECK: clfhsi 0, 65535 # encoding: [0xe5,0x5d,0x00,0x00,0xff,0xff]