diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -37,6 +37,8 @@ const MCInstrInfo &MCII; MCContext &Ctx; + mutable unsigned MemOpsEmitted; + public: SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) : MCII(mcii), Ctx(ctx) { @@ -165,6 +167,7 @@ verifyInstructionPredicates(MI, computeAvailableFeatures(STI.getFeatureBits())); + MemOpsEmitted = 0; uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); unsigned Size = MCII.get(MI.getOpcode()).getSize(); // Big-endian insertion of Size bytes. @@ -191,12 +194,14 @@ SmallVectorImpl &Fixups, SystemZ::FixupKind Kind) const { const MCOperand &MO = MI.getOperand(OpNum); - if (MO.isImm()) + if (MO.isImm()) { + ++MemOpsEmitted; return static_cast(MO.getImm()); + } if (MO.isExpr()) { // All instructions follow the pattern where the first displacement has a // 2 bytes offset, and the second one 4 bytes. - unsigned ByteOffs = Fixups.size() == 0 ? 2 : 4; + unsigned ByteOffs = MemOpsEmitted++ == 0 ? 2 : 4; Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind, MI.getLoc())); assert(Fixups.size() <= 2 && "More than two memory operands in MI?"); diff --git a/llvm/test/MC/SystemZ/fixups.s b/llvm/test/MC/SystemZ/fixups.s --- a/llvm/test/MC/SystemZ/fixups.s +++ b/llvm/test/MC/SystemZ/fixups.s @@ -287,6 +287,11 @@ .align 16 vgeg %v0, src(%v0,%r1), 0 +## Fixup for second operand only +# CHECK: mvc 32(8,%r0), src # encoding: [0xd2,0x07,0x00,0x20,0b0000AAAA,A] +# CHECK-NEXT: # fixup A - offset: 4, value: src, kind: FK_390_12 + .align 16 + mvc 32(8,%r0),src # Data relocs # llvm-mc does not show any "encoding" string for data, so we just check the relocs