| Index: src/IceInstARM32.cpp
|
| diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
|
| index 9f54e85a99f203ce42ef9d34b7cb45f41a86ecae..6ac169862b063dcb3149c765a8ef9c0977d7f182 100644
|
| --- a/src/IceInstARM32.cpp
|
| +++ b/src/IceInstARM32.cpp
|
| @@ -37,12 +37,57 @@ const struct TypeARM32Attributes_ {
|
| #undef X
|
| };
|
|
|
| +const struct InstARM32ShiftAttributes_ {
|
| + const char *EmitString;
|
| +} InstARM32ShiftAttributes[] = {
|
| +#define X(tag, emit) \
|
| + { emit } \
|
| + ,
|
| + ICEINSTARM32SHIFT_TABLE
|
| +#undef X
|
| +};
|
| +
|
| } // end of anonymous namespace
|
|
|
| const char *InstARM32::getWidthString(Type Ty) {
|
| return TypeARM32Attributes[Ty].WidthString;
|
| }
|
|
|
| +void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func) {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(Inst->getSrcSize() == 2);
|
| + Variable *Dest = Inst->getDest();
|
| + assert(Dest == Inst->getSrc(0));
|
| + Operand *Src1 = Inst->getSrc(1);
|
| + Str << "\t" << Opcode << "\t";
|
| + Dest->emit(Func);
|
| + Str << ", ";
|
| + Src1->emit(Func);
|
| +}
|
| +
|
| +OperandARM32Mem::OperandARM32Mem(Cfg * /* Func */, Type Ty, Variable *Base,
|
| + ConstantInteger32 *ImmOffset, AddrMode Mode)
|
| + : OperandARM32(kMem, Ty), Base(Base), ImmOffset(ImmOffset), Index(nullptr),
|
| + ShiftOp(kNoShift), ShiftAmt(0), Mode(Mode) {
|
| + // The Neg modes are only needed for Reg +/- Reg.
|
| + assert(!isNegAddrMode());
|
| + NumVars = 1;
|
| + Vars = &this->Base;
|
| +}
|
| +
|
| +OperandARM32Mem::OperandARM32Mem(Cfg *Func, Type Ty, Variable *Base,
|
| + Variable *Index, ShiftKind ShiftOp,
|
| + uint16_t ShiftAmt, AddrMode Mode)
|
| + : OperandARM32(kMem, Ty), Base(Base), ImmOffset(0), Index(Index),
|
| + ShiftOp(ShiftOp), ShiftAmt(ShiftAmt), Mode(Mode) {
|
| + NumVars = 2;
|
| + Vars = Func->allocateArrayOf<Variable *>(2);
|
| + Vars[0] = Base;
|
| + Vars[1] = Index;
|
| +}
|
| +
|
| bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
|
| int32_t Bits = SignExt ? TypeARM32Attributes[Ty].SExtAddrOffsetBits
|
| : TypeARM32Attributes[Ty].ZExtAddrOffsetBits;
|
| @@ -55,6 +100,52 @@ bool OperandARM32Mem::canHoldOffset(Type Ty, bool SignExt, int32_t Offset) {
|
| return Utils::IsAbsoluteUint(Bits, Offset);
|
| }
|
|
|
| +OperandARM32FlexImm::OperandARM32FlexImm(Cfg * /* Func */, Type Ty,
|
| + uint32_t Imm, uint32_t RotateAmt)
|
| + : OperandARM32Flex(kFlexImm, Ty), Imm(Imm), RotateAmt(RotateAmt) {
|
| + NumVars = 0;
|
| + Vars = nullptr;
|
| +}
|
| +
|
| +bool OperandARM32FlexImm::canHoldImm(uint32_t Immediate, uint32_t *RotateAmt,
|
| + uint32_t *Immed_8) {
|
| + // Avoid the more expensive test for frequent small immediate values.
|
| + if (Immediate <= 0xFF) {
|
| + *RotateAmt = 0;
|
| + *Immed_8 = Immediate;
|
| + return true;
|
| + }
|
| + // Note that immediate must be unsigned for the test to work correctly.
|
| + for (int Rot = 1; Rot < 16; Rot++) {
|
| + uint32_t Imm8 = Utils::rotateLeft32(Immediate, 2 * Rot);
|
| + if (Imm8 <= 0xFF) {
|
| + *RotateAmt = Rot;
|
| + *Immed_8 = Imm8;
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +OperandARM32FlexReg::OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg,
|
| + ShiftKind ShiftOp, Operand *ShiftAmt)
|
| + : OperandARM32Flex(kFlexReg, Ty), Reg(Reg), ShiftOp(ShiftOp),
|
| + ShiftAmt(ShiftAmt) {
|
| + NumVars = 1;
|
| + Variable *ShiftVar = llvm::dyn_cast_or_null<Variable>(ShiftAmt);
|
| + if (ShiftVar)
|
| + ++NumVars;
|
| + Vars = Func->allocateArrayOf<Variable *>(NumVars);
|
| + Vars[0] = Reg;
|
| + if (ShiftVar)
|
| + Vars[1] = ShiftVar;
|
| +}
|
| +
|
| +InstARM32Ldr::InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem)
|
| + : InstARM32(Func, InstARM32::Ldr, 1, Dest) {
|
| + addSource(Mem);
|
| +}
|
| +
|
| InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source)
|
| : InstARM32(Func, InstARM32::Ret, Source ? 2 : 1, nullptr) {
|
| addSource(LR);
|
| @@ -64,6 +155,14 @@ InstARM32Ret::InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source)
|
|
|
| // ======================== Dump routines ======================== //
|
|
|
| +// Two-addr ops
|
| +template <> const char *InstARM32Movt::Opcode = "movt";
|
| +// Unary ops
|
| +template <> const char *InstARM32Movw::Opcode = "movw";
|
| +template <> const char *InstARM32Mvn::Opcode = "mvn";
|
| +// Mov-like ops
|
| +template <> const char *InstARM32Mov::Opcode = "mov";
|
| +
|
| void InstARM32::dump(const Cfg *Func) const {
|
| if (!ALLOW_DUMP)
|
| return;
|
| @@ -72,6 +171,101 @@ void InstARM32::dump(const Cfg *Func) const {
|
| Inst::dump(Func);
|
| }
|
|
|
| +template <> void InstARM32Mov::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(getSrcSize() == 1);
|
| + Variable *Dest = getDest();
|
| + if (Dest->hasReg()) {
|
| + Str << "\t"
|
| + << "mov"
|
| + << "\t";
|
| + getDest()->emit(Func);
|
| + Str << ", ";
|
| + getSrc(0)->emit(Func);
|
| + } else {
|
| + Variable *Src0 = llvm::cast<Variable>(getSrc(0));
|
| + assert(Src0->hasReg());
|
| + Str << "\t"
|
| + << "str"
|
| + << "\t";
|
| + Src0->emit(Func);
|
| + Str << ", ";
|
| + Dest->emit(Func);
|
| + }
|
| +}
|
| +
|
| +template <> void InstARM32Mov::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 1);
|
| + (void)Func;
|
| + llvm_unreachable("Not yet implemented");
|
| +}
|
| +
|
| +void InstARM32Ldr::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(getSrcSize() == 1);
|
| + assert(getDest()->hasReg());
|
| + Type Ty = getSrc(0)->getType();
|
| + Str << "\t"
|
| + << "ldr" << getWidthString(Ty) << "\t";
|
| + getDest()->emit(Func);
|
| + Str << ", ";
|
| + getSrc(0)->emit(Func);
|
| +}
|
| +
|
| +void InstARM32Ldr::emitIAS(const Cfg *Func) const {
|
| + assert(getSrcSize() == 2);
|
| + (void)Func;
|
| + llvm_unreachable("Not yet implemented");
|
| +}
|
| +
|
| +void InstARM32Ldr::dump(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrDump();
|
| + dumpDest(Func);
|
| + Str << "ldr." << getSrc(0)->getType() << " ";
|
| + dumpSources(Func);
|
| +}
|
| +
|
| +template <> void InstARM32Movw::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(getSrcSize() == 1);
|
| + Str << "\t" << Opcode << "\t";
|
| + getDest()->emit(Func);
|
| + Str << ", ";
|
| + Constant *Src0 = llvm::cast<Constant>(getSrc(0));
|
| + if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src0)) {
|
| + Str << "#:lower16:";
|
| + CR->emitWithoutPrefix(Func->getTarget());
|
| + } else {
|
| + Src0->emit(Func);
|
| + }
|
| +}
|
| +
|
| +template <> void InstARM32Movt::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + assert(getSrcSize() == 2);
|
| + Variable *Dest = getDest();
|
| + Constant *Src1 = llvm::cast<Constant>(getSrc(1));
|
| + Str << "\t" << Opcode << "\t";
|
| + Dest->emit(Func);
|
| + Str << ", ";
|
| + if (auto CR = llvm::dyn_cast<ConstantRelocatable>(Src1)) {
|
| + Str << "#:upper16:";
|
| + CR->emitWithoutPrefix(Func->getTarget());
|
| + } else {
|
| + Src1->emit(Func);
|
| + }
|
| +}
|
| +
|
| void InstARM32Ret::emit(const Cfg *Func) const {
|
| if (!ALLOW_DUMP)
|
| return;
|
| @@ -98,4 +292,119 @@ void InstARM32Ret::dump(const Cfg *Func) const {
|
| dumpSources(Func);
|
| }
|
|
|
| +void OperandARM32Mem::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + Str << "[";
|
| + getBase()->emit(Func);
|
| + switch (getAddrMode()) {
|
| + case PostIndex:
|
| + case NegPostIndex:
|
| + Str << "], ";
|
| + break;
|
| + default:
|
| + Str << ", ";
|
| + break;
|
| + }
|
| + if (isRegReg()) {
|
| + if (isNegAddrMode()) {
|
| + Str << "-";
|
| + }
|
| + getIndex()->emit(Func);
|
| + if (getShiftOp() != kNoShift) {
|
| + Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
|
| + << getShiftAmt();
|
| + }
|
| + } else {
|
| + getOffset()->emit(Func);
|
| + }
|
| + switch (getAddrMode()) {
|
| + case Offset:
|
| + case NegOffset:
|
| + Str << "]";
|
| + break;
|
| + case PreIndex:
|
| + case NegPreIndex:
|
| + Str << "]!";
|
| + break;
|
| + case PostIndex:
|
| + case NegPostIndex:
|
| + // Brace is already closed off.
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void OperandARM32Mem::dump(const Cfg *Func, Ostream &Str) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Str << "[";
|
| + if (Func)
|
| + getBase()->dump(Func);
|
| + else
|
| + getBase()->dump(Str);
|
| + Str << ", ";
|
| + if (isRegReg()) {
|
| + if (isNegAddrMode()) {
|
| + Str << "-";
|
| + }
|
| + if (Func)
|
| + getIndex()->dump(Func);
|
| + else
|
| + getIndex()->dump(Str);
|
| + if (getShiftOp() != kNoShift) {
|
| + Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " #"
|
| + << getShiftAmt();
|
| + }
|
| + } else {
|
| + getOffset()->dump(Func, Str);
|
| + }
|
| + Str << "] AddrMode==" << getAddrMode() << "\n";
|
| +}
|
| +
|
| +void OperandARM32FlexImm::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + uint32_t Imm = getImm();
|
| + uint32_t RotateAmt = getRotateAmt();
|
| + Str << "#" << Utils::rotateRight32(Imm, 2 * RotateAmt);
|
| +}
|
| +
|
| +void OperandARM32FlexImm::dump(const Cfg * /* Func */, Ostream &Str) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + uint32_t Imm = getImm();
|
| + uint32_t RotateAmt = getRotateAmt();
|
| + Str << "#(" << Imm << " ror 2*" << RotateAmt << ")";
|
| +}
|
| +
|
| +void OperandARM32FlexReg::emit(const Cfg *Func) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Ostream &Str = Func->getContext()->getStrEmit();
|
| + getReg()->emit(Func);
|
| + if (getShiftOp() != kNoShift) {
|
| + Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
|
| + getShiftAmt()->emit(Func);
|
| + }
|
| +}
|
| +
|
| +void OperandARM32FlexReg::dump(const Cfg *Func, Ostream &Str) const {
|
| + if (!ALLOW_DUMP)
|
| + return;
|
| + Variable *Reg = getReg();
|
| + if (Func)
|
| + Reg->dump(Func);
|
| + else
|
| + Reg->dump(Str);
|
| + if (getShiftOp() != kNoShift) {
|
| + Str << ", " << InstARM32ShiftAttributes[getShiftOp()].EmitString << " ";
|
| + if (Func)
|
| + getShiftAmt()->dump(Func);
|
| + else
|
| + getShiftAmt()->dump(Str);
|
| + }
|
| +}
|
| +
|
| } // end of namespace Ice
|
|
|