Index: src/IceAssemblerARM32.cpp |
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp |
index 3dbbb29f0be6fde664abdf2b6b64b253e1f8a8fa..3e15ee6f01c40e5cdb11a65cb265c1ed1b0f3a32 100644 |
--- a/src/IceAssemblerARM32.cpp |
+++ b/src/IceAssemblerARM32.cpp |
@@ -37,6 +37,7 @@ static constexpr IValueT B3 = 1 << 3; |
static constexpr IValueT B4 = 1 << 4; |
static constexpr IValueT B5 = 1 << 5; |
static constexpr IValueT B6 = 1 << 6; |
+static constexpr IValueT B7 = 1 << 7; |
static constexpr IValueT B21 = 1 << 21; |
static constexpr IValueT B24 = 1 << 24; |
@@ -58,6 +59,7 @@ static constexpr IValueT kOpcodeShift = 21; |
static constexpr IValueT kRdShift = 12; |
static constexpr IValueT kRmShift = 0; |
static constexpr IValueT kRnShift = 16; |
+static constexpr IValueT kRsShift = 8; |
static constexpr IValueT kSShift = 20; |
static constexpr IValueT kTypeShift = 25; |
@@ -348,6 +350,20 @@ void AssemblerARM32::emitMemOp(CondARM32::Cond Cond, IValueT InstType, |
emitInst(Encoding); |
} |
+void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, |
+ IValueT Rn, IValueT Rm, IValueT Rs, bool SetCc) { |
+ if (!isGPRRegisterDefined(Rd) || !isGPRRegisterDefined(Rn) || |
+ !isGPRRegisterDefined(Rm) || !isGPRRegisterDefined(Rs) || |
+ !isConditionDefined(Cond)) |
+ return setNeedsTextFixup(); |
+ AssemblerBuffer::EnsureCapacity ensured(&Buffer); |
+ IValueT Encoding = Opcode | (encodeCondition(Cond) << kConditionShift) | |
+ (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) | |
+ (Rd << kRdShift) | (Rs << kRsShift) | B7 | B4 | |
+ (Rm << kRmShift); |
+ emitInst(Encoding); |
+} |
+ |
void AssemblerARM32::adc(const Operand *OpRd, const Operand *OpRn, |
const Operand *OpSrc1, bool SetFlags, |
CondARM32::Cond Cond) { |
@@ -609,6 +625,31 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, |
emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address); |
} |
+void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn, |
+ const Operand *OpSrc1, bool SetFlags, |
+ CondARM32::Cond Cond) { |
+ IValueT Rd; |
+ if (decodeOperand(OpRd, Rd) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ IValueT Rn; |
+ if (decodeOperand(OpRn, Rn) != DecodedAsRegister) |
+ return setNeedsTextFixup(); |
+ IValueT Rm; |
+ if (decodeOperand(OpSrc1, Rm) != DecodedAsRegister) |
+ 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"); |
+ // Assembler registers rd, rn, rm are encoded as rn, rm, rs. |
+ IValueT MulOpcode = 0; |
Jim Stichnoth
2015/10/29 22:17:58
constexpr?
Karl
2015/10/30 14:25:56
Done.
|
+ emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags); |
+} |
+ |
void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn, |
const Operand *OpSrc1, bool SetFlags, |
CondARM32::Cond Cond) { |