| Index: src/IceAssemblerARM32.cpp
|
| diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
|
| index 16f1e4a1223a7ecf88244942989bb7c3772e46ea..2195d4d985766074c3dea6391637ad61e8c0c167 100644
|
| --- a/src/IceAssemblerARM32.cpp
|
| +++ b/src/IceAssemblerARM32.cpp
|
| @@ -22,7 +22,9 @@
|
|
|
| #include "IceAssemblerARM32.h"
|
|
|
| -namespace Ice {
|
| +namespace {
|
| +
|
| +using namespace Ice;
|
|
|
| // The following define individual bits.
|
| static constexpr uint32_t B0 = 1;
|
| @@ -50,9 +52,6 @@ static constexpr uint32_t kImmed8Shift = 0;
|
| static constexpr uint32_t kRotateBits = 4;
|
| static constexpr uint32_t kRotateShift = 8;
|
|
|
| -// Types of instructions.
|
| -static constexpr uint32_t kInstTypeImmediate = 1;
|
| -
|
| inline uint32_t encodeBool(bool b) { return b ? 1 : 0; }
|
|
|
| inline uint32_t encodeGPRRegister(RegARM32::GPRRegister Rn) {
|
| @@ -75,14 +74,33 @@ inline uint32_t encodeCondition(CondARM32::Cond Cond) {
|
| return static_cast<uint32_t>(Cond);
|
| }
|
|
|
| -// Converts rotated immediate into imm12.
|
| -inline uint32_t encodeImm12FromFlexImm(const OperandARM32FlexImm &FlexImm) {
|
| - uint32_t Immed8 = FlexImm.getImm();
|
| - uint32_t Rotate = FlexImm.getRotateAmt();
|
| - assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)));
|
| - return (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
|
| +// The way an operand was decoded in function decode below.
|
| +enum DecodedResult {
|
| + CantDecode = 0, // I.e. will fail in test.
|
| + DecodedAsRegister,
|
| + DecodedAsRotatedImm8
|
| +};
|
| +
|
| +DecodedResult decode(const Operand *Opnd, uint32_t &Value) {
|
| + if (const auto *Var = llvm::dyn_cast<Variable>(Opnd)) {
|
| + if (Var->hasReg()) {
|
| + Value = Var->getRegNum();
|
| + return DecodedAsRegister;
|
| + }
|
| + } else if (const auto *FlexImm = llvm::dyn_cast<OperandARM32FlexImm>(Opnd)) {
|
| + uint32_t Immed8 = FlexImm->getImm();
|
| + uint32_t Rotate = FlexImm->getRotateAmt();
|
| + assert((Rotate < (1 << kRotateBits)) && (Immed8 < (1 << kImmed8Bits)));
|
| + Value = (Rotate << kRotateShift) | (Immed8 << kImmed8Shift);
|
| + return DecodedAsRotatedImm8;
|
| + }
|
| + return CantDecode;
|
| }
|
|
|
| +} // end of anonymous namespace
|
| +
|
| +namespace Ice {
|
| +
|
| Label *ARM32::AssemblerARM32::getOrCreateLabel(SizeT Number,
|
| LabelVector &Labels) {
|
| Label *L = nullptr;
|
| @@ -120,6 +138,7 @@ void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type,
|
| uint32_t Rd, uint32_t Imm12) {
|
| assert(isGPRRegisterDefined(Rd));
|
| assert(Cond != CondARM32::kNone);
|
| + AssemblerBuffer::EnsureCapacity ensured(&Buffer);
|
| uint32_t Encoding = encodeCondition(Cond) << kConditionShift |
|
| (Type << kTypeShift) | (Opcode << kOpcodeShift) |
|
| (encodeBool(SetCc) << kSShift) | (Rn << kRnShift) |
|
| @@ -127,6 +146,36 @@ void ARM32::AssemblerARM32::emitType01(CondARM32::Cond Cond, uint32_t Type,
|
| emitInst(Encoding);
|
| }
|
|
|
| +void ARM32::AssemblerARM32::add(const Operand *OpRd, const Operand *OpRn,
|
| + const Operand *OpSrc1, bool SetFlags,
|
| + CondARM32::Cond Cond) {
|
| + // Note: Loop is used so that we can short circuit using break;
|
| + do {
|
| + uint32_t Rd;
|
| + if (decode(OpRd, Rd) != DecodedAsRegister)
|
| + break;
|
| + uint32_t Rn;
|
| + if (decode(OpRn, Rn) != DecodedAsRegister)
|
| + break;
|
| + uint32_t Src1Value;
|
| + // TODO(kschimpf) Other possible decodings of add.
|
| + if (decode(OpSrc1, Src1Value) == DecodedAsRotatedImm8) {
|
| + // ADD (Immediate): See ARM section A8.8.5, rule A1.
|
| + // cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
|
| + // s=SetFlags and iiiiiiiiiiii=Src1Value
|
| + if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags) ||
|
| + (Rn == RegARM32::Reg_lr) || (Rn == RegARM32::Reg_pc && SetFlags))
|
| + // Conditions of rule violated.
|
| + break;
|
| + uint32_t Add = B2; // 0100
|
| + uint32_t InstType = 1;
|
| + emitType01(Cond, InstType, Add, SetFlags, Rn, Rd, Src1Value);
|
| + return;
|
| + }
|
| + } while (0);
|
| + UnimplementedError(Ctx->getFlags());
|
| +}
|
| +
|
| void ARM32::AssemblerARM32::bkpt(uint16_t imm16) {
|
| AssemblerBuffer::EnsureCapacity ensured(&Buffer);
|
| uint32_t Encoding = (CondARM32::AL << kConditionShift) | B24 | B21 |
|
| @@ -145,17 +194,30 @@ void ARM32::AssemblerARM32::bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond) {
|
| emitInst(Encoding);
|
| }
|
|
|
| -void ARM32::AssemblerARM32::mov(RegARM32::GPRRegister Rd,
|
| - const OperandARM32FlexImm &FlexImm,
|
| +void ARM32::AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
|
| CondARM32::Cond Cond) {
|
| - // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1)
|
| - assert(isConditionDefined(Cond));
|
| - AssemblerBuffer::EnsureCapacity ensured(&Buffer);
|
| - bool SetCc = false; // Note: We don't use movs in this assembler.
|
| - uint32_t Rn = 0;
|
| - uint32_t Mov = B3 | B2 | B0; // 1101.
|
| - emitType01(Cond, kInstTypeImmediate, Mov, SetCc, Rn, encodeGPRRegister(Rd),
|
| - encodeImm12FromFlexImm(FlexImm));
|
| + // Note: Loop is used so that we can short ciruit using break;
|
| + do {
|
| + uint32_t Rd;
|
| + if (decode(OpRd, Rd) != DecodedAsRegister)
|
| + break;
|
| + uint32_t Src;
|
| + // TODO(kschimpf) Handle other forms of mov.
|
| + if (decode(OpSrc, Src) == DecodedAsRotatedImm8) {
|
| + // cccc0011101s0000ddddiiiiiiiiiiii (ARM section A8.8.102, encoding A1)
|
| + // Note: We don't use movs in this assembler.
|
| + constexpr bool SetFlags = false;
|
| + if (!isConditionDefined(Cond) || (Rd == RegARM32::Reg_pc && SetFlags))
|
| + // Conditions of rule violated.
|
| + break;
|
| + uint32_t Rn = 0;
|
| + uint32_t Mov = B3 | B2 | B0; // 1101.
|
| + uint32_t InstType = 1;
|
| + emitType01(Cond, InstType, Mov, SetFlags, Rn, Rd, Src);
|
| + return;
|
| + }
|
| + } while (0);
|
| + UnimplementedError(Ctx->getFlags());
|
| }
|
|
|
| } // end of namespace Ice
|
|
|