Index: llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp =================================================================== --- llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -40,12 +40,16 @@ using namespace llvm; -// Return true if Expr is in the range [MinValue, MaxValue]. -static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) { +// Return true if Expr is in the range [MinValue, MaxValue]. If AllowSymbol +// is true a SymbolRef is also accepted (address displacement). +static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue, + bool AllowSymbol = false) { if (auto *CE = dyn_cast(Expr)) { int64_t Value = CE->getValue(); return Value >= MinValue && Value <= MaxValue; } + if (AllowSymbol && isa(Expr)) + return true; return false; } @@ -265,10 +269,10 @@ return isMem(MemKind) && Mem.RegKind == RegKind; } bool isMemDisp12(MemoryKind MemKind, RegisterKind RegKind) const { - return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff); + return isMem(MemKind, RegKind) && inRange(Mem.Disp, 0, 0xfff, true); } bool isMemDisp20(MemoryKind MemKind, RegisterKind RegKind) const { - return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287); + return isMem(MemKind, RegKind) && inRange(Mem.Disp, -524288, 524287, true); } bool isMemDisp12Len4(RegisterKind RegKind) const { return isMemDisp12(BDLMem, RegKind) && inRange(Mem.Length.Imm, 1, 0x10); Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.h =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.h +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.h @@ -33,8 +33,9 @@ static const char *getRegisterName(unsigned RegNo); // Print an address with the given base, displacement and index. - static void printAddress(const MCAsmInfo *MAI, unsigned Base, int64_t Disp, - unsigned Index, raw_ostream &O); + static void printAddress(const MCAsmInfo *MAI, unsigned Base, + const MCOperand &DispMO, unsigned Index, + raw_ostream &O); // Print the given operand. static void printOperand(const MCOperand &MO, const MCAsmInfo *MAI, Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp @@ -24,9 +24,9 @@ #include "SystemZGenAsmWriter.inc" void SystemZInstPrinter::printAddress(const MCAsmInfo *MAI, unsigned Base, - int64_t Disp, unsigned Index, + const MCOperand &DispMO, unsigned Index, raw_ostream &O) { - O << Disp; + printOperand(DispMO, MAI, O); if (Base || Index) { O << '('; if (Index) { @@ -194,23 +194,23 @@ void SystemZInstPrinter::printBDAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O) { - printAddress(&MAI, MI->getOperand(OpNum).getReg(), - MI->getOperand(OpNum + 1).getImm(), 0, O); + printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), + 0, O); } void SystemZInstPrinter::printBDXAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O) { - printAddress(&MAI, MI->getOperand(OpNum).getReg(), - MI->getOperand(OpNum + 1).getImm(), + printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), MI->getOperand(OpNum + 2).getReg(), O); } void SystemZInstPrinter::printBDLAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O) { unsigned Base = MI->getOperand(OpNum).getReg(); - uint64_t Disp = MI->getOperand(OpNum + 1).getImm(); + const MCOperand &DispMO = MI->getOperand(OpNum + 1); uint64_t Length = MI->getOperand(OpNum + 2).getImm(); - O << Disp << '(' << Length; + printOperand(DispMO, &MAI, O); + O << '(' << Length; if (Base) { O << ","; printRegName(O, Base); @@ -221,9 +221,10 @@ void SystemZInstPrinter::printBDRAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O) { unsigned Base = MI->getOperand(OpNum).getReg(); - uint64_t Disp = MI->getOperand(OpNum + 1).getImm(); + const MCOperand &DispMO = MI->getOperand(OpNum + 1); unsigned Length = MI->getOperand(OpNum + 2).getReg(); - O << Disp << "("; + printOperand(DispMO, &MAI, O); + O << "("; printRegName(O, Length); if (Base) { O << ","; @@ -234,8 +235,7 @@ void SystemZInstPrinter::printBDVAddrOperand(const MCInst *MI, int OpNum, raw_ostream &O) { - printAddress(&MAI, MI->getOperand(OpNum).getReg(), - MI->getOperand(OpNum + 1).getImm(), + printAddress(&MAI, MI->getOperand(OpNum).getReg(), MI->getOperand(OpNum + 1), MI->getOperand(OpNum + 2).getReg(), O); } Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -32,6 +32,10 @@ case SystemZ::FK_390_PC32DBL: return (int64_t)Value / 2; + case SystemZ::FK_390_12: + case SystemZ::FK_390_20: + return Value; + case SystemZ::FK_390_TLS_CALL: return 0; } @@ -95,7 +99,9 @@ { "FK_390_PC16DBL", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "FK_390_PC24DBL", 0, 24, MCFixupKindInfo::FKF_IsPCRel }, { "FK_390_PC32DBL", 0, 32, MCFixupKindInfo::FKF_IsPCRel }, - { "FK_390_TLS_CALL", 0, 0, 0 } + { "FK_390_TLS_CALL", 0, 0, 0 }, + { "FK_390_12", 4, 12, 0 }, + { "FK_390_20", 4, 20, 0 } }; // Fixup kinds from .reloc directive are like R_390_NONE. They @@ -126,19 +132,23 @@ MCFixupKind Kind = Fixup.getKind(); if (Kind >= FirstLiteralRelocationKind) return; - unsigned Offset = Fixup.getOffset(); + unsigned ByteOffset = Fixup.getOffset(); unsigned BitSize = getFixupKindInfo(Kind).TargetSize; - unsigned Size = (BitSize + 7) / 8; + unsigned BitOffset = getFixupKindInfo(Kind).TargetOffset; + unsigned Size = (BitSize + BitOffset + 7) / 8; - assert(Offset + Size <= Data.size() && "Invalid fixup offset!"); + assert(ByteOffset + Size <= Data.size() && "Invalid fixup offset!"); - // Big-endian insertion of Size bytes. Value = extractBitsForFixup(Kind, Value); if (BitSize < 64) Value &= ((uint64_t)1 << BitSize) - 1; + Value <<= BitOffset; + // TODO: no test yet for the shifting of the bit offset. + + // Big-endian insertion of Size bytes. unsigned ShiftValue = (Size * 8) - 8; for (unsigned I = 0; I != Size; ++I) { - Data[Offset + I] |= uint8_t(Value >> ShiftValue); + Data[ByteOffset + I] |= uint8_t(Value >> ShiftValue); ShiftValue -= 8; } } Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -60,6 +60,12 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + // Return the displacement value for the OpNum operand. If it is a symbol, + // add a fixup for it and return 0. + uint64_t getDispOpValue(const MCInst &MI, unsigned OpNum, + SmallVectorImpl &Fixups, + SystemZ::FixupKind Kind) const; + // Called by the TableGen code to get the binary encoding of an address. // The index or length, if any, is encoded first, followed by the base, // followed by the displacement. In a 20-bit displacement, @@ -179,12 +185,37 @@ llvm_unreachable("Unexpected operand type!"); } +// TODO: What's the best way to do this? +static uint32_t getFixupByteOffs(const MCInst &MI, unsigned OpNum) { + switch (MI.getOpcode()) { + default: break; + case SystemZ::MVC: + return OpNum == 1 ? 2 : 4; + } + return 2; +} + +uint64_t SystemZMCCodeEmitter:: +getDispOpValue(const MCInst &MI, unsigned OpNum, + SmallVectorImpl &Fixups, + SystemZ::FixupKind Kind) const { + const MCOperand &MO = MI.getOperand(OpNum); + if (MO.isImm()) + return static_cast(MO.getImm()); + if (MO.isExpr()) { + Fixups.push_back(MCFixup::create(getFixupByteOffs(MI, OpNum), + MO.getExpr(), (MCFixupKind)Kind)); + return 0; + } + llvm_unreachable("Unexpected operand type!"); +} + uint64_t SystemZMCCodeEmitter:: getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12); assert(isUInt<4>(Base) && isUInt<12>(Disp)); return (Base << 12) | Disp; } @@ -194,7 +225,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20); assert(isUInt<4>(Base) && isInt<20>(Disp)); return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); } @@ -204,7 +235,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12); uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); return (Index << 16) | (Base << 12) | Disp; @@ -215,7 +246,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20); uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) @@ -227,7 +258,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12); uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len)); return (Len << 16) | (Base << 12) | Disp; @@ -238,7 +269,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12); uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len)); return (Len << 16) | (Base << 12) | Disp; @@ -249,7 +280,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12); uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len)); return (Len << 16) | (Base << 12) | Disp; @@ -260,7 +291,7 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12); uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index)); return (Index << 16) | (Base << 12) | Disp; Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h @@ -20,6 +20,8 @@ FK_390_PC24DBL, FK_390_PC32DBL, FK_390_TLS_CALL, + FK_390_12, + FK_390_20, // Marker LastTargetFixupKind, Index: llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp =================================================================== --- llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp +++ llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp @@ -46,6 +46,8 @@ case FK_Data_2: return ELF::R_390_16; case FK_Data_4: return ELF::R_390_32; case FK_Data_8: return ELF::R_390_64; + case SystemZ::FK_390_12: return ELF::R_390_12; + case SystemZ::FK_390_20: return ELF::R_390_20; } llvm_unreachable("Unsupported absolute address"); } Index: llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -775,9 +775,10 @@ unsigned OpNo, const char *ExtraCode, raw_ostream &OS) { - SystemZInstPrinter::printAddress(MAI, MI->getOperand(OpNo).getReg(), - MI->getOperand(OpNo + 1).getImm(), - MI->getOperand(OpNo + 2).getReg(), OS); + SystemZInstPrinter:: + printAddress(MAI, MI->getOperand(OpNo).getReg(), + MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), + MI->getOperand(OpNo + 2).getReg(), OS); return false; } Index: llvm/test/MC/SystemZ/fixups.s =================================================================== --- llvm/test/MC/SystemZ/fixups.s +++ llvm/test/MC/SystemZ/fixups.s @@ -1,7 +1,7 @@ -# RUN: llvm-mc -triple s390x-unknown-unknown --show-encoding %s | FileCheck %s +# RUN: llvm-mc -triple s390x-unknown-unknown -mcpu=z13 --show-encoding %s | FileCheck %s -# RUN: llvm-mc -triple s390x-unknown-unknown -filetype=obj %s | \ +# RUN: llvm-mc -triple s390x-unknown-unknown -mcpu=z13 -filetype=obj %s | \ # RUN: llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-REL # CHECK: larl %r14, target # encoding: [0xc0,0xe0,A,A,A,A] @@ -79,6 +79,40 @@ bras %r14, target@plt:tls_ldcall:sym +# Symbolic displacements +# CHECK: lg %r14, src # encoding: [0xe3,0xe0,0b0000AAAA,A,A,0x04] +# CHECK-NEXT: # fixup A - offset: 2, value: src, kind: FK_390_20 +# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_20 src 0x0 + .align 16 + lg %r14, src + +# CHECK: la %r14, src(%r1) # encoding: [0x41,0xe0,0b0001AAAA,A] +# CHECK-NEXT: # fixup A - offset: 2, value: src, kind: FK_390_12 +# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_12 src 0x0 + .align 16 + la %r14, src(%r1) + +# CHECK: lay %r14, src(%r1,%r2) # encoding: [0xe3,0xe1,0b0010AAAA,A,A,0x71] +# CHECK-NEXT: # fixup A - offset: 2, value: src, kind: FK_390_20 +# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_20 src 0x0 + .align 16 + lay %r14, src(%r1, %r2) + +# CHECK: mvc dst(1,%r1), src(%r1) # encoding: [0xd2,0x00,0b0001AAAA,A,0b0001BBBB,B] +# CHECK-NEXT: # fixup A - offset: 2, value: dst, kind: FK_390_12 +# CHECK-NEXT: # fixup B - offset: 4, value: src, kind: FK_390_12 +# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_12 dst 0x0 +# CHECK-REL: 0x{{[0-9A-F]*4}} R_390_12 src 0x0 + .align 16 + mvc dst(1,%r1), src(%r1) + +# CHECK: vl %v0, src # encoding: [0xe7,0x00,0b0000AAAA,A,0x00,0x06] +# CHECK-NEXT: # fixup A - offset: 2, value: src, kind: FK_390_12 +# CHECK-REL: 0x{{[0-9A-F]*2}} R_390_12 src 0x0 + .align 16 + vl %v0, src + + # Data relocs # llvm-mc does not show any "encoding" string for data, so we just check the relocs @@ -116,4 +150,3 @@ # CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_GD32 target 0x0 .align 16 .long target@tlsgd - Index: llvm/test/MC/SystemZ/reloc-directive.s =================================================================== --- llvm/test/MC/SystemZ/reloc-directive.s +++ llvm/test/MC/SystemZ/reloc-directive.s @@ -9,6 +9,8 @@ # PRINT-NEXT: .reloc 0, R_390_64, .data+2 # PRINT-NEXT: .reloc 0, R_390_GOTENT, foo+3 # PRINT-NEXT: .reloc 0, R_390_PC32DBL, 6 +# PRINT-NEXT: .reloc 4, R_390_12, foo +# PRINT-NEXT: .reloc 2, R_390_20, foo # PRINT: .reloc 0, BFD_RELOC_NONE, 9 # PRINT-NEXT: .reloc 0, BFD_RELOC_8, 9 # PRINT-NEXT: .reloc 0, BFD_RELOC_16, 9 @@ -21,6 +23,8 @@ # CHECK-NEXT: 0x0 R_390_64 .data 0x2 # CHECK-NEXT: 0x0 R_390_GOTENT foo 0x3 # CHECK-NEXT: 0x0 R_390_PC32DBL - 0x6 +# CHECK-NEXT: 0x4 R_390_12 foo 0x0 +# CHECK-NEXT: 0x2 R_390_20 foo 0x0 # CHECK-NEXT: 0x0 R_390_NONE - 0x9 # CHECK-NEXT: 0x0 R_390_8 - 0x9 # CHECK-NEXT: 0x0 R_390_16 - 0x9 @@ -37,6 +41,8 @@ .reloc 0, R_390_64, .data+2 .reloc 0, R_390_GOTENT, foo+3 .reloc 0, R_390_PC32DBL, 6 + .reloc 4, R_390_12, foo + .reloc 2, R_390_20, foo .reloc 0, BFD_RELOC_NONE, 9 .reloc 0, BFD_RELOC_8, 9