+void CodeEmitterGen::
+AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
+ unsigned &NumberedOp,
+ std::set<unsigned> &NamedOpIndices,
+ std::string &Case, CodeGenTarget &Target) {
+ CodeGenInstruction &CGI = Target.getInstruction(R);
+
+ // Determine if VarName actually contributes to the Inst encoding.
+ int bit = BI->getNumBits()-1;
+
+ // Scan for a bit that this contributed to.
+ for (; bit >= 0; ) {
+ if (getVariableBit(VarName, BI, bit) != -1)
+ break;
+
+ --bit;
+ }
+
+ // If we found no bits, ignore this value, otherwise emit the call to get the
+ // operand encoding.
+ if (bit < 0) return;
+
+ // If the operand matches by name, reference according to that
+ // operand number. Non-matching operands are assumed to be in
+ // order.
+ unsigned OpIdx;
+ if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
+ // Get the machine operand number for the indicated operand.
+ OpIdx = CGI.Operands[OpIdx].MIOperandNo;
+ assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
+ "Explicitly used operand also marked as not emitted!");
+ } else {
+ unsigned NumberOps = CGI.Operands.size();
+ /// If this operand is not supposed to be emitted by the
+ /// generated emitter, skip it.
+ while (NumberedOp < NumberOps &&
+ (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
+ (!NamedOpIndices.empty() && NamedOpIndices.count(
+ CGI.Operands.getSubOperandNumber(NumberedOp).first)))) {
+ ++NumberedOp;
+
+ if (NumberedOp >= CGI.Operands.back().MIOperandNo +
+ CGI.Operands.back().MINumOperands) {
+ errs() << "Too few operands in record " << R->getName() <<
+ " (no match for variable " << VarName << "):\n";
+ errs() << *R;
+ errs() << '\n';
+
+ return;
+ }
+ }
+
+ OpIdx = NumberedOp++;
+ }
+
+ std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
+ std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName;
+
+ // If the source operand has a custom encoder, use it. This will
+ // get the encoding for all of the suboperands.
+ if (!EncoderMethodName.empty()) {
+ // A custom encoder has all of the information for the
+ // sub-operands, if there are more than one, so only
+ // query the encoder once per source operand.
+ if (SO.second == 0) {
+ Case += " // op: " + VarName + "\n" +
+ " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
+ Case += ", Fixups, STI";
+ Case += ");\n";
+ }
+ } else {
+ Case += " // op: " + VarName + "\n" +
+ " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
+ Case += ", Fixups, STI";
+ Case += ");\n";
+ }
+
+ for (; bit >= 0; ) {
+ int varBit = getVariableBit(VarName, BI, bit);
+
+ // If this bit isn't from a variable, skip it.
+ if (varBit == -1) {
+ --bit;
+ continue;
+ }
+
+ // Figure out the consecutive range of bits covered by this operand, in
+ // order to generate better encoding code.
+ int beginInstBit = bit;
+ int beginVarBit = varBit;
+ int N = 1;
+ for (--bit; bit >= 0;) {
+ varBit = getVariableBit(VarName, BI, bit);
+ if (varBit == -1 || varBit != (beginVarBit - N)) break;
+ ++N;
+ --bit;
+ }
+
+ uint64_t opMask = ~(uint64_t)0 >> (64-N);
+ int opShift = beginVarBit - N + 1;
+ opMask <<= opShift;
+ opShift = beginInstBit - beginVarBit;
+
+ if (opShift > 0) {
+ Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) << " +
+ itostr(opShift) + ";\n";
+ } else if (opShift < 0) {
+ Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) >> " +
+ itostr(-opShift) + ";\n";
+ } else {
+ Case += " Value |= op & UINT64_C(" + utostr(opMask) + ");\n";
+ }
+ }
+}
+
+
+std::string CodeEmitterGen::getInstructionCase(Record *R,
+ CodeGenTarget &Target) {
+ std::string Case;
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+ const std::vector<RecordVal> &Vals = R->getValues();
+ unsigned NumberedOp = 0;
+
+ std::set<unsigned> NamedOpIndices;
+ // Collect the set of operand indices that might correspond to named
+ // operand, and skip these when assigning operands based on position.
+ if (Target.getInstructionSet()->
+ getValueAsBit("noNamedPositionallyEncodedOperands")) {
+ CodeGenInstruction &CGI = Target.getInstruction(R);
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ unsigned OpIdx;
+ if (!CGI.Operands.hasOperandNamed(Vals[i].getName(), OpIdx))
+ continue;
+
+ NamedOpIndices.insert(OpIdx);
+ }
+ }
+
+ // Loop over all of the fields in the instruction, determining which are the
+ // operands to the instruction.
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ // Ignore fixed fields in the record, we're looking for values like:
+ // bits<5> RST = { ?, ?, ?, ?, ? };
+ if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete())
+ continue;
+
+ AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp,
+ NamedOpIndices, Case, Target);
+ }
+
+ std::string PostEmitter = R->getValueAsString("PostEncoderMethod");
+ if (!PostEmitter.empty()) {
+ Case += " Value = " + PostEmitter + "(MI, Value";
+ Case += ", STI";
+ Case += ");\n";
+ }
+
+ return Case;
+}
+