Add new form of ldr/str (immediate) to ARM integrated assembler.
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/1431453002 .
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 05903e3..4e5549d 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -98,6 +98,10 @@
return static_cast<IValueT>(Rn);
}
+inline RegARM32::GPRRegister decodeGPRRegister(IValueT R) {
+ return static_cast<RegARM32::GPRRegister>(R);
+}
+
inline bool isGPRRegisterDefined(RegARM32::GPRRegister R) {
return R != RegARM32::Encoded_Not_GPR;
}
@@ -142,7 +146,7 @@
// Returns the GPR register at given Shift in Value.
inline RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
- return static_cast<RegARM32::GPRRegister>((Value >> Shift) & 0xF);
+ return decodeGPRRegister((Value >> Shift) & 0xF);
}
// The way an operand was decoded in functions decodeOperand and decodeAddress
@@ -164,7 +168,7 @@
// Encodes iiiiitt0mmmm for data-processing (2nd) operands where iiiii=Imm5,
// tt=Shift, and mmmm=Rm.
IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift,
- IValueT imm5) {
+ IOffsetT imm5) {
(void)kShiftImmBits;
assert(imm5 < (1 << kShiftImmBits));
return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm;
@@ -212,6 +216,18 @@
OperandARM32Mem::Offset);
return DecodedAsImmRegOffset;
}
+ if (const auto *Mem = llvm::dyn_cast<OperandARM32Mem>(Opnd)) {
+ if (Mem->isRegReg())
+ // TODO(kschimpf) Add this case.
+ return CantDecode;
+ Variable *Var = Mem->getBase();
+ if (!Var->hasReg())
+ return CantDecode;
+ ConstantInteger32 *Offset = Mem->getOffset();
+ Value = decodeImmRegOffset(decodeGPRRegister(Var->getRegNum()),
+ Offset->getValue(), Mem->getAddrMode());
+ return DecodedAsImmRegOffset;
+ }
return CantDecode;
}
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index f7f9f01..e9a0922 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -857,6 +857,11 @@
Str << getName(Func) << ":";
}
+template <InstARM32::InstKindARM32 K>
+void InstARM32LoadBase<K>::emitIAS(const Cfg *Func) const {
+ emitUsingTextFixup(Func);
+}
+
template <> void InstARM32Ldr::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
@@ -878,6 +883,20 @@
getSrc(0)->emit(Func);
}
+template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 1);
+ Variable *Dest = getDest();
+ Type DestTy = Dest->getType();
+ ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+ if (isVectorType(DestTy) || isScalarFloatingType(DestTy))
+ // TODO(kschimpf) Handle case.
+ Asm->setNeedsTextFixup();
+ else
+ Asm->ldr(Dest, getSrc(0), getPredicate());
+ if (Asm->needsTextFixup())
+ emitUsingTextFixup(Func);
+}
+
template <> void InstARM32Ldrex::emit(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
@@ -1128,6 +1147,19 @@
getSrc(1)->emit(Func);
}
+void InstARM32Str::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 2);
+ Type Ty = getSrc(0)->getType();
+ ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+ if (isVectorType(Ty) || isScalarFloatingType(Ty))
+ // TODO(kschimpf) Handle case.
+ Asm->setNeedsTextFixup();
+ else
+ Asm->str(getSrc(0), getSrc(1), getPredicate());
+ if (Asm->needsTextFixup())
+ emitUsingTextFixup(Func);
+}
+
void InstARM32Str::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
@@ -1491,6 +1523,9 @@
template class InstARM32ThreeAddrFP<InstARM32::Vmul>;
template class InstARM32ThreeAddrFP<InstARM32::Vsub>;
+template class InstARM32LoadBase<InstARM32::Ldr>;
+template class InstARM32LoadBase<InstARM32::Ldrex>;
+
template class InstARM32TwoAddrGPR<InstARM32::Movt>;
template class InstARM32UnaryopGPR<InstARM32::Movw, false>;
diff --git a/src/IceInstARM32.h b/src/IceInstARM32.h
index 0420722..e7d9e4c 100644
--- a/src/IceInstARM32.h
+++ b/src/IceInstARM32.h
@@ -538,6 +538,7 @@
InstARM32LoadBase(Func, Dest, Source, Predicate);
}
void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override {
if (!BuildDefs::dump())
return;
@@ -1008,6 +1009,7 @@
InstARM32Str(Func, Value, Mem, Predicate);
}
void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Str); }
diff --git a/tests_lit/assembler/arm32/global-load-store.ll b/tests_lit/assembler/arm32/global-load-store.ll
index 6c07913..a285e48 100644
--- a/tests_lit/assembler/arm32/global-load-store.ll
+++ b/tests_lit/assembler/arm32/global-load-store.ll
@@ -55,9 +55,12 @@
; IASM-LABEL:load:
; IASM-NEXT: .Lload$__0:
-; IASM-NEXT: movw r0, #:lower16:global1 @ .word e3000000
-; IASM-NEXT: movt r0, #:upper16:global1 @ .word e3400000
-; IASM-NEXT: ldr r0, [r0]
+; IASM-NEXT: movw r0, #:lower16:global1
+; IASM-NEXT: movt r0, #:upper16:global1
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x90
+; IASM-NEXT: .byte 0xe5
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
@@ -84,9 +87,12 @@
; IASM-LABEL:store:
; IASM-NEXT: .Lstore$__0:
-; IASM-NEXT: movw r1, #:lower16:global1 @ .word e3001000
-; IASM-NEXT: movt r1, #:upper16:global1 @ .word e3401000
-; IASM-NEXT: str r0, [r1]
+; IASM-NEXT: movw r1, #:lower16:global1
+; IASM-NEXT: movt r1, #:upper16:global1
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x81
+; IASM-NEXT: .byte 0xe5
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f