forked from OSchip/llvm-project
[ARM] Refactor handling of IT mask operands.
During assembly, the mask operand to an IT instruction (storing the sequence of T/E for 'Then' and 'Else') is parsed out of the mnemonic into a representation that encodes 'Then' and 'Else' in the same way regardless of the condition code. At some point during encoding it has to be converted into the instruction encoding used in the architecture, in which the mask encodes a sequence of replacement low-order bits for the condition code, so that which bit value means 'then' and which 'else' depends on whether the original condition code had its low bit set. Previously, that transformation was done by processInstruction(), half way through assembly. So an MCOperand storing an IT mask would sometimes store it in one format, and sometimes in the other, depending on where in the assembly pipeline you were. You can see this in diagnostics from `llvm-mc -debug -triple=thumbv8a -show-inst`, for example: if you give it an instruction such as `itete eq`, you'd see an `<MCOperand Imm:5>` in a diagnostic become `<MCOperand Imm:11>` in the final output. Having the same data structure store values with time-dependent semantics is confusing already, and it will get more confusing when we introduce the MVE VPT instruction which reuses the Then/Else bitmask idea in a different context. So I'm refactoring: now, all `ARMOperand` and `MCOperand` representations of an IT mask work exactly the same way, namely, 0 means 'Then' and 1 means 'Else', regardless of what original predicate is being referred to. The architectural encoding of IT that depends on the original condition is now constructed at the point when we turn the `MCOperand` into the final instruction bit pattern, and decoded similarly in the disassembler. The previous condition-independent parse-time format used 0 for Else and 1 for Then. I've taken the opportunity to flip the sense of it while I'm changing all of this anyway, because it seems to me more natural to use 0 for 'leave the starting condition unchanged' and 1 for 'invert it', as if those bits were an XOR mask. Reviewers: ostannard Subscribers: javed.absar, kristof.beyls, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D63219 llvm-svn: 363244
This commit is contained in:
parent
86b7f865ac
commit
848d3d0d2c
|
@ -25,6 +25,7 @@ def it_mask_asmoperand : AsmOperandClass { let Name = "ITMask"; }
|
||||||
def it_mask : Operand<i32> {
|
def it_mask : Operand<i32> {
|
||||||
let PrintMethod = "printThumbITMask";
|
let PrintMethod = "printThumbITMask";
|
||||||
let ParserMatchClass = it_mask_asmoperand;
|
let ParserMatchClass = it_mask_asmoperand;
|
||||||
|
let EncoderMethod = "getITMaskOpValue";
|
||||||
}
|
}
|
||||||
|
|
||||||
// t2_shift_imm: An integer that encodes a shift amount and the type of shift
|
// t2_shift_imm: An integer that encodes a shift amount and the type of shift
|
||||||
|
|
|
@ -90,6 +90,16 @@ static cl::opt<bool> AddBuildAttributes("arm-add-build-attributes",
|
||||||
|
|
||||||
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
|
enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
|
||||||
|
|
||||||
|
static inline unsigned extractITMaskBit(unsigned Mask, unsigned Position) {
|
||||||
|
// Position==0 means we're not in an IT block at all. Position==1
|
||||||
|
// means we want the first state bit, which is always 0 (Then).
|
||||||
|
// Position==2 means we want the second state bit, stored at bit 3
|
||||||
|
// of Mask, and so on downwards. So (5 - Position) will shift the
|
||||||
|
// right bit down to bit 0, including the always-0 bit at bit 4 for
|
||||||
|
// the mandatory initial Then.
|
||||||
|
return (Mask >> (5 - Position) & 1);
|
||||||
|
}
|
||||||
|
|
||||||
class UnwindContext {
|
class UnwindContext {
|
||||||
using Locs = SmallVector<SMLoc, 4>;
|
using Locs = SmallVector<SMLoc, 4>;
|
||||||
|
|
||||||
|
@ -226,11 +236,10 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit the IT instruction
|
// Emit the IT instruction
|
||||||
unsigned Mask = getITMaskEncoding();
|
|
||||||
MCInst ITInst;
|
MCInst ITInst;
|
||||||
ITInst.setOpcode(ARM::t2IT);
|
ITInst.setOpcode(ARM::t2IT);
|
||||||
ITInst.addOperand(MCOperand::createImm(ITState.Cond));
|
ITInst.addOperand(MCOperand::createImm(ITState.Cond));
|
||||||
ITInst.addOperand(MCOperand::createImm(Mask));
|
ITInst.addOperand(MCOperand::createImm(ITState.Mask));
|
||||||
Out.EmitInstruction(ITInst, getSTI());
|
Out.EmitInstruction(ITInst, getSTI());
|
||||||
|
|
||||||
// Emit the conditonal instructions
|
// Emit the conditonal instructions
|
||||||
|
@ -288,27 +297,10 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||||
return MRI->getSubReg(QReg, ARM::dsub_0);
|
return MRI->getSubReg(QReg, ARM::dsub_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the encoding of the IT mask, as it will appear in an IT instruction.
|
|
||||||
unsigned getITMaskEncoding() {
|
|
||||||
assert(inITBlock());
|
|
||||||
unsigned Mask = ITState.Mask;
|
|
||||||
unsigned TZ = countTrailingZeros(Mask);
|
|
||||||
if ((ITState.Cond & 1) == 0) {
|
|
||||||
assert(Mask && TZ <= 3 && "illegal IT mask value!");
|
|
||||||
Mask ^= (0xE << TZ) & 0xF;
|
|
||||||
}
|
|
||||||
return Mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the condition code corresponding to the current IT block slot.
|
// Get the condition code corresponding to the current IT block slot.
|
||||||
ARMCC::CondCodes currentITCond() {
|
ARMCC::CondCodes currentITCond() {
|
||||||
unsigned MaskBit;
|
unsigned MaskBit = extractITMaskBit(ITState.Mask, ITState.CurPosition);
|
||||||
if (ITState.CurPosition == 1)
|
return MaskBit ? ARMCC::getOppositeCondition(ITState.Cond) : ITState.Cond;
|
||||||
MaskBit = 1;
|
|
||||||
else
|
|
||||||
MaskBit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
|
|
||||||
|
|
||||||
return MaskBit ? ITState.Cond : ARMCC::getOppositeCondition(ITState.Cond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invert the condition of the current IT block slot without changing any
|
// Invert the condition of the current IT block slot without changing any
|
||||||
|
@ -338,7 +330,7 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||||
// Keep any existing condition bits.
|
// Keep any existing condition bits.
|
||||||
NewMask |= ITState.Mask & (0xE << TZ);
|
NewMask |= ITState.Mask & (0xE << TZ);
|
||||||
// Insert the new condition bit.
|
// Insert the new condition bit.
|
||||||
NewMask |= (Cond == ITState.Cond) << TZ;
|
NewMask |= (Cond != ITState.Cond) << TZ;
|
||||||
// Move the trailing 1 down one bit.
|
// Move the trailing 1 down one bit.
|
||||||
NewMask |= 1 << (TZ - 1);
|
NewMask |= 1 << (TZ - 1);
|
||||||
ITState.Mask = NewMask;
|
ITState.Mask = NewMask;
|
||||||
|
@ -353,9 +345,10 @@ class ARMAsmParser : public MCTargetAsmParser {
|
||||||
ITState.IsExplicit = false;
|
ITState.IsExplicit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new explicit IT block with the given condition and mask. The mask
|
// Create a new explicit IT block with the given condition and mask.
|
||||||
// should be in the parsed format, with a 1 implying 't', regardless of the
|
// The mask should be in the format used in ARMOperand and
|
||||||
// low bit of the condition.
|
// MCOperand, with a 1 implying 'e', regardless of the low bit of
|
||||||
|
// the condition.
|
||||||
void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) {
|
void startExplicitITBlock(ARMCC::CondCodes Cond, unsigned Mask) {
|
||||||
assert(!inITBlock());
|
assert(!inITBlock());
|
||||||
ITState.Cond = Cond;
|
ITState.Cond = Cond;
|
||||||
|
@ -3355,10 +3348,10 @@ void ARMOperand::print(raw_ostream &OS) const {
|
||||||
break;
|
break;
|
||||||
case k_ITCondMask: {
|
case k_ITCondMask: {
|
||||||
static const char *const MaskStr[] = {
|
static const char *const MaskStr[] = {
|
||||||
"(invalid)", "(teee)", "(tee)", "(teet)",
|
"(invalid)", "(tttt)", "(ttt)", "(ttte)",
|
||||||
"(te)", "(tete)", "(tet)", "(tett)",
|
"(tt)", "(ttet)", "(tte)", "(ttee)",
|
||||||
"(t)", "(ttee)", "(tte)", "(ttet)",
|
"(t)", "(tett)", "(tet)", "(tete)",
|
||||||
"(tt)", "(ttte)", "(ttt)", "(tttt)"
|
"(te)", "(teet)", "(tee)", "(teee)",
|
||||||
};
|
};
|
||||||
assert((ITMask.Mask & 0xf) == ITMask.Mask);
|
assert((ITMask.Mask & 0xf) == ITMask.Mask);
|
||||||
OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
|
OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
|
||||||
|
@ -6272,11 +6265,14 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||||
|
|
||||||
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
|
Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
|
||||||
|
|
||||||
// Handle the IT instruction ITMask. Convert it to a bitmask. This
|
// Handle the mask for IT instructions. In ARMOperand and MCOperand,
|
||||||
// is the mask as it will be for the IT encoding if the conditional
|
// this is stored in a format independent of the condition code: the
|
||||||
// encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
|
// lowest set bit indicates the end of the encoding, and above that,
|
||||||
// where the conditional bit0 is zero, the instruction post-processing
|
// a 1 bit indicates 'else', and an 0 indicates 'then'. E.g.
|
||||||
// will adjust the mask accordingly.
|
// IT -> 1000
|
||||||
|
// ITx -> x100 (ITT -> 0100, ITE -> 1100)
|
||||||
|
// ITxy -> xy10 (e.g. ITET -> 1010)
|
||||||
|
// ITxyz -> xyz1 (e.g. ITEET -> 1101)
|
||||||
if (Mnemonic == "it") {
|
if (Mnemonic == "it") {
|
||||||
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
|
SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
|
||||||
if (ITMask.size() > 3) {
|
if (ITMask.size() > 3) {
|
||||||
|
@ -6289,7 +6285,7 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
|
||||||
return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
|
return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
|
||||||
}
|
}
|
||||||
Mask >>= 1;
|
Mask >>= 1;
|
||||||
if (ITMask[i - 1] == 't')
|
if (ITMask[i - 1] == 'e')
|
||||||
Mask |= 8;
|
Mask |= 8;
|
||||||
}
|
}
|
||||||
Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
|
Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
|
||||||
|
@ -6681,11 +6677,10 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
|
||||||
unsigned Cond = Inst.getOperand(0).getImm();
|
unsigned Cond = Inst.getOperand(0).getImm();
|
||||||
unsigned Mask = Inst.getOperand(1).getImm();
|
unsigned Mask = Inst.getOperand(1).getImm();
|
||||||
|
|
||||||
// Mask hasn't been modified to the IT instruction encoding yet so
|
// Conditions only allowing a 't' are those with no set bit except
|
||||||
// conditions only allowing a 't' are a block of 1s starting at bit 3
|
// the lowest-order one that indicates the end of the sequence. In
|
||||||
// followed by all 0s. Easiest way is to just list the 4 possibilities.
|
// other words, powers of 2.
|
||||||
if (Cond == ARMCC::AL && Mask != 8 && Mask != 12 && Mask != 14 &&
|
if (Cond == ARMCC::AL && countPopulation(Mask) != 1)
|
||||||
Mask != 15)
|
|
||||||
return Error(Loc, "unpredictable IT predicate sequence");
|
return Error(Loc, "unpredictable IT predicate sequence");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -9260,15 +9255,11 @@ bool ARMAsmParser::processInstruction(MCInst &Inst,
|
||||||
}
|
}
|
||||||
case ARM::ITasm:
|
case ARM::ITasm:
|
||||||
case ARM::t2IT: {
|
case ARM::t2IT: {
|
||||||
MCOperand &MO = Inst.getOperand(1);
|
|
||||||
unsigned Mask = MO.getImm();
|
|
||||||
ARMCC::CondCodes Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
|
|
||||||
|
|
||||||
// Set up the IT block state according to the IT instruction we just
|
// Set up the IT block state according to the IT instruction we just
|
||||||
// matched.
|
// matched.
|
||||||
assert(!inITBlock() && "nested IT blocks?!");
|
assert(!inITBlock() && "nested IT blocks?!");
|
||||||
startExplicitITBlock(Cond, Mask);
|
startExplicitITBlock(ARMCC::CondCodes(Inst.getOperand(0).getImm()),
|
||||||
MO.setImm(getITMaskEncoding());
|
Inst.getOperand(1).getImm());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ARM::t2LSLrr:
|
case ARM::t2LSLrr:
|
||||||
|
|
|
@ -63,22 +63,19 @@ namespace {
|
||||||
return ITStates.size() == 1;
|
return ITStates.size() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called when decoding an IT instruction. Sets the IT state for the following
|
// Called when decoding an IT instruction. Sets the IT state for
|
||||||
// instructions that for the IT block. Firstcond and Mask correspond to the
|
// the following instructions that for the IT block. Firstcond
|
||||||
// fields in the IT instruction encoding.
|
// corresponds to the field in the IT instruction encoding; Mask
|
||||||
|
// is in the MCOperand format in which 1 means 'else' and 0 'then'.
|
||||||
void setITState(char Firstcond, char Mask) {
|
void setITState(char Firstcond, char Mask) {
|
||||||
// (3 - the number of trailing zeros) is the number of then / else.
|
// (3 - the number of trailing zeros) is the number of then / else.
|
||||||
unsigned CondBit0 = Firstcond & 1;
|
|
||||||
unsigned NumTZ = countTrailingZeros<uint8_t>(Mask);
|
unsigned NumTZ = countTrailingZeros<uint8_t>(Mask);
|
||||||
unsigned char CCBits = static_cast<unsigned char>(Firstcond & 0xf);
|
unsigned char CCBits = static_cast<unsigned char>(Firstcond & 0xf);
|
||||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||||
// push condition codes onto the stack the correct order for the pops
|
// push condition codes onto the stack the correct order for the pops
|
||||||
for (unsigned Pos = NumTZ+1; Pos <= 3; ++Pos) {
|
for (unsigned Pos = NumTZ+1; Pos <= 3; ++Pos) {
|
||||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
unsigned Else = (Mask >> Pos) & 1;
|
||||||
if (T)
|
ITStates.push_back(CCBits ^ Else);
|
||||||
ITStates.push_back(CCBits);
|
|
||||||
else
|
|
||||||
ITStates.push_back(CCBits ^ 1);
|
|
||||||
}
|
}
|
||||||
ITStates.push_back(CCBits);
|
ITStates.push_back(CCBits);
|
||||||
}
|
}
|
||||||
|
@ -5176,6 +5173,16 @@ static DecodeStatus DecodeIT(MCInst &Inst, unsigned Insn,
|
||||||
if (mask == 0x0)
|
if (mask == 0x0)
|
||||||
return MCDisassembler::Fail;
|
return MCDisassembler::Fail;
|
||||||
|
|
||||||
|
// IT masks are encoded as a sequence of replacement low-order bits
|
||||||
|
// for the condition code. So if the low bit of the starting
|
||||||
|
// condition code is 1, then we have to flip all the bits above the
|
||||||
|
// terminating bit (which is the lowest 1 bit).
|
||||||
|
if (pred & 1) {
|
||||||
|
unsigned LowBit = mask & -mask;
|
||||||
|
unsigned BitsAboveLowBit = 0xF & (-LowBit << 1);
|
||||||
|
mask ^= BitsAboveLowBit;
|
||||||
|
}
|
||||||
|
|
||||||
Inst.addOperand(MCOperand::createImm(pred));
|
Inst.addOperand(MCOperand::createImm(pred));
|
||||||
Inst.addOperand(MCOperand::createImm(mask));
|
Inst.addOperand(MCOperand::createImm(mask));
|
||||||
return S;
|
return S;
|
||||||
|
|
|
@ -1039,16 +1039,13 @@ void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum,
|
||||||
raw_ostream &O) {
|
raw_ostream &O) {
|
||||||
// (3 - the number of trailing zeros) is the number of then / else.
|
// (3 - the number of trailing zeros) is the number of then / else.
|
||||||
unsigned Mask = MI->getOperand(OpNum).getImm();
|
unsigned Mask = MI->getOperand(OpNum).getImm();
|
||||||
unsigned Firstcond = MI->getOperand(OpNum - 1).getImm();
|
|
||||||
unsigned CondBit0 = Firstcond & 1;
|
|
||||||
unsigned NumTZ = countTrailingZeros(Mask);
|
unsigned NumTZ = countTrailingZeros(Mask);
|
||||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||||
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
||||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
if ((Mask >> Pos) & 1)
|
||||||
if (T)
|
|
||||||
O << 't';
|
|
||||||
else
|
|
||||||
O << 'e';
|
O << 'e';
|
||||||
|
else
|
||||||
|
O << 't';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,9 @@ public:
|
||||||
SmallVectorImpl<MCFixup> &Fixups,
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
const MCSubtargetInfo &STI) const;
|
const MCSubtargetInfo &STI) const;
|
||||||
|
|
||||||
|
uint32_t getITMaskOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
|
const MCSubtargetInfo &STI) const;
|
||||||
|
|
||||||
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
|
/// getAddrModeImm12OpValue - Return encoding info for 'reg +/- imm12'
|
||||||
/// operand.
|
/// operand.
|
||||||
|
@ -829,6 +832,33 @@ getT2AdrLabelOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
return Val;
|
return Val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getITMaskOpValue - Return the architectural encoding of an IT
|
||||||
|
/// predication mask, given the MCOperand format.
|
||||||
|
uint32_t ARMMCCodeEmitter::
|
||||||
|
getITMaskOpValue(const MCInst &MI, unsigned OpIdx,
|
||||||
|
SmallVectorImpl<MCFixup> &Fixups,
|
||||||
|
const MCSubtargetInfo &STI) const {
|
||||||
|
const MCOperand MaskMO = MI.getOperand(OpIdx);
|
||||||
|
assert(MaskMO.isImm() && "Unexpected operand type!");
|
||||||
|
|
||||||
|
unsigned Mask = MaskMO.getImm();
|
||||||
|
|
||||||
|
// IT masks are encoded as a sequence of replacement low-order bits
|
||||||
|
// for the condition code. So if the low bit of the starting
|
||||||
|
// condition code is 1, then we have to flip all the bits above the
|
||||||
|
// terminating bit (which is the lowest 1 bit).
|
||||||
|
assert(OpIdx > 0 && "IT mask appears first!");
|
||||||
|
const MCOperand CondMO = MI.getOperand(OpIdx-1);
|
||||||
|
assert(CondMO.isImm() && "Unexpected operand type!");
|
||||||
|
if (CondMO.getImm() & 1) {
|
||||||
|
unsigned LowBit = Mask & -Mask;
|
||||||
|
unsigned BitsAboveLowBit = 0xF & (-LowBit << 1);
|
||||||
|
Mask ^= BitsAboveLowBit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mask;
|
||||||
|
}
|
||||||
|
|
||||||
/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
|
/// getThumbAdrLabelOpValue - Return encoding info for 8-bit immediate ADR label
|
||||||
/// target.
|
/// target.
|
||||||
uint32_t ARMMCCodeEmitter::
|
uint32_t ARMMCCodeEmitter::
|
||||||
|
|
|
@ -245,7 +245,7 @@ bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
|
||||||
unsigned NPredReg = 0;
|
unsigned NPredReg = 0;
|
||||||
ARMCC::CondCodes NCC = getITInstrPredicate(*NMI, NPredReg);
|
ARMCC::CondCodes NCC = getITInstrPredicate(*NMI, NPredReg);
|
||||||
if (NCC == CC || NCC == OCC) {
|
if (NCC == CC || NCC == OCC) {
|
||||||
Mask |= (NCC & 1) << Pos;
|
Mask |= ((NCC ^ CC) & 1) << Pos;
|
||||||
// Add implicit use of ITSTATE.
|
// Add implicit use of ITSTATE.
|
||||||
NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
|
NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
|
||||||
true/*isImp*/, false/*isKill*/));
|
true/*isImp*/, false/*isKill*/));
|
||||||
|
@ -269,8 +269,6 @@ bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
|
||||||
|
|
||||||
// Finalize IT mask.
|
// Finalize IT mask.
|
||||||
Mask |= (1 << Pos);
|
Mask |= (1 << Pos);
|
||||||
// Tag along (firstcond[0] << 4) with the mask.
|
|
||||||
Mask |= (CC & 1) << 4;
|
|
||||||
MIB.addImm(Mask);
|
MIB.addImm(Mask);
|
||||||
|
|
||||||
// Last instruction in IT block kills ITSTATE.
|
// Last instruction in IT block kills ITSTATE.
|
||||||
|
|
Loading…
Reference in New Issue