diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp --- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -237,7 +237,7 @@ return Kind == KindImm; } bool isImm(int64_t MinValue, int64_t MaxValue) const { - return Kind == KindImm && inRange(Imm, MinValue, MaxValue); + return Kind == KindImm && inRange(Imm, MinValue, MaxValue, true); } const MCExpr *getImm() const { assert(Kind == KindImm && "Not an immediate"); diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZInstPrinter.cpp @@ -83,7 +83,12 @@ template void SystemZInstPrinter::printUImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) { - int64_t Value = MI->getOperand(OpNum).getImm(); + const MCOperand &MO = MI->getOperand(OpNum); + if (MO.isExpr()) { + O << markup(""); + return; + } + uint64_t Value = static_cast(MO.getImm()); assert(isUInt(Value) && "Invalid uimm argument"); O << markup(""); } @@ -91,6 +96,11 @@ template void SystemZInstPrinter::printSImmOperand(const MCInst *MI, int OpNum, raw_ostream &O) { + const MCOperand &MO = MI->getOperand(OpNum); + if (MO.isExpr()) { + O << markup(""); + return; + } int64_t Value = MI->getOperand(OpNum).getImm(); assert(isInt(Value) && "Invalid simm argument"); O << markup(""); diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -47,6 +47,13 @@ return (int64_t)Value / 2; }; + auto handleImmValue = [&](bool IsSigned, unsigned W) -> uint64_t { + if (!(IsSigned ? checkFixupInRange(minIntN(W), maxIntN(W)) + : checkFixupInRange(0, maxUIntN(W)))) + return 0; + return Value; + }; + switch (unsigned(Kind)) { case SystemZ::FK_390_PC12DBL: return handlePCRelFixupValue(12); @@ -73,6 +80,31 @@ case SystemZ::FK_390_TLS_CALL: return 0; + + case SystemZ::FK_390_S8Imm: + return handleImmValue(true, 8); + case SystemZ::FK_390_S16Imm: + return handleImmValue(true, 16); + case SystemZ::FK_390_S32Imm: + return handleImmValue(true, 32); + case SystemZ::FK_390_U1Imm: + return handleImmValue(false, 1); + case SystemZ::FK_390_U2Imm: + return handleImmValue(false, 2); + case SystemZ::FK_390_U3Imm: + return handleImmValue(false, 3); + case SystemZ::FK_390_U4Imm: + return handleImmValue(false, 4); + case SystemZ::FK_390_U8Imm: + return handleImmValue(false, 8); + case SystemZ::FK_390_U12Imm: + return handleImmValue(false, 12); + case SystemZ::FK_390_U16Imm: + return handleImmValue(false, 16); + case SystemZ::FK_390_U32Imm: + return handleImmValue(false, 32); + case SystemZ::FK_390_U48Imm: + return handleImmValue(false, 48); } llvm_unreachable("Unknown fixup kind!"); @@ -131,13 +163,25 @@ const MCFixupKindInfo & SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { const static MCFixupKindInfo Infos[SystemZ::NumTargetFixupKinds] = { - { "FK_390_PC12DBL", 4, 12, MCFixupKindInfo::FKF_IsPCRel }, - { "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_12", 4, 12, 0 }, - { "FK_390_20", 4, 20, 0 } + {"FK_390_PC12DBL", 4, 12, MCFixupKindInfo::FKF_IsPCRel}, + {"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_12", 4, 12, 0}, + {"FK_390_20", 4, 20, 0}, + {"FK_390_S8Imm", 0, 8, 0}, + {"FK_390_S16Imm", 0, 16, 0}, + {"FK_390_S32Imm", 0, 32, 0}, + {"FK_390_U1Imm", 0, 1, 0}, + {"FK_390_U2Imm", 0, 2, 0}, + {"FK_390_U3Imm", 0, 3, 0}, + {"FK_390_U4Imm", 0, 4, 0}, + {"FK_390_U8Imm", 0, 8, 0}, + {"FK_390_U12Imm", 0, 12, 0}, + {"FK_390_U16Imm", 0, 16, 0}, + {"FK_390_U32Imm", 0, 32, 0}, + {"FK_390_U48Imm", 0, 48, 0}, }; // Fixup kinds from .reloc directive are like R_390_NONE. They 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 @@ -57,11 +57,25 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + // Automatically generated by TableGen. + uint32_t getOperandBitOffset(const MCInst &MI, unsigned OpNum, + const MCSubtargetInfo &STI) const; + // Called by the TableGen code to get the binary encoding of operand // MO in MI. Fixups is the list of fixups against MI. uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const; + const MCSubtargetInfo &STI, unsigned OpNum = 0, + SystemZ::FixupKind FixupKind = + SystemZ::FixupKind::LastTargetFixupKind) const; + + template + uint64_t encodeImmOperand(const MCInst &MI, unsigned OpNum, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + return getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI, OpNum, + FixupKind); + } // Return the displacement value for the OpNum operand. If it is a symbol, // add a fixup for it and return 0. @@ -169,14 +183,28 @@ } } -uint64_t SystemZMCCodeEmitter:: -getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl &Fixups, - const MCSubtargetInfo &STI) const { +uint64_t SystemZMCCodeEmitter::getMachineOpValue( + const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI, unsigned OpNum, + SystemZ::FixupKind FixupKind) const { if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) return static_cast(MO.getImm()); + if (MO.isExpr()) { + if (FixupKind == SystemZ::FixupKind::LastTargetFixupKind) { + Ctx.reportError(MI.getLoc(), "invalid operand for instruction"); + return 0; + } + uint32_t BitOffset = getOperandBitOffset(MI, OpNum, STI); + if (BitOffset & 7) { + Ctx.reportError(MI.getLoc(), "invalid operand for instruction"); + return 0; + } + Fixups.push_back(MCFixup::create(BitOffset >> 3, MO.getExpr(), + (MCFixupKind)FixupKind, MI.getLoc())); + return 0; + } llvm_unreachable("Unexpected operand type!"); } @@ -320,6 +348,7 @@ return 0; } +#define GET_OPERAND_BIT_OFFSET #include "SystemZGenMCCodeEmitter.inc" MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, diff --git a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h --- a/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h +++ b/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h @@ -23,6 +23,19 @@ FK_390_12, FK_390_20, + FK_390_S8Imm, + FK_390_S16Imm, + FK_390_S32Imm, + FK_390_U1Imm, + FK_390_U2Imm, + FK_390_U3Imm, + FK_390_U4Imm, + FK_390_U8Imm, + FK_390_U12Imm, + FK_390_U16Imm, + FK_390_U32Imm, + FK_390_U48Imm, + // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/llvm/lib/Target/SystemZ/SystemZOperands.td b/llvm/lib/Target/SystemZ/SystemZOperands.td --- a/llvm/lib/Target/SystemZ/SystemZOperands.td +++ b/llvm/lib/Target/SystemZ/SystemZOperands.td @@ -23,6 +23,7 @@ class ImmediateOp : Operand { let PrintMethod = "print"#asmop#"Operand"; + let EncoderMethod = "encodeImmOperand"; let DecoderMethod = "decode"#asmop#"Operand"; let ParserMatchClass = !cast(asmop); let OperandType = "OPERAND_IMMEDIATE"; 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 @@ -4,6 +4,9 @@ # RUN: llvm-mc -triple s390x-unknown-unknown -mcpu=z13 -filetype=obj %s | \ # RUN: llvm-readobj -r - | FileCheck %s -check-prefix=CHECK-REL +# RUN: llvm-mc -triple s390x-unknown-unknown -mcpu=z13 -filetype=obj %s | \ +# RUN: llvm-objdump -d - | FileCheck %s -check-prefix=CHECK-DIS + # CHECK: larl %r14, target # encoding: [0xc0,0xe0,A,A,A,A] # CHECK-NEXT: # fixup A - offset: 2, value: target+2, kind: FK_390_PC32DBL # CHECK-REL: 0x{{[0-9A-F]*2}} R_390_PC32DBL target 0x2 @@ -293,6 +296,17 @@ .align 16 mvc 32(8,%r0),src +## Symbol calculations. +# CHECK: lghi %r0, lghi_b-lghi_a # encoding: [0xa7,0x09,A,A] +# CHECK-NEXT: # fixup A - offset: 2, value: lghi_b-lghi_a, kind: FK_390_S16Imm +# CHECK-DIS: : +# CHECK-DIS-NEXT: a7 09 00 08 lghi %r0, 8 + .align 16 +lghi_a_b: + lghi %r0, lghi_b-lghi_a +lghi_a: .quad 0 +lghi_b: + # Data relocs # llvm-mc does not show any "encoding" string for data, so we just check the relocs @@ -330,4 +344,3 @@ # CHECK-REL: 0x{{[0-9A-F]*0}} R_390_TLS_GD32 target 0x0 .align 16 .long target@tlsgd - diff --git a/llvm/test/MC/SystemZ/insn-bad-z196.s b/llvm/test/MC/SystemZ/insn-bad-z196.s --- a/llvm/test/MC/SystemZ/insn-bad-z196.s +++ b/llvm/test/MC/SystemZ/insn-bad-z196.s @@ -16,23 +16,17 @@ #CHECK: aghik %r0, %r1, -32769 #CHECK: error: invalid operand #CHECK: aghik %r0, %r1, 32768 -#CHECK: error: invalid operand -#CHECK: aghik %r0, %r1, foo aghik %r0, %r1, -32769 aghik %r0, %r1, 32768 - aghik %r0, %r1, foo #CHECK: error: invalid operand #CHECK: ahik %r0, %r1, -32769 #CHECK: error: invalid operand #CHECK: ahik %r0, %r1, 32768 -#CHECK: error: invalid operand -#CHECK: ahik %r0, %r1, foo ahik %r0, %r1, -32769 ahik %r0, %r1, 32768 - ahik %r0, %r1, foo #CHECK: error: invalid operand #CHECK: aih %r0, (-1 << 31) - 1 diff --git a/llvm/test/MC/SystemZ/insn-bad.s b/llvm/test/MC/SystemZ/insn-bad.s --- a/llvm/test/MC/SystemZ/insn-bad.s +++ b/llvm/test/MC/SystemZ/insn-bad.s @@ -85,12 +85,9 @@ #CHECK: aghi %r0, -32769 #CHECK: error: invalid operand #CHECK: aghi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: aghi %r0, foo aghi %r0, -32769 aghi %r0, 32768 - aghi %r0, foo #CHECK: error: instruction requires: distinct-ops #CHECK: aghik %r1, %r2, 3 @@ -141,12 +138,9 @@ #CHECK: ahi %r0, -32769 #CHECK: error: invalid operand #CHECK: ahi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: ahi %r0, foo ahi %r0, -32769 ahi %r0, 32768 - ahi %r0, foo #CHECK: error: instruction requires: distinct-ops #CHECK: ahik %r1, %r2, 3 @@ -626,14 +620,11 @@ jlo label jlno label -#CHECK: error: invalid operand -#CHECK: brc foo, bar #CHECK: error: invalid operand #CHECK: brc -1, bar #CHECK: error: invalid operand #CHECK: brc 16, bar - brc foo, bar brc -1, bar brc 16, bar @@ -668,14 +659,11 @@ #CHECK: jlnop label jlnop label -#CHECK: error: invalid operand -#CHECK: brcl foo, bar #CHECK: error: invalid operand #CHECK: brcl -1, bar #CHECK: error: invalid operand #CHECK: brcl 16, bar - brcl foo, bar brcl -1, bar brcl 16, bar @@ -1184,12 +1172,9 @@ #CHECK: cghi %r0, -32769 #CHECK: error: invalid operand #CHECK: cghi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: cghi %r0, foo cghi %r0, -32769 cghi %r0, 32768 - cghi %r0, foo #CHECK: error: offset out of range #CHECK: cghrl %r0, -0x1000000002 @@ -1392,12 +1377,9 @@ #CHECK: chi %r0, -32769 #CHECK: error: invalid operand #CHECK: chi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: chi %r0, foo chi %r0, -32769 chi %r0, 32768 - chi %r0, foo #CHECK: error: instruction requires: high-word #CHECK: chlr %r0, %r0 @@ -3546,12 +3528,9 @@ #CHECK: lghi %r0, -32769 #CHECK: error: invalid operand #CHECK: lghi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: lghi %r0, foo lghi %r0, -32769 lghi %r0, 32768 - lghi %r0, foo #CHECK: error: offset out of range #CHECK: lghrl %r0, -0x1000000002 @@ -3598,12 +3577,9 @@ #CHECK: lhi %r0, -32769 #CHECK: error: invalid operand #CHECK: lhi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: lhi %r0, foo lhi %r0, -32769 lhi %r0, 32768 - lhi %r0, foo #CHECK: error: offset out of range #CHECK: lhrl %r0, -0x1000000002 @@ -4321,12 +4297,9 @@ #CHECK: mghi %r0, -32769 #CHECK: error: invalid operand #CHECK: mghi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: mghi %r0, foo mghi %r0, -32769 mghi %r0, 32768 - mghi %r0, foo #CHECK: error: invalid operand #CHECK: mh %r0, -1 @@ -4340,12 +4313,9 @@ #CHECK: mhi %r0, -32769 #CHECK: error: invalid operand #CHECK: mhi %r0, 32768 -#CHECK: error: invalid operand -#CHECK: mhi %r0, foo mhi %r0, -32769 mhi %r0, 32768 - mhi %r0, foo #CHECK: error: invalid operand #CHECK: mhy %r0, -524289 diff --git a/llvm/test/MC/SystemZ/insn-good-z196.s b/llvm/test/MC/SystemZ/insn-good-z196.s --- a/llvm/test/MC/SystemZ/insn-good-z196.s +++ b/llvm/test/MC/SystemZ/insn-good-z196.s @@ -24,6 +24,7 @@ #CHECK: aghik %r0, %r15, 0 # encoding: [0xec,0x0f,0x00,0x00,0x00,0xd9] #CHECK: aghik %r15, %r0, 0 # encoding: [0xec,0xf0,0x00,0x00,0x00,0xd9] #CHECK: aghik %r7, %r8, -16 # encoding: [0xec,0x78,0xff,0xf0,0x00,0xd9] +#CHECK: aghik %r0, %r1, foo # encoding: [0xec,0x01,A,A,0x00,0xd9] aghik %r0, %r0, -32768 aghik %r0, %r0, -1 @@ -33,6 +34,7 @@ aghik %r0, %r15, 0 aghik %r15, %r0, 0 aghik %r7, %r8, -16 + aghik %r0, %r1, foo #CHECK: agrk %r0, %r0, %r0 # encoding: [0xb9,0xe8,0x00,0x00] #CHECK: agrk %r0, %r0, %r15 # encoding: [0xb9,0xe8,0xf0,0x00] @@ -78,6 +80,7 @@ #CHECK: ahik %r0, %r15, 0 # encoding: [0xec,0x0f,0x00,0x00,0x00,0xd8] #CHECK: ahik %r15, %r0, 0 # encoding: [0xec,0xf0,0x00,0x00,0x00,0xd8] #CHECK: ahik %r7, %r8, -16 # encoding: [0xec,0x78,0xff,0xf0,0x00,0xd8] +#CHECK: ahik %r0, %r1, foo # encoding: [0xec,0x01,A,A,0x00,0xd8] ahik %r0, %r0, -32768 ahik %r0, %r0, -1 @@ -87,6 +90,7 @@ ahik %r0, %r15, 0 ahik %r15, %r0, 0 ahik %r7, %r8, -16 + ahik %r0, %r1, foo #CHECK: aih %r0, -2147483648 # encoding: [0xcc,0x08,0x80,0x00,0x00,0x00] #CHECK: aih %r0, -1 # encoding: [0xcc,0x08,0xff,0xff,0xff,0xff] diff --git a/llvm/test/MC/SystemZ/insn-good.s b/llvm/test/MC/SystemZ/insn-good.s --- a/llvm/test/MC/SystemZ/insn-good.s +++ b/llvm/test/MC/SystemZ/insn-good.s @@ -236,6 +236,7 @@ #CHECK: aghi %r0, 1 # encoding: [0xa7,0x0b,0x00,0x01] #CHECK: aghi %r0, 32767 # encoding: [0xa7,0x0b,0x7f,0xff] #CHECK: aghi %r15, 0 # encoding: [0xa7,0xfb,0x00,0x00] +#CHECK: aghi %r0, foo # encoding: [0xa7,0x0b,A,A] aghi %r0, -32768 aghi %r0, -1 @@ -243,6 +244,7 @@ aghi %r0, 1 aghi %r0, 32767 aghi %r15, 0 + aghi %r0, foo #CHECK: agr %r0, %r0 # encoding: [0xb9,0x08,0x00,0x00] #CHECK: agr %r0, %r15 # encoding: [0xb9,0x08,0x00,0x0f] @@ -304,6 +306,7 @@ #CHECK: ahi %r0, 1 # encoding: [0xa7,0x0a,0x00,0x01] #CHECK: ahi %r0, 32767 # encoding: [0xa7,0x0a,0x7f,0xff] #CHECK: ahi %r15, 0 # encoding: [0xa7,0xfa,0x00,0x00] +#CHECK: ahi %r0, foo # encoding: [0xa7,0x0a,A,A] ahi %r0, -32768 ahi %r0, -1 @@ -311,6 +314,7 @@ ahi %r0, 1 ahi %r0, 32767 ahi %r15, 0 + ahi %r0, foo #CHECK: ahy %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x7a] #CHECK: ahy %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x7a] @@ -3425,6 +3429,7 @@ #CHECK: cghi %r0, 1 # encoding: [0xa7,0x0f,0x00,0x01] #CHECK: cghi %r0, 32767 # encoding: [0xa7,0x0f,0x7f,0xff] #CHECK: cghi %r15, 0 # encoding: [0xa7,0xff,0x00,0x00] +#CHECK: cghi %r0, foo # encoding: [0xa7,0x0f,A,A] cghi %r0, -32768 cghi %r0, -1 @@ -3432,6 +3437,7 @@ cghi %r0, 1 cghi %r0, 32767 cghi %r15, 0 + cghi %r0, foo #CHECK: cghrl %r0, .[[LAB:L.*]]-4294967296 # encoding: [0xc6,0x04,A,A,A,A] #CHECK: fixup A - offset: 2, value: (.[[LAB]]-4294967296)+2, kind: FK_390_PC32DBL @@ -4286,6 +4292,7 @@ #CHECK: chi %r0, 1 # encoding: [0xa7,0x0e,0x00,0x01] #CHECK: chi %r0, 32767 # encoding: [0xa7,0x0e,0x7f,0xff] #CHECK: chi %r15, 0 # encoding: [0xa7,0xfe,0x00,0x00] +#CHECK: chi %r0, foo # encoding: [0xa7,0x0e,A,A] chi %r0, -32768 chi %r0, -1 @@ -4293,6 +4300,7 @@ chi %r0, 1 chi %r0, 32767 chi %r15, 0 + chi %r0, foo #CHECK: chrl %r0, .[[LAB:L.*]]-4294967296 # encoding: [0xc6,0x05,A,A,A,A] #CHECK: fixup A - offset: 2, value: (.[[LAB]]-4294967296)+2, kind: FK_390_PC32DBL @@ -9608,6 +9616,7 @@ #CHECK: lghi %r0, 1 # encoding: [0xa7,0x09,0x00,0x01] #CHECK: lghi %r0, 32767 # encoding: [0xa7,0x09,0x7f,0xff] #CHECK: lghi %r15, 0 # encoding: [0xa7,0xf9,0x00,0x00] +#CHECK: lghi %r14, foo # encoding: [0xa7,0xe9,A,A] lghi %r0, -32768 lghi %r0, -1 @@ -9615,6 +9624,7 @@ lghi %r0, 1 lghi %r0, 32767 lghi %r15, 0 + lghi %r14, foo #CHECK: lghr %r0, %r15 # encoding: [0xb9,0x07,0x00,0x0f] #CHECK: lghr %r7, %r8 # encoding: [0xb9,0x07,0x00,0x78] @@ -9730,6 +9740,7 @@ #CHECK: lhi %r0, 1 # encoding: [0xa7,0x08,0x00,0x01] #CHECK: lhi %r0, 32767 # encoding: [0xa7,0x08,0x7f,0xff] #CHECK: lhi %r15, 0 # encoding: [0xa7,0xf8,0x00,0x00] +#CHECK: lhi %r0, foo # encoding: [0xa7,0x08,A,A] lhi %r0, -32768 lhi %r0, -1 @@ -9737,6 +9748,7 @@ lhi %r0, 1 lhi %r0, 32767 lhi %r15, 0 + lhi %r0, foo #CHECK: lhr %r0, %r15 # encoding: [0xb9,0x27,0x00,0x0f] #CHECK: lhr %r7, %r8 # encoding: [0xb9,0x27,0x00,0x78] @@ -11641,6 +11653,7 @@ #CHECK: mghi %r0, 1 # encoding: [0xa7,0x0d,0x00,0x01] #CHECK: mghi %r0, 32767 # encoding: [0xa7,0x0d,0x7f,0xff] #CHECK: mghi %r15, 0 # encoding: [0xa7,0xfd,0x00,0x00] +#CHECK: mghi %r0, foo # encoding: [0xa7,0x0d,A,A] mghi %r0, -32768 mghi %r0, -1 @@ -11648,6 +11661,7 @@ mghi %r0, 1 mghi %r0, 32767 mghi %r15, 0 + mghi %r0, foo #CHECK: mh %r0, 0 # encoding: [0x4c,0x00,0x00,0x00] #CHECK: mh %r0, 4095 # encoding: [0x4c,0x00,0x0f,0xff] @@ -11671,6 +11685,7 @@ #CHECK: mhi %r0, 1 # encoding: [0xa7,0x0c,0x00,0x01] #CHECK: mhi %r0, 32767 # encoding: [0xa7,0x0c,0x7f,0xff] #CHECK: mhi %r15, 0 # encoding: [0xa7,0xfc,0x00,0x00] +#CHECK: mhi %r0, foo # encoding: [0xa7,0x0c,A,A] mhi %r0, -32768 mhi %r0, -1 @@ -11678,6 +11693,7 @@ mhi %r0, 1 mhi %r0, 32767 mhi %r15, 0 + mhi %r0, foo #CHECK: mhy %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x7c] #CHECK: mhy %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x7c] diff --git a/llvm/utils/TableGen/CodeEmitterGen.cpp b/llvm/utils/TableGen/CodeEmitterGen.cpp --- a/llvm/utils/TableGen/CodeEmitterGen.cpp +++ b/llvm/utils/TableGen/CodeEmitterGen.cpp @@ -46,16 +46,22 @@ private: int getVariableBit(const std::string &VarName, BitsInit *BI, int bit); - std::string getInstructionCase(Record *R, CodeGenTarget &Target); - std::string getInstructionCaseForEncoding(Record *R, Record *EncodingDef, - CodeGenTarget &Target); + std::pair + getInstructionCases(Record *R, CodeGenTarget &Target); + void addInstructionCasesForEncoding(Record *R, Record *EncodingDef, + CodeGenTarget &Target, std::string &Case, + std::string &BitOffsetCase); bool addCodeToMergeInOperand(Record *R, BitsInit *BI, - const std::string &VarName, - std::string &Case, CodeGenTarget &Target); + const std::string &VarName, std::string &Case, + std::string &BitOffsetCase, + CodeGenTarget &Target); void emitInstructionBaseValues( raw_ostream &o, ArrayRef NumberedInstructions, CodeGenTarget &Target, int HwMode = -1); + void + emitCaseMap(raw_ostream &o, + const std::map> &CaseMap); unsigned BitWidth = 0u; bool UseAPInt = false; }; @@ -80,6 +86,7 @@ bool CodeEmitterGen::addCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, std::string &Case, + std::string &BitOffsetCase, CodeGenTarget &Target) { CodeGenInstruction &CGI = Target.getInstruction(R); @@ -175,6 +182,7 @@ ++numOperandLits; } + bool BitOffsetCaseEmitted = false; for (; bit >= 0; ) { int varBit = getVariableBit(VarName, BI, bit); @@ -183,7 +191,7 @@ --bit; continue; } - + // Figure out the consecutive range of bits covered by this operand, in // order to generate better encoding code. int beginInstBit = bit; @@ -202,6 +210,12 @@ unsigned loBit = beginVarBit - N + 1; unsigned hiBit = loBit + N; unsigned loInstBit = beginInstBit - N + 1; + if (!BitOffsetCaseEmitted) { + BitOffsetCase += " case " + utostr(OpIdx) + ":\n"; + BitOffsetCase += " return " + + utostr(BI->getNumBits() - beginInstBit - 1) + ";\n"; + BitOffsetCaseEmitted = true; + } if (UseAPInt) { std::string extractStr; if (N >= 64) { @@ -246,46 +260,55 @@ return true; } -std::string CodeEmitterGen::getInstructionCase(Record *R, - CodeGenTarget &Target) { - std::string Case; +std::pair +CodeEmitterGen::getInstructionCases(Record *R, CodeGenTarget &Target) { + std::string Case, BitOffsetCase; + + auto append = [&](const char *S) { + Case += S; + BitOffsetCase += S; + }; + if (const RecordVal *RV = R->getValue("EncodingInfos")) { if (auto *DI = dyn_cast_or_null(RV->getValue())) { const CodeGenHwModes &HWM = Target.getHwModes(); EncodingInfoByHwMode EBM(DI->getDef(), HWM); - Case += " switch (HwMode) {\n"; - Case += " default: llvm_unreachable(\"Unhandled HwMode\");\n"; + append(" switch (HwMode) {\n"); + append(" default: llvm_unreachable(\"Unhandled HwMode\");\n"); for (auto &KV : EBM) { - Case += " case " + itostr(KV.first) + ": {\n"; - Case += getInstructionCaseForEncoding(R, KV.second, Target); - Case += " break;\n"; - Case += " }\n"; + append((" case " + itostr(KV.first) + ": {\n").c_str()); + addInstructionCasesForEncoding(R, KV.second, Target, Case, + BitOffsetCase); + append(" break;\n"); + append(" }\n"); } - Case += " }\n"; - return Case; + append(" }\n"); + return std::make_pair(std::move(Case), std::move(BitOffsetCase)); } } - return getInstructionCaseForEncoding(R, R, Target); + addInstructionCasesForEncoding(R, R, Target, Case, BitOffsetCase); + return std::make_pair(std::move(Case), std::move(BitOffsetCase)); } -std::string CodeEmitterGen::getInstructionCaseForEncoding(Record *R, Record *EncodingDef, - CodeGenTarget &Target) { - std::string Case; +void CodeEmitterGen::addInstructionCasesForEncoding( + Record *R, Record *EncodingDef, CodeGenTarget &Target, std::string &Case, + std::string &BitOffsetCase) { BitsInit *BI = EncodingDef->getValueAsBitsInit("Inst"); // Loop over all of the fields in the instruction, determining which are the // operands to the instruction. bool Success = true; + BitOffsetCase += " switch (OpNum) {\n"; for (const RecordVal &RV : EncodingDef->getValues()) { // Ignore fixed fields in the record, we're looking for values like: // bits<5> RST = { ?, ?, ?, ?, ? }; if (RV.isNonconcreteOK() || RV.getValue()->isComplete()) continue; - Success &= - addCodeToMergeInOperand(R, BI, std::string(RV.getName()), - Case, Target); + Success &= addCodeToMergeInOperand(R, BI, std::string(RV.getName()), Case, + BitOffsetCase, Target); } + BitOffsetCase += " }\n"; if (!Success) { // Dump the record, so we can see what's going on... @@ -304,8 +327,6 @@ Case += ", STI"; Case += ");\n"; } - - return Case; } static void emitInstBits(raw_ostream &OS, const APInt &Bits) { @@ -356,6 +377,26 @@ o << " UINT64_C(0)\n };\n"; } +void CodeEmitterGen::emitCaseMap( + raw_ostream &o, + const std::map> &CaseMap) { + std::map>::const_iterator IE, EE; + for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) { + const std::string &Case = IE->first; + const std::vector &InstList = IE->second; + + for (int i = 0, N = InstList.size(); i < N; i++) { + if (i) + o << "\n"; + o << " case " << InstList[i] << ":"; + } + o << " {\n"; + o << Case; + o << " break;\n" + << " }\n"; + } +} + void CodeEmitterGen::run(raw_ostream &o) { emitSourceFileHeader("Machine Code Emitter", o); @@ -437,17 +478,22 @@ // Map to accumulate all the cases. std::map> CaseMap; + std::map> BitOffsetCaseMap; // Construct all cases statement for each opcode + std::map>> + OperandBitOffsets; for (Record *R : Insts) { if (R->getValueAsString("Namespace") == "TargetOpcode" || R->getValueAsBit("isPseudo")) continue; std::string InstName = (R->getValueAsString("Namespace") + "::" + R->getName()).str(); - std::string Case = getInstructionCase(R, Target); + std::string Case, BitOffsetCase; + std::tie(Case, BitOffsetCase) = getInstructionCases(R, Target); - CaseMap[Case].push_back(std::move(InstName)); + CaseMap[Case].push_back(InstName); + BitOffsetCaseMap[BitOffsetCase].push_back(std::move(InstName)); } // Emit initial function code @@ -470,21 +516,7 @@ } // Emit each case statement - std::map>::iterator IE, EE; - for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) { - const std::string &Case = IE->first; - std::vector &InstList = IE->second; - - for (int i = 0, N = InstList.size(); i < N; i++) { - if (i) - o << "\n"; - o << " case " << InstList[i] << ":"; - } - o << " {\n"; - o << Case; - o << " break;\n" - << " }\n"; - } + emitCaseMap(o, CaseMap); // Default case: unhandled opcode o << " default:\n" @@ -498,6 +530,23 @@ else o << " return Value;\n"; o << "}\n\n"; + + o << "#ifdef GET_OPERAND_BIT_OFFSET\n" + << "#undef GET_OPERAND_BIT_OFFSET\n\n" + << "uint32_t " << Target.getName() + << "MCCodeEmitter::getOperandBitOffset(const MCInst &MI,\n" + << " unsigned OpNum,\n" + << " const MCSubtargetInfo &STI) const {\n" + << " switch (MI.getOpcode()) {\n"; + emitCaseMap(o, BitOffsetCaseMap); + o << " }\n" + << " std::string msg;\n" + << " raw_string_ostream Msg(msg);\n" + << " Msg << \"Not supported instr[opcode]: \" << MI << \"[\" << OpNum " + "<< \"]\";\n" + << " report_fatal_error(Msg.str().c_str());\n" + << "}\n\n" + << "#endif // GET_OPERAND_ENCODING_INFO\n\n"; } }