diff --git a/llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td b/llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td new file mode 100644 index 000000000000..27058baa73c0 --- /dev/null +++ b/llvm/test/TableGen/FixedLenDecoderEmitter/InitValue.td @@ -0,0 +1,35 @@ +// RUN: llvm-tblgen -gen-disassembler -I %p/../../../include %s | FileCheck %s + +include "llvm/Target/Target.td" + +def archInstrInfo : InstrInfo { } + +def arch : Target { + let InstructionSet = archInstrInfo; +} + +let OutOperandList = (outs), Size = 2 in { + +def foo : Instruction { + let InOperandList = (ins i32imm:$factor); + field bits<16> Inst; + field bits<16> SoftFail = 0; + bits<8> factor; + let factor{0} = 0; // zero initial value + let Inst{15-8} = factor{7-0}; + } + +def bar : Instruction { + let InOperandList = (ins i32imm:$factor); + field bits<16> Inst; + field bits<16> SoftFail = 0; + bits<8> factor; + let factor{0} = 1; // non-zero initial value + let Inst{15-8} = factor{7-0}; + } + +} + +// CHECK: tmp = fieldFromInstruction(insn, 9, 7) << 1; +// CHECK: tmp = 0x1; +// CHECK: tmp |= fieldFromInstruction(insn, 9, 7) << 1; diff --git a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp index f5e975d2e5ae..7a6f44b9ab6e 100644 --- a/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -64,9 +64,10 @@ struct OperandInfo { std::vector Fields; std::string Decoder; bool HasCompleteDecoder; + uint64_t InitValue; OperandInfo(std::string D, bool HCD) - : Decoder(std::move(D)), HasCompleteDecoder(HCD) {} + : Decoder(std::move(D)), HasCompleteDecoder(HCD), InitValue(0) {} void addField(unsigned Base, unsigned Width, unsigned Offset) { Fields.push_back(EncodingField(Base, Width, Offset)); @@ -1103,12 +1104,15 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, bool &OpHasCompleteDecoder) const { const std::string &Decoder = OpInfo.Decoder; - if (OpInfo.numFields() != 1) - o.indent(Indentation) << "tmp = 0;\n"; + if (OpInfo.numFields() != 1 || OpInfo.InitValue != 0) { + o.indent(Indentation) << "tmp = 0x"; + o.write_hex(OpInfo.InitValue); + o << ";\n"; + } for (const EncodingField &EF : OpInfo) { o.indent(Indentation) << "tmp "; - if (OpInfo.numFields() != 1) o << '|'; + if (OpInfo.numFields() != 1 || OpInfo.InitValue != 0) o << '|'; o << "= fieldFromInstruction" << "(insn, " << EF.Base << ", " << EF.Width << ')'; if (OpInfo.numFields() != 1 || EF.Offset != 0) @@ -2026,6 +2030,16 @@ populateInstruction(CodeGenTarget &Target, const Record &EncodingDef, HasCompleteDecoderBit->getValue() : true; OperandInfo OpInfo(Decoder, HasCompleteDecoder); + + // Some bits of the operand may be required to be 1 depending on the + // instruction's encoding. Collect those bits. + if (const RecordVal *EncodedValue = EncodingDef.getValue(Op.second)) + if (const BitsInit *OpBits = dyn_cast(EncodedValue->getValue())) + for (unsigned I = 0; I < OpBits->getNumBits(); ++I) + if (const BitInit *OpBit = dyn_cast(OpBits->getBit(I))) + if (OpBit->getValue()) + OpInfo.InitValue |= 1 << I; + unsigned Base = ~0U; unsigned Width = 0; unsigned Offset = 0;