@@ -259,8 +259,9 @@ void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
259
259
// the opcode descriptor (MCInstrDesc).
260
260
// 2. Uses start at index #(MCDesc.getNumDefs()).
261
261
// 3. There can only be a single optional register definition, an it is
262
- // always the last operand of the sequence (excluding extra operands
263
- // contributed by variadic opcodes).
262
+ // either the last operand of the sequence (excluding extra operands
263
+ // contributed by variadic opcodes) or one of the explicit register
264
+ // definitions. The latter occurs for some Thumb1 instructions.
264
265
//
265
266
// These assumptions work quite well for most out-of-order in-tree targets
266
267
// like x86. This is mainly because the vast majority of instructions is
@@ -308,12 +309,18 @@ void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
308
309
// The first NumExplicitDefs register operands are expected to be register
309
310
// definitions.
310
311
unsigned CurrentDef = 0 ;
312
+ unsigned OptionalDefIdx = MCDesc.getNumOperands () - 1 ;
311
313
unsigned i = 0 ;
312
314
for (; i < MCI.getNumOperands () && CurrentDef < NumExplicitDefs; ++i) {
313
315
const MCOperand &Op = MCI.getOperand (i);
314
316
if (!Op.isReg ())
315
317
continue ;
316
318
319
+ if (MCDesc.OpInfo [CurrentDef].isOptionalDef ()) {
320
+ OptionalDefIdx = CurrentDef++;
321
+ continue ;
322
+ }
323
+
317
324
WriteDescriptor &Write = ID.Writes [CurrentDef];
318
325
Write.OpIndex = i;
319
326
if (CurrentDef < NumWriteLatencyEntries) {
@@ -369,7 +376,7 @@ void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
369
376
370
377
if (MCDesc.hasOptionalDef ()) {
371
378
WriteDescriptor &Write = ID.Writes [NumExplicitDefs + NumImplicitDefs];
372
- Write.OpIndex = MCDesc. getNumOperands () - 1 ;
379
+ Write.OpIndex = OptionalDefIdx ;
373
380
// Assign a default latency for this write.
374
381
Write.Latency = ID.MaxLatency ;
375
382
Write.SClassOrWriteResourceID = 0 ;
0 commit comments