Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(223)

Unified Diff: src/IceAssemblerARM32.cpp

Issue 1495093002: Improve error handling in the ARM integrated assembler. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix issues in last patch. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/IceAssemblerARM32.cpp
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 6b6dea5a2e9fb86c9fc78b171318bf11aef5d37f..fef7f6586b7de12732e3219d9c26120a1c49ec60 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -86,7 +86,6 @@ static constexpr IValueT kRotateShift = 8;
static constexpr IValueT kShiftImmShift = 7;
static constexpr IValueT kShiftImmBits = 5;
static constexpr IValueT kShiftShift = 5;
-
static constexpr IValueT kImmed12Bits = 12;
static constexpr IValueT kImm12Shift = 0;
@@ -113,33 +112,29 @@ static constexpr IOffsetT kPCReadOffset = 8;
static constexpr int kBranchOffsetBits = 24;
static constexpr IOffsetT kBranchOffsetMask = 0x00ffffff;
-inline IValueT encodeBool(bool B) { return B ? 1 : 0; }
+IValueT encodeBool(bool B) { return B ? 1 : 0; }
-inline IValueT encodeRotation(ARM32::AssemblerARM32::RotationValue Value) {
+IValueT encodeRotation(ARM32::AssemblerARM32::RotationValue Value) {
return static_cast<IValueT>(Value);
}
-inline IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) {
+IValueT encodeGPRRegister(RegARM32::GPRRegister Rn) {
return static_cast<IValueT>(Rn);
}
-inline RegARM32::GPRRegister decodeGPRRegister(IValueT R) {
+RegARM32::GPRRegister decodeGPRRegister(IValueT R) {
return static_cast<RegARM32::GPRRegister>(R);
}
-inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) {
- return R != RegARM32::Encoded_Not_GPR;
-}
-
-inline bool isGPRRegisterDefined(IValueT R) {
+bool isGPRRegisterDefined(IValueT R) {
return R != encodeGPRRegister(RegARM32::Encoded_Not_GPR);
}
-inline bool isConditionDefined(CondARM32::Cond Cond) {
+bool isConditionDefined(CondARM32::Cond Cond) {
return Cond != CondARM32::kNone;
}
-inline IValueT encodeCondition(CondARM32::Cond Cond) {
+IValueT encodeCondition(CondARM32::Cond Cond) {
return static_cast<IValueT>(Cond);
}
@@ -157,23 +152,20 @@ IValueT encodeShift(OperandARM32::ShiftKind Shift) {
case OperandARM32::RRX:
return 3; // 0b11
}
-
llvm::report_fatal_error("Unknown Shift value");
return 0;
}
// Returns the bits in the corresponding masked value.
-inline IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) {
+IValueT mask(IValueT Value, IValueT Shift, IValueT Bits) {
return (Value >> Shift) & ((1 << Bits) - 1);
}
// Extract out a Bit in Value.
-inline bool isBitSet(IValueT Bit, IValueT Value) {
- return (Value & Bit) == Bit;
-}
+bool isBitSet(IValueT Bit, IValueT Value) { return (Value & Bit) == Bit; }
// Returns the GPR register at given Shift in Value.
-inline RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
+RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
return decodeGPRRegister((Value >> Shift) & 0xF);
}
@@ -211,7 +203,7 @@ enum EncodedOperand {
};
// Sets Encoding to a rotated Imm8 encoding of Value, if possible.
-inline IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) {
+IValueT encodeRotatedImm8(IValueT RotateAmt, IValueT Immed8) {
assert(RotateAmt < (1 << kRotateBits));
assert(Immed8 < (1 << kImmed8Bits));
return (RotateAmt << kRotateShift) | (Immed8 << kImmed8Shift);
@@ -363,6 +355,58 @@ bool canEncodeBranchOffset(IOffsetT Offset) {
Utils::IsInt(kBranchOffsetBits, Offset >> 2);
}
+IValueT encodeRegister(const Operand *OpReg, const char *RegName,
+ const char *InstName) {
+ IValueT Reg = 0;
+ if (encodeOperand(OpReg, Reg) != EncodedAsRegister)
+ llvm::report_fatal_error(std::string(InstName) + ": Can't find register " +
+ RegName);
+ return Reg;
+}
+
+void verifyRegDefined(IValueT Reg, const char *RegName, const char *InstName) {
+ if (!BuildDefs::minimal() && !isGPRRegisterDefined(Reg))
Jim Stichnoth 2015/12/04 00:02:40 I think you should follow the usual BuildDefs patt
Karl 2015/12/04 15:29:30 Done.
+ llvm::report_fatal_error(std::string(InstName) + ": Can't find " + RegName);
+}
+
+void verifyCondDefined(CondARM32::Cond Cond, const char *InstName) {
+ if (!BuildDefs::minimal() && !isConditionDefined(Cond))
+ llvm::report_fatal_error(std::string(InstName) + ": Condition not defined");
+}
+
+void verifyPOrNotW(IValueT Address, const char *InstName) {
+ if (!BuildDefs::minimal() && !isBitSet(P, Address) && isBitSet(W, Address))
+ llvm::report_fatal_error(std::string(InstName) +
+ ": P=0 when W=1 not allowed");
+}
+
+void verifyRegsNotEq(IValueT Reg1, const char *Reg1Name, IValueT Reg2,
+ const char *Reg2Name, const char *InstName) {
+ if (!BuildDefs::minimal() && Reg1 == Reg2)
+ llvm::report_fatal_error(std::string(InstName) + ": " + Reg1Name + "=" +
+ Reg2Name + " not allowed");
+}
+
+void verifyRegNotPc(IValueT Reg, const char *RegName, const char *InstName) {
+ verifyRegsNotEq(Reg, RegName, RegARM32::Encoded_Reg_pc, "pc", InstName);
+}
+
+void verifyAddrRegNotPc(IValueT RegShift, IValueT Address, const char *RegName,
+ const char *InstName) {
+ if (!BuildDefs::minimal() &&
+ getGPRReg(RegShift, Address) == RegARM32::Encoded_Reg_pc)
+ llvm::report_fatal_error(std::string(InstName) + ": " + RegName +
+ "=pc not allowed");
+}
+
+void verifyRegNotPcWhenSetFlags(IValueT Reg, bool SetFlags,
+ const char *InstName) {
+ if (!BuildDefs::minimal() && SetFlags && (Reg == RegARM32::Encoded_Reg_pc))
+ llvm::report_fatal_error(std::string(InstName) + ": " +
+ RegARM32::RegNames[Reg] +
+ "=pc not allowed when CC=1");
+}
+
} // end of anonymous namespace
namespace Ice {
@@ -490,51 +534,46 @@ void AssemblerARM32::emitTextInst(const std::string &Text, SizeT InstSize) {
}
}
-void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Type,
+void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT InstType,
IValueT Opcode, bool SetFlags, IValueT Rn,
IValueT Rd, IValueT Imm12,
- EmitChecks RuleChecks) {
+ EmitChecks RuleChecks, const char *InstName) {
switch (RuleChecks) {
case NoChecks:
break;
case RdIsPcAndSetFlags:
- if ((Rd == RegARM32::Encoded_Reg_pc) && SetFlags)
- // Conditions of rule violated.
- return setNeedsTextFixup();
+ verifyRegNotPcWhenSetFlags(Rd, SetFlags, InstName);
break;
}
-
- if (!isGPRRegisterDefined(Rd) || !isConditionDefined(Cond))
- return setNeedsTextFixup();
+ verifyRegDefined(Rd, "Rd", InstName);
+ verifyCondDefined(Cond, InstName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
- (Type << kTypeShift) | (Opcode << kOpcodeShift) |
+ (InstType << kTypeShift) | (Opcode << kOpcodeShift) |
(encodeBool(SetFlags) << kSShift) |
(Rn << kRnShift) | (Rd << kRdShift) | Imm12;
emitInst(Encoding);
}
-void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd,
- const Operand *OpRn, const Operand *OpSrc1,
- bool SetFlags, CondARM32::Cond Cond,
- EmitChecks RuleChecks) {
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rn;
- if (encodeOperand(OpRn, Rn) != EncodedAsRegister)
- return setNeedsTextFixup();
- emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, RuleChecks);
+void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode,
+ const Operand *OpRd, const Operand *OpRn,
+ const Operand *OpSrc1, bool SetFlags,
+ EmitChecks RuleChecks, const char *InstName) {
+ IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
+ IValueT Rn = encodeRegister(OpRn, "Rn", InstName);
+ emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, RuleChecks, InstName);
}
-void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn,
- const Operand *OpSrc1, bool SetFlags,
- CondARM32::Cond Cond, EmitChecks RuleChecks) {
+void AssemblerARM32::emitType01(CondARM32::Cond Cond, IValueT Opcode,
+ IValueT Rd, IValueT Rn, const Operand *OpSrc1,
+ bool SetFlags, EmitChecks RuleChecks,
+ const char *InstName) {
IValueT Src1Value;
// TODO(kschimpf) Other possible decodings of data operations.
switch (encodeOperand(OpSrc1, Src1Value)) {
default:
+ // TODO(kschimpf): Figure out what additional cases need to be handled.
return setNeedsTextFixup();
case EncodedAsRegister: {
// XXX (register)
@@ -545,13 +584,13 @@ void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn,
constexpr IValueT Imm5 = 0;
Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Imm5);
emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value,
- RuleChecks);
+ RuleChecks, InstName);
return;
}
case EncodedAsShiftedRegister: {
// Form is defined in case EncodedAsRegister. (i.e. XXX (register)).
emitType01(Cond, kInstTypeDataRegister, Opcode, SetFlags, Rn, Rd, Src1Value,
- RuleChecks);
+ RuleChecks, InstName);
return;
}
case EncodedAsConstI32: {
@@ -559,7 +598,8 @@ void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn,
IValueT RotateAmt;
IValueT Imm8;
if (!OperandARM32FlexImm::canHoldImm(Src1Value, &RotateAmt, &Imm8))
- return setNeedsTextFixup();
+ llvm::report_fatal_error(std::string(InstName) +
+ ": Immediate rotated constant not valid");
Src1Value = encodeRotatedImm8(RotateAmt, Imm8);
// Intentionally fall to next case!
}
@@ -570,19 +610,18 @@ void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn,
// cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
emitType01(Cond, kInstTypeDataImmediate, Opcode, SetFlags, Rn, Rd,
- Src1Value, RuleChecks);
+ Src1Value, RuleChecks, InstName);
return;
}
}
}
void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset,
- bool Link) {
+ bool Link, const char *InstName) {
// cccc101liiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond, l=Link, and
// iiiiiiiiiiiiiiiiiiiiiiii=
// EncodedBranchOffset(cccc101l000000000000000000000000, Offset);
- if (!isConditionDefined(Cond))
- return setNeedsTextFixup();
+ verifyCondDefined(Cond, InstName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = static_cast<int32_t>(Cond) << kConditionShift |
5 << kTypeShift | (Link ? 1 : 0) << kLinkShift;
@@ -592,21 +631,22 @@ void AssemblerARM32::emitType05(CondARM32::Cond Cond, IOffsetT Offset,
void AssemblerARM32::emitBranch(Label *L, CondARM32::Cond Cond, bool Link) {
// TODO(kschimpf): Handle far jumps.
+ constexpr const char *BranchName = "b";
if (L->isBound()) {
const int32_t Dest = L->getPosition() - Buffer.size();
- emitType05(Cond, Dest, Link);
+ emitType05(Cond, Dest, Link, BranchName);
return;
}
const IOffsetT Position = Buffer.size();
// Use the offset field of the branch instruction for linking the sites.
- emitType05(Cond, L->getEncodedPosition(), Link);
+ emitType05(Cond, L->getEncodedPosition(), Link, BranchName);
if (!needsTextFixup())
L->linkTo(Position);
}
-void AssemblerARM32::emitCompareOp(IValueT Opcode, const Operand *OpRn,
- const Operand *OpSrc1,
- CondARM32::Cond Cond) {
+void AssemblerARM32::emitCompareOp(CondARM32::Cond Cond, IValueT Opcode,
+ const Operand *OpRn, const Operand *OpSrc1,
+ const char *InstName) {
// XXX (register)
// XXX<c> <Rn>, <Rm>{, <shift>}
//
@@ -622,17 +662,15 @@ void AssemblerARM32::emitCompareOp(IValueT Opcode, const Operand *OpRn,
// defining RotatedImm8.
constexpr bool SetFlags = true;
constexpr IValueT Rd = RegARM32::Encoded_Reg_r0;
- IValueT Rn;
- if (encodeOperand(OpRn, Rn) != EncodedAsRegister)
- return setNeedsTextFixup();
- emitType01(Opcode, Rd, Rn, OpSrc1, SetFlags, Cond, NoChecks);
+ IValueT Rn = encodeRegister(OpRn, "Rn", InstName);
+ emitType01(Cond, Opcode, Rd, Rn, OpSrc1, SetFlags, NoChecks, InstName);
}
void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
bool IsLoad, bool IsByte, IValueT Rt,
- IValueT Address) {
- if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond))
- return setNeedsTextFixup();
+ IValueT Address, const char *InstName) {
+ verifyRegDefined(Rt, "Rt", InstName);
+ verifyCondDefined(Cond, InstName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
(InstType << kTypeShift) | (IsLoad ? L : 0) |
@@ -642,11 +680,12 @@ void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType,
void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte,
IValueT Rt, const Operand *OpAddress,
- const TargetInfo &TInfo) {
+ const TargetInfo &TInfo, const char *InstName) {
IValueT Address;
switch (encodeAddress(OpAddress, Address, TInfo)) {
default:
- return setNeedsTextFixup();
+ llvm::report_fatal_error(std::string(InstName) +
+ ": Memory address not understood");
case EncodedAsImmRegOffset: {
// XXX{B} (immediate):
// xxx{b}<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
@@ -659,16 +698,16 @@ void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte,
RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
// Check if conditions of rules violated.
- if (Rn == RegARM32::Encoded_Reg_pc)
- return setNeedsTextFixup();
- if (!isBitSet(P, Address) && isBitSet(W, Address))
- return setNeedsTextFixup();
+ verifyRegNotPc(Rn, "Rn", InstName);
+ verifyPOrNotW(Address, InstName);
if (!IsByte && (Rn == RegARM32::Encoded_Reg_sp) && !isBitSet(P, Address) &&
- isBitSet(U, Address) & !isBitSet(W, Address) &&
+ isBitSet(U, Address) && !isBitSet(W, Address) &&
(mask(Address, kImm12Shift, kImmed12Bits) == 0x8 /* 000000000100 */))
- return setNeedsTextFixup();
+ llvm::report_fatal_error(std::string(InstName) +
+ ": Use push/pop instead");
- return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
+ return emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address,
+ InstName);
}
case EncodedAsShiftRotateImm5: {
// XXX{B} (register)
@@ -682,33 +721,29 @@ void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte,
RegARM32::GPRRegister Rm = getGPRReg(kRmShift, Address);
// Check if conditions of rules violated.
- if (isBitSet(P, Address) && isBitSet(W, Address))
- // Instruction XXXBT!
- return setNeedsTextFixup();
- if (IsByte &&
- ((Rt == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc)))
- // Unpredictable.
- return setNeedsTextFixup();
- if (!IsByte && Rm == RegARM32::Encoded_Reg_pc)
- // Unpredictable.
- return setNeedsTextFixup();
- if (isBitSet(W, Address) &&
- ((Rn == RegARM32::Encoded_Reg_pc) || encodeGPRRegister(Rn) == Rt))
- // Unpredictable
- return setNeedsTextFixup();
-
- return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address);
+ verifyPOrNotW(Address, InstName);
+ verifyRegNotPc(Rm, "Rm", InstName);
+ if (IsByte)
+ verifyRegNotPc(Rt, "Rt", InstName);
+ if (isBitSet(W, Address)) {
+ verifyRegNotPc(Rn, "Rn", InstName);
+ verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName);
+ }
+ return emitMemOp(Cond, kInstTypeRegisterShift, IsLoad, IsByte, Rt, Address,
+ InstName);
}
}
}
void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
IValueT Rt, const Operand *OpAddress,
- const TargetInfo &TInfo) {
+ const TargetInfo &TInfo,
+ const char *InstName) {
IValueT Address;
switch (encodeAddress(OpAddress, Address, TInfo, OpEncoding3)) {
default:
- return setNeedsTextFixup();
+ llvm::report_fatal_error(std::string(InstName) +
+ ": Memory address not understood");
case EncodedAsImmRegOffsetEnc3: {
// XXXH (immediate)
// xxxh<c> <Rt>, [<Rn>{, #+-<Imm8>}]
@@ -718,14 +753,12 @@ void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
// cccc000pu0wxnnnnttttiiiiyyyyjjjj where cccc=Cond, nnnn=Rn, tttt=Rt,
// iiiijjjj=Imm8, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode,
// and pu0w0nnnn0000iiii0000jjjj=Address.
- if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond))
- return setNeedsTextFixup();
- if (!isBitSet(P, Address) && isBitSet(W, Address))
- return setNeedsTextFixup();
- if ((Rt == RegARM32::Encoded_Reg_pc) ||
- (isBitSet(W, Address) &&
- (getGPRReg(kRnShift, Address) == decodeGPRRegister(Rt))))
- return setNeedsTextFixup();
+ verifyRegDefined(Rt, "Rt", InstName);
+ verifyCondDefined(Cond, InstName);
+ verifyPOrNotW(Address, InstName);
+ verifyRegNotPc(Rt, "Rt", InstName);
+ if (isBitSet(W, Address))
+ verifyRegsNotEq(getGPRReg(kRnShift, Address), "Rn", Rt, "Rt", InstName);
const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
Opcode | (Rt << kRdShift) | Address;
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
@@ -739,21 +772,20 @@ void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
// cccc000pu0wxnnnntttt00001011mmmm where cccc=Cond, tttt=Rt, nnnn=Rn,
// mmmm=Rm, pu0w<<21 is a BlockAddr, x000000000000yyyy0000=Opcode, and
// pu0w0nnnn000000000000mmmm=Address.
- if (!isGPRRegisterDefined(Rt) || !isConditionDefined(Cond))
- return setNeedsTextFixup();
- if (!isBitSet(P, Address) && isBitSet(W, Address))
- return setNeedsTextFixup();
- if (Rt == RegARM32::Encoded_Reg_pc)
- return setNeedsTextFixup();
- if (getGPRReg(kRmShift, Address) == RegARM32::Encoded_Reg_pc)
- return setNeedsTextFixup();
+ verifyRegDefined(Rt, "Rt", InstName);
+ verifyCondDefined(Cond, InstName);
+ verifyPOrNotW(Address, InstName);
+ verifyRegNotPc(Rt, "Rt", InstName);
+ verifyAddrRegNotPc(kRmShift, Address, "Rm", InstName);
const RegARM32::GPRRegister Rn = getGPRReg(kRnShift, Address);
- if (isBitSet(W, Address) &&
- ((Rn == RegARM32::Encoded_Reg_pc) || (encodeGPRRegister(Rn) == Rt)))
- return setNeedsTextFixup();
+ if (isBitSet(W, Address)) {
+ verifyRegNotPc(Rn, "Rn", InstName);
+ verifyRegsNotEq(Rn, "Rn", Rt, "Rt", InstName);
+ }
if (mask(Address, kShiftImmShift, 5) != 0)
// For encoding 3, no shift is allowed.
- return setNeedsTextFixup();
+ llvm::report_fatal_error(std::string(InstName) +
+ ": Shift constant not allowed");
const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) |
Opcode | (Rt << kRdShift) | Address;
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
@@ -763,10 +795,11 @@ void AssemblerARM32::emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode,
}
void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
- IValueT Rn, IValueT Rm) {
- if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) ||
- !isGPRRegisterDefined(Rm) || !isConditionDefined(Cond))
- return setNeedsTextFixup();
+ IValueT Rn, IValueT Rm, const char *InstName) {
+ verifyRegDefined(Rd, "Rd", InstName);
+ verifyRegDefined(Rn, "Rn", InstName);
+ verifyRegDefined(Rm, "Rm", InstName);
+ verifyCondDefined(Cond, InstName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) |
(Rn << kDivRnShift) | (Rd << kDivRdShift) | B26 |
@@ -777,11 +810,12 @@ void AssemblerARM32::emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
IValueT Rn, IValueT Rm, IValueT Rs,
- bool SetFlags) {
- if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) ||
- !isGPRRegisterDefined(Rm) || !isGPRRegisterDefined(Rs) ||
- !isConditionDefined(Cond))
- return setNeedsTextFixup();
+ bool SetFlags, const char *InstName) {
+ verifyRegDefined(Rd, "Rd", InstName);
+ verifyRegDefined(Rn, "Rn", InstName);
+ verifyRegDefined(Rm, "Rm", InstName);
+ verifyRegDefined(Rs, "Rs", InstName);
+ verifyCondDefined(Cond, InstName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) |
(encodeBool(SetFlags) << kSShift) | (Rn << kRnShift) |
@@ -791,10 +825,13 @@ void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
}
void AssemblerARM32::emitUxt(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
- IValueT Rn, IValueT Rm, RotationValue Rotation) {
+ IValueT Rn, IValueT Rm, RotationValue Rotation,
+ const char *InstName) {
+ verifyCondDefined(Cond, InstName);
IValueT Rot = encodeRotation(Rotation);
- if (!isConditionDefined(Cond) || !Utils::IsUint(2, Rot))
- return setNeedsTextFixup();
+ if (!Utils::IsUint(2, Rot))
+ llvm::report_fatal_error(std::string(InstName) +
+ ": Illegal rotation value");
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | Opcode |
(Rn << kRnShift) | (Rd << kRdShift) |
@@ -804,11 +841,14 @@ void AssemblerARM32::emitUxt(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
void AssemblerARM32::emitMultiMemOp(CondARM32::Cond Cond,
BlockAddressMode AddressMode, bool IsLoad,
- IValueT BaseReg, IValueT Registers) {
+ IValueT BaseReg, IValueT Registers,
+ const char *InstName) {
constexpr IValueT NumGPRegisters = 16;
- if (!isConditionDefined(Cond) || !isGPRRegisterDefined(BaseReg) ||
- Registers >= (1 << NumGPRegisters))
- return setNeedsTextFixup();
+ verifyCondDefined(Cond, InstName);
+ verifyRegDefined(BaseReg, "base", InstName);
+ if (Registers >= (1 << NumGPRegisters))
+ llvm::report_fatal_error(std::string(InstName) +
+ ": Register set too large");
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 |
AddressMode | (IsLoad ? L : 0) | (BaseReg << kRnShift) |
@@ -830,8 +870,10 @@ void AssemblerARM32::adc(const Operand *OpRd, const Operand *OpRn,
//
// cccc0010101snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
- constexpr IValueT Adc = B2 | B0; // 0101
- emitType01(Adc, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ constexpr const char *AdcName = "adc";
+ constexpr IValueT AdcOpcode = B2 | B0; // 0101
+ emitType01(Cond, AdcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ AdcName);
}
void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn,
@@ -852,8 +894,10 @@ void AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn,
//
// cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
+ constexpr const char *AddName = "add";
constexpr IValueT Add = B2; // 0100
- emitType01(Add, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ emitType01(Cond, Add, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ AddName);
}
void AssemblerARM32::and_(const Operand *OpRd, const Operand *OpRn,
@@ -870,8 +914,10 @@ void AssemblerARM32::and_(const Operand *OpRd, const Operand *OpRn,
//
// cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
+ constexpr const char *AndName = "and";
constexpr IValueT And = 0; // 0000
- emitType01(And, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ emitType01(Cond, And, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ AndName);
}
void AssemblerARM32::b(Label *L, CondARM32::Cond Cond) {
@@ -903,8 +949,10 @@ void AssemblerARM32::bic(const Operand *OpRd, const Operand *OpRn,
//
// cccc0011110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rn, nnnn=Rn,
// s=SetFlags, and iiiiiiiiiiii=Src1Value defining RotatedImm8.
- IValueT Opcode = B3 | B2 | B1; // i.e. 1110
- emitType01(Opcode, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ constexpr const char *BicName = "bic";
+ constexpr IValueT BicOpcode = B3 | B2 | B1; // i.e. 1110
+ emitType01(Cond, BicOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ BicName);
}
void AssemblerARM32::bl(const ConstantRelocatable *Target) {
@@ -914,24 +962,22 @@ void AssemblerARM32::bl(const ConstantRelocatable *Target) {
// cccc1011iiiiiiiiiiiiiiiiiiiiiiii where cccc=Cond (not currently allowed)
// and iiiiiiiiiiiiiiiiiiiiiiii is the (encoded) Target to branch to.
emitFixup(createBlFixup(Target));
+ constexpr const char *BlName = "bl";
constexpr CondARM32::Cond Cond = CondARM32::AL;
constexpr IValueT Immed = 0;
constexpr bool Link = true;
- emitType05(Cond, Immed, Link);
+ emitType05(Cond, Immed, Link, BlName);
}
void AssemblerARM32::blx(const Operand *Target) {
- IValueT Rm;
- if (encodeOperand(Target, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
// BLX (register) - ARM section A8.8.26, encoding A1:
// blx<c> <Rm>
//
// cccc000100101111111111110011mmmm where cccc=Cond (not currently allowed)
// and mmmm=Rm.
- if (Rm == RegARM32::Encoded_Reg_pc)
- // Unpredictable.
- return setNeedsTextFixup();
+ constexpr const char *BlxName = "Blx";
+ IValueT Rm = encodeRegister(Target, "Rm", BlxName);
+ verifyRegNotPc(Rm, "Rm", BlxName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
constexpr CondARM32::Cond Cond = CondARM32::AL;
int32_t Encoding = (encodeCondition(Cond) << kConditionShift) | B24 | B21 |
@@ -944,8 +990,9 @@ void AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
// bx<c> <Rm>
//
// cccc000100101111111111110001mmmm where mmmm=rm and cccc=Cond.
- if (!(isGPRRegisterDefined(Rm) && isConditionDefined(Cond)))
- return setNeedsTextFixup();
+ constexpr const char *BxName = "bx";
+ verifyCondDefined(Cond, BxName);
+ verifyRegDefined(Rm, "Rm", BxName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B24 |
B21 | (0xfff << 8) | B4 |
@@ -966,8 +1013,9 @@ void AssemblerARM32::cmp(const Operand *OpRn, const Operand *OpSrc1,
//
// cccc00110101nnnn0000iiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
- constexpr IValueT Opcode = B3 | B1; // ie. 1010
- emitCompareOp(Opcode, OpRn, OpSrc1, Cond);
+ constexpr const char *CmpName = "cmp";
+ constexpr IValueT CmpOpcode = B3 | B1; // ie. 1010
+ emitCompareOp(Cond, CmpOpcode, OpRn, OpSrc1, CmpName);
}
void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn,
@@ -984,16 +1032,17 @@ void AssemblerARM32::eor(const Operand *OpRd, const Operand *OpRn,
//
// cccc0010001snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
- constexpr IValueT Eor = B0; // 0001
- emitType01(Eor, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ constexpr const char *EorName = "eor";
+ constexpr IValueT EorOpcode = B0; // 0001
+ emitType01(Cond, EorOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ EorName);
}
void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
CondARM32::Cond Cond, const TargetInfo &TInfo) {
+ constexpr const char *LdrName = "ldr";
constexpr bool IsLoad = true;
- IValueT Rt;
- if (encodeOperand(OpRt, Rt) != EncodedAsRegister)
- return setNeedsTextFixup();
+ IValueT Rt = encodeRegister(OpRt, "Rt", LdrName);
const Type Ty = OpRt->getType();
switch (typeWidthInBytesLog2(Ty)) {
case 3:
@@ -1001,8 +1050,8 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
// using two (32-bit) load instructions. Note: Intenionally drop to default
// case.
default:
- llvm::report_fatal_error(std::string("Type ") + typeString(Ty) +
- " not implementable using ldr\n");
+ llvm::report_fatal_error(std::string("ldr : Type ") + typeString(Ty) +
+ " not implementable\n");
case 0: {
// Handles i1 and i8 loads.
//
@@ -1022,7 +1071,7 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
// cccc011pu1w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
// is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
constexpr bool IsByte = true;
- return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
}
case 1: {
// Handles i16 loads.
@@ -1035,7 +1084,8 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
// cccc000pu1w1nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
// iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
// pu0w0nnnn0000iiiiiiiiiiii=Address.
- return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo);
+ constexpr const char *Ldrh = "ldrh";
+ return emitMemOpEnc3(Cond, L | B7 | B5 | B4, Rt, OpAddress, TInfo, Ldrh);
}
case 2: {
// Note: Handles i32 and float loads. Target lowering handles i64 and
@@ -1056,7 +1106,7 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
// cccc011pu0w1nnnnttttiiiiiss0mmmm where cccc=Cond, tttt=Rt, U=1 if +, pu0b
// is a BlockAddr, and pu0w0nnnn0000iiiiiss0mmmm=Address.
constexpr bool IsByte = false;
- return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, LdrName);
}
}
}
@@ -1064,27 +1114,25 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
- constexpr IValueT Lsl = B3 | B2 | B0; // 1101
- constexpr IValueT Rn = 0; // Rn field is not used.
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rm;
- if (encodeOperand(OpRm, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
+ constexpr const char *LslName = "lsl";
+ IValueT Rd = encodeRegister(OpRd, "Rd", LslName);
+ IValueT Rm = encodeRegister(OpRm, "Rm", LslName);
IValueT Value;
switch (encodeOperand(OpSrc1, Value)) {
default:
- return setNeedsTextFixup();
+ llvm::report_fatal_error(std::string(LslName) +
+ ": Last operand not understood");
case EncodedAsShiftImm5: {
// LSL (immediate) - ARM section A8.8.94, encoding A1:
// lsl{s}<c> <Rd>, <Rm>, #imm5
//
// cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
// iiiii=imm5, and mmmm=Rm.
+ constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101
+ constexpr IValueT Rn = 0; // Rn field is not used.
Value = Value | (Rm << kRmShift);
- emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd, Value,
- RdIsPcAndSetFlags);
+ emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd, Value,
+ RdIsPcAndSetFlags, LslName);
return;
}
case EncodedAsRegister: {
@@ -1093,14 +1141,15 @@ void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm,
//
// cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
// mmmm=Rm, and ssss=Rs.
- IValueT Rs;
- if (encodeOperand(OpSrc1, Rs) != EncodedAsRegister)
- return setNeedsTextFixup();
- if ((Rd == RegARM32::Encoded_Reg_pc) || (Rm == RegARM32::Encoded_Reg_pc) ||
- (Rs == RegARM32::Encoded_Reg_pc))
- setNeedsTextFixup();
- emitType01(Cond, kInstTypeDataRegShift, Lsl, SetFlags, Rn, Rd,
- encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks);
+ constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101
+ constexpr IValueT Rn = 0; // Rn field is not used.
+ IValueT Rs = encodeRegister(OpSrc1, "Rs", LslName);
+ verifyRegNotPc(Rd, "Rd", LslName);
+ verifyRegNotPc(Rm, "Rm", LslName);
+ verifyRegNotPc(Rs, "Rs", LslName);
+ emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd,
+ encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks,
+ LslName);
return;
}
}
@@ -1120,19 +1169,21 @@ void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
// cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags, dddd=Rd,
// and iiiiiiiiiiii=RotatedImm8=Src. Note: We don't use movs in this
// assembler.
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
+ constexpr const char *MovName = "mov";
+ IValueT Rd = encodeRegister(OpRd, "Rd", MovName);
constexpr bool SetFlags = false;
constexpr IValueT Rn = 0;
- constexpr IValueT Mov = B3 | B2 | B0; // 1101.
- emitType01(Mov, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags);
+ constexpr IValueT MovOpcode = B3 | B2 | B0; // 1101.
+ emitType01(Cond, MovOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags,
+ MovName);
}
void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16,
bool SetFlags, CondARM32::Cond Cond) {
- if (!isConditionDefined(Cond) || !Utils::IsAbsoluteUint(16, Imm16))
- return setNeedsTextFixup();
+ constexpr const char *MovwName = "movw";
+ verifyCondDefined(Cond, MovwName);
+ if (!Utils::IsAbsoluteUint(16, Imm16))
+ llvm::report_fatal_error(std::string(MovwName) + ": Not I16 constant");
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode |
(encodeBool(SetFlags) << kSShift) |
@@ -1143,18 +1194,15 @@ void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16,
void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) {
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
+ constexpr const char *MovwName = "movw";
+ IValueT Rd = encodeRegister(OpRd, "Rd", MovwName);
if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) {
// MOVW (immediate) - ARM section A8.8.102, encoding A2:
// movw<c> <Rd>, #<imm16>
//
// cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
// iiiiiiiiiiiiiiii=imm16.
- if (!isConditionDefined(Cond))
- // Conditions of rule violated.
- return setNeedsTextFixup();
+ verifyCondDefined(Cond, MovwName);
// Use 0 for the lower 16 bits of the relocatable, and add a fixup to
// install the correct bits.
constexpr bool IsMovW = true;
@@ -1166,7 +1214,8 @@ void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
}
IValueT ConstVal;
if (encodeOperand(OpSrc, ConstVal) != EncodedAsConstI32)
- return setNeedsTextFixup();
+ llvm::report_fatal_error(std::string(MovwName) + ": Constant not i32");
+
// TODO(kschimpf): Determine if we want to handle rotated immediate 8 values
// to handle cases where the constant is greater than 16 bits (encoding A1
// below). For now, handle using encoding A2.
@@ -1183,20 +1232,18 @@ void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) {
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
- auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc);
- if (Src == nullptr)
- return setNeedsTextFixup();
// MOVT - ARM section A8.8.102, encoding A2:
// movt<c> <Rd>, #<imm16>
//
// cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
// iiiiiiiiiiiiiiii=imm16.
- if (!isConditionDefined(Cond))
- // Conditions of rule violated.
+ constexpr const char *MovtName = "movt";
+ IValueT Rd = encodeRegister(OpRd, "Rd", MovtName);
+ auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc);
+ if (!Src)
+ // TODO(kschimpf) Figure out what else can appear here.
return setNeedsTextFixup();
+ verifyCondDefined(Cond, MovtName);
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
// Use 0 for the lower 16 bits of the relocatable, and add a fixup to
// install the correct bits.
@@ -1222,13 +1269,13 @@ void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc,
//
// cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd,
// mmmm=Rm, iiii defines shift constant, and tt=ShiftKind.
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
+ constexpr const char *MvnName = "mvn";
+ IValueT Rd = encodeRegister(OpRd, "Rd", MvnName);
constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111
constexpr IValueT Rn = 0;
constexpr bool SetFlags = false;
- emitType01(MvnOpcode, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags);
+ emitType01(Cond, MvnOpcode, Rd, Rn, OpSrc, SetFlags, RdIsPcAndSetFlags,
+ MvnName);
}
void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn,
@@ -1245,8 +1292,10 @@ void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn,
//
// cccc0010110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
- constexpr IValueT Sbc = B2 | B1; // 0110
- emitType01(Sbc, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ constexpr const char *SbcName = "sbc";
+ constexpr IValueT SbcOpcode = B2 | B1; // 0110
+ emitType01(Cond, SbcOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ SbcName);
}
void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn,
@@ -1256,29 +1305,23 @@ void AssemblerARM32::sdiv(const Operand *OpRd, const Operand *OpRn,
//
// cccc01110001dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
// mmmm=Rm.
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rn;
- if (encodeOperand(OpRn, Rn) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rm;
- if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
- if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc ||
- Rm == RegARM32::Encoded_Reg_pc)
- llvm::report_fatal_error("Sdiv instruction unpredictable on pc");
+ constexpr const char *SdivName = "sdiv";
+ IValueT Rd = encodeRegister(OpRd, "Rd", SdivName);
+ IValueT Rn = encodeRegister(OpRn, "Rn", SdivName);
+ IValueT Rm = encodeRegister(OpSrc1, "Rm", SdivName);
+ verifyRegNotPc(Rd, "Rd", SdivName);
+ verifyRegNotPc(Rn, "Rn", SdivName);
+ verifyRegNotPc(Rm, "Rm", SdivName);
// Assembler registers rd, rn, rm are encoded as rn, rm, rs.
- constexpr IValueT Opcode = 0;
- emitDivOp(Cond, Opcode, Rd, Rn, Rm);
+ constexpr IValueT SdivOpcode = 0;
+ emitDivOp(Cond, SdivOpcode, Rd, Rn, Rm, SdivName);
}
void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
CondARM32::Cond Cond, const TargetInfo &TInfo) {
+ constexpr const char *StrName = "str";
constexpr bool IsLoad = false;
- IValueT Rt;
- if (encodeOperand(OpRt, Rt) != EncodedAsRegister)
- return setNeedsTextFixup();
+ IValueT Rt = encodeRegister(OpRt, "Rt", StrName);
const Type Ty = OpRt->getType();
switch (typeWidthInBytesLog2(Ty)) {
case 3:
@@ -1286,8 +1329,8 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
// using two (32-bit) store instructions. Note: Intenionally drop to
// default case.
default:
- llvm::report_fatal_error(std::string("Type ") + typeString(Ty) +
- " not implementable using str\n");
+ llvm::report_fatal_error(std::string(StrName) + ": Type " + typeString(Ty) +
+ " not implemented");
case 0: {
// Handles i1 and i8 stores.
//
@@ -1299,7 +1342,7 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
// cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
// iiiiiiiiiiii=imm12, u=1 if +.
constexpr bool IsByte = true;
- return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
}
case 1: {
// Handles i16 stores.
@@ -1312,7 +1355,8 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
// cccc000pu1w0nnnnttttiiii1011iiii where cccc=Cond, tttt=Rt, nnnn=Rn,
// iiiiiiii=Imm8, u=1 if +, pu0w is a BlockAddr, and
// pu0w0nnnn0000iiiiiiiiiiii=Address.
- return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo);
+ constexpr const char *Strh = "strh";
+ return emitMemOpEnc3(Cond, B7 | B5 | B4, Rt, OpAddress, TInfo, Strh);
}
case 2: {
// Note: Handles i32 and float stores. Target lowering handles i64 and
@@ -1326,7 +1370,7 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
// cccc010pu1w0nnnnttttiiiiiiiiiiii where cccc=Cond, tttt=Rt, nnnn=Rn,
// iiiiiiiiiiii=imm12, u=1 if +.
constexpr bool IsByte = false;
- return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo);
+ return emitMemOp(Cond, IsLoad, IsByte, Rt, OpAddress, TInfo, StrName);
return setNeedsTextFixup();
}
}
@@ -1346,8 +1390,10 @@ void AssemblerARM32::orr(const Operand *OpRd, const Operand *OpRn,
//
// cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
- constexpr IValueT Orr = B3 | B2; // i.e. 1100
- emitType01(Orr, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ constexpr const char *OrrName = "orr";
+ constexpr IValueT OrrOpcode = B3 | B2; // i.e. 1100
+ emitType01(Cond, OrrOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ OrrName);
}
void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) {
@@ -1355,16 +1401,15 @@ void AssemblerARM32::pop(const Operand *OpRt, CondARM32::Cond Cond) {
// pop<c> {Rt}
//
// cccc010010011101dddd000000000100 where dddd=Rt and cccc=Cond.
- IValueT Rt;
- if (encodeOperand(OpRt, Rt) != EncodedAsRegister)
- return setNeedsTextFixup();
- assert(Rt != RegARM32::Encoded_Reg_sp);
+ constexpr const char *Pop = "pop";
+ IValueT Rt = encodeRegister(OpRt, "Rt", Pop);
+ verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Pop);
// Same as load instruction.
constexpr bool IsLoad = true;
constexpr bool IsByte = false;
IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, kWordSize,
OperandARM32Mem::PostIndex);
- emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
+ emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address, Pop);
}
void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) {
@@ -1373,8 +1418,10 @@ void AssemblerARM32::popList(const IValueT Registers, CondARM32::Cond Cond) {
//
// cccc100010111101rrrrrrrrrrrrrrrr where cccc=Cond and
// rrrrrrrrrrrrrrrr=Registers (one bit for each GP register).
+ constexpr const char *PopListName = "pop {}";
constexpr bool IsLoad = true;
- emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers);
+ emitMultiMemOp(Cond, IA_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers,
+ PopListName);
}
void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) {
@@ -1382,16 +1429,15 @@ void AssemblerARM32::push(const Operand *OpRt, CondARM32::Cond Cond) {
// push<c> {Rt}
//
// cccc010100101101dddd000000000100 where dddd=Rt and cccc=Cond.
- IValueT Rt;
- if (encodeOperand(OpRt, Rt) != EncodedAsRegister)
- return setNeedsTextFixup();
- assert(Rt != RegARM32::Encoded_Reg_sp);
+ constexpr const char *Push = "push";
+ IValueT Rt = encodeRegister(OpRt, "Rt", Push);
+ verifyRegsNotEq(Rt, "Rt", RegARM32::Encoded_Reg_sp, "sp", Push);
// Same as store instruction.
constexpr bool isLoad = false;
constexpr bool isByte = false;
IValueT Address = encodeImmRegOffset(RegARM32::Encoded_Reg_sp, -kWordSize,
OperandARM32Mem::PreIndex);
- emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address);
+ emitMemOp(Cond, kInstTypeMemImmediate, isLoad, isByte, Rt, Address, Push);
}
void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) {
@@ -1400,62 +1446,54 @@ void AssemblerARM32::pushList(const IValueT Registers, CondARM32::Cond Cond) {
//
// cccc100100101101rrrrrrrrrrrrrrrr where cccc=Cond and
// rrrrrrrrrrrrrrrr=Registers (one bit for each GP register).
+ constexpr const char *PushListName = "push {}";
constexpr bool IsLoad = false;
- emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers);
+ emitMultiMemOp(Cond, DB_W, IsLoad, RegARM32::Encoded_Reg_sp, Registers,
+ PushListName);
}
void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn,
const Operand *OpRm, const Operand *OpRa,
CondARM32::Cond Cond) {
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rn;
- if (encodeOperand(OpRn, Rn) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rm;
- if (encodeOperand(OpRm, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Ra;
- if (encodeOperand(OpRa, Ra) != EncodedAsRegister)
- return setNeedsTextFixup();
// MLA - ARM section A8.8.114, encoding A1.
// mla{s}<c> <Rd>, <Rn>, <Rm>, <Ra>
//
// cccc0000001sddddaaaammmm1001nnnn where cccc=Cond, s=SetFlags, dddd=Rd,
// aaaa=Ra, mmmm=Rm, and nnnn=Rn.
- if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc ||
- Rm == RegARM32::Encoded_Reg_pc || Ra == RegARM32::Encoded_Reg_pc)
- llvm::report_fatal_error("Mul instruction unpredictable on pc");
+ constexpr const char *MlaName = "mla";
+ IValueT Rd = encodeRegister(OpRd, "Rd", MlaName);
+ IValueT Rn = encodeRegister(OpRn, "Rn", MlaName);
+ IValueT Rm = encodeRegister(OpRm, "Rm", MlaName);
+ IValueT Ra = encodeRegister(OpRa, "Ra", MlaName);
+ verifyRegNotPc(Rd, "Rd", MlaName);
+ verifyRegNotPc(Rn, "Rn", MlaName);
+ verifyRegNotPc(Rm, "Rm", MlaName);
+ verifyRegNotPc(Ra, "Ra", MlaName);
constexpr IValueT MlaOpcode = B21;
constexpr bool SetFlags = false;
// Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
- emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, SetFlags);
+ emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, SetFlags, MlaName);
}
void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rn;
- if (encodeOperand(OpRn, Rn) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rm;
- if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
// MUL - ARM section A8.8.114, encoding A1.
// mul{s}<c> <Rd>, <Rn>, <Rm>
//
// cccc0000000sdddd0000mmmm1001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn,
// mmmm=Rm, and s=SetFlags.
- if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc ||
- Rm == RegARM32::Encoded_Reg_pc)
- llvm::report_fatal_error("Mul instruction unpredictable on pc");
+ constexpr const char *MulName = "mul";
+ IValueT Rd = encodeRegister(OpRd, "Rd", MulName);
+ IValueT Rn = encodeRegister(OpRn, "Rn", MulName);
+ IValueT Rm = encodeRegister(OpSrc1, "Rm", MulName);
+ verifyRegNotPc(Rd, "Rd", MulName);
+ verifyRegNotPc(Rn, "Rn", MulName);
+ verifyRegNotPc(Rm, "Rm", MulName);
// Assembler registers rd, rn, rm are encoded as rn, rm, rs.
constexpr IValueT MulOpcode = 0;
- emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags);
+ emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags,
+ MulName);
}
void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn,
@@ -1465,21 +1503,16 @@ void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn,
//
// cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
// mmmm=Rm.
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rn;
- if (encodeOperand(OpRn, Rn) != EncodedAsRegister)
- return setNeedsTextFixup();
- IValueT Rm;
- if (encodeOperand(OpSrc1, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
- if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc ||
- Rm == RegARM32::Encoded_Reg_pc)
- llvm::report_fatal_error("Udiv instruction unpredictable on pc");
+ constexpr const char *UdivName = "udiv";
+ IValueT Rd = encodeRegister(OpRd, "Rd", UdivName);
+ IValueT Rn = encodeRegister(OpRn, "Rn", UdivName);
+ IValueT Rm = encodeRegister(OpSrc1, "Rm", UdivName);
+ verifyRegNotPc(Rd, "Rd", UdivName);
+ verifyRegNotPc(Rn, "Rn", UdivName);
+ verifyRegNotPc(Rm, "Rm", UdivName);
// Assembler registers rd, rn, rm are encoded as rn, rm, rs.
- constexpr IValueT Opcode = B21;
- emitDivOp(Cond, Opcode, Rd, Rn, Rm);
+ constexpr IValueT UdivOpcode = B21;
+ emitDivOp(Cond, UdivOpcode, Rd, Rn, Rm, UdivName);
}
void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
@@ -1500,8 +1533,10 @@ void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
//
// cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8
- constexpr IValueT Sub = B1; // 0010
- emitType01(Sub, OpRd, OpRn, OpSrc1, SetFlags, Cond, RdIsPcAndSetFlags);
+ constexpr const char *SubName = "sub";
+ constexpr IValueT SubOpcode = B1; // 0010
+ emitType01(Cond, SubOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
+ SubName);
}
void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1,
@@ -1517,8 +1552,9 @@ void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1,
//
// cccc00110001nnnn0000iiiiiiiiiiii where cccc=Cond, nnnn=Rn, and
// iiiiiiiiiiii defines RotatedImm8.
- constexpr IValueT Opcode = B3; // ie. 1000
- emitCompareOp(Opcode, OpRn, OpSrc1, Cond);
+ constexpr const char *TstName = "tst";
+ constexpr IValueT TstOpcode = B3; // ie. 1000
+ emitCompareOp(Cond, TstOpcode, OpRn, OpSrc1, TstName);
}
void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi,
@@ -1529,45 +1565,40 @@ void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi,
//
// cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn,
// mmmm=Rm, and s=SetFlags
- IValueT RdLo;
- IValueT RdHi;
- IValueT Rn;
- IValueT Rm;
- if (encodeOperand(OpRdLo, RdLo) != EncodedAsRegister ||
- encodeOperand(OpRdHi, RdHi) != EncodedAsRegister ||
- encodeOperand(OpRn, Rn) != EncodedAsRegister ||
- encodeOperand(OpRm, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
- if (RdHi == RegARM32::Encoded_Reg_pc || RdLo == RegARM32::Encoded_Reg_pc ||
- Rn == RegARM32::Encoded_Reg_pc || Rm == RegARM32::Encoded_Reg_pc ||
- RdHi == RdLo)
- llvm::report_fatal_error("Umull instruction unpredictable on pc");
+ constexpr const char *UmullName = "umull";
+ IValueT RdLo = encodeRegister(OpRdLo, "RdLo", UmullName);
+ IValueT RdHi = encodeRegister(OpRdHi, "RdHi", UmullName);
+ IValueT Rn = encodeRegister(OpRn, "Rn", UmullName);
+ IValueT Rm = encodeRegister(OpRm, "Rm", UmullName);
+ verifyRegNotPc(RdLo, "RdLo", UmullName);
+ verifyRegNotPc(RdHi, "RdHi", UmullName);
+ verifyRegNotPc(Rn, "Rn", UmullName);
+ verifyRegNotPc(Rm, "Rm", UmullName);
+ verifyRegsNotEq(RdHi, "RdHi", RdLo, "RdLo", UmullName);
+ constexpr IValueT UmullOpcode = B23;
constexpr bool SetFlags = false;
- emitMulOp(Cond, B23, RdLo, RdHi, Rn, Rm, SetFlags);
+ emitMulOp(Cond, UmullOpcode, RdLo, RdHi, Rn, Rm, SetFlags, UmullName);
}
void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
CondARM32::Cond Cond) {
- IValueT Rd;
- if (encodeOperand(OpRd, Rd) != EncodedAsRegister)
- return setNeedsTextFixup();
+ constexpr const char *UxtName = "uxt";
+ IValueT Rd = encodeRegister(OpRd, "Rd", UxtName);
+ IValueT Rm = encodeRegister(OpSrc0, "Rm", UxtName);
// Note: For the moment, we assume no rotation is specified.
RotationValue Rotation = kRotateNone;
constexpr IValueT Rn = RegARM32::Encoded_Reg_pc;
- IValueT Rm;
- if (encodeOperand(OpSrc0, Rm) != EncodedAsRegister)
- return setNeedsTextFixup();
switch (typeWidthInBytes(OpSrc0->getType())) {
default:
- return setNeedsTextFixup();
+ llvm::report_fatal_error("Type of Rm not understood: uxt");
case 1: {
// UXTB - ARM section A8.8.274, encoding A1:
// uxtb<c> <Rd>, <Rm>{, <rotate>}
//
// cccc011011101111ddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and
// rr defined (RotationValue) rotate.
- constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21;
- emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation);
+ constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21;
+ emitUxt(Cond, UxtOpcode, Rd, Rn, Rm, Rotation, UxtName);
return;
}
case 2: {
@@ -1576,8 +1607,8 @@ void AssemblerARM32::uxt(const Operand *OpRd, const Operand *OpSrc0,
//
// cccc01101111nnnnddddrr000111mmmm where cccc=Cond, dddd=Rd, mmmm=Rm, and
// rr defined (RotationValue) rotate.
- constexpr IValueT Opcode = B26 | B25 | B23 | B22 | B21 | B20;
- emitUxt(Cond, Opcode, Rd, Rn, Rm, Rotation);
+ constexpr IValueT UxtOpcode = B26 | B25 | B23 | B22 | B21 | B20;
+ emitUxt(Cond, UxtOpcode, Rd, Rn, Rm, Rotation, UxtName);
return;
}
}
« no previous file with comments | « src/IceAssemblerARM32.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698