Add orr (register) and orr (immediate) to ARM integrated assembler.
Also cleans up comments about handling a rotated imm8 value.
BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/1412923006 .
diff --git a/src/DartARM32/assembler_arm.cc b/src/DartARM32/assembler_arm.cc
index f2fd997..d1730c6 100644
--- a/src/DartARM32/assembler_arm.cc
+++ b/src/DartARM32/assembler_arm.cc
@@ -274,19 +274,18 @@
EmitType01(cond, o.type(), CMN, 1, rn, R0, o);
}
-
+#if 0
+// Moved to ARM32::AssemberARM32::orr()
void Assembler::orr(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ORR, 0, rn, rd, o);
}
-
+// Moved to ARM32::AssemberARM32::orr()
void Assembler::orrs(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ORR, 1, rn, rd, o);
}
-
-#if 0
-// Moved to AssemblerARM32::mov(..FlexImm..)
+// Moved to AssemblerARM32::mov()
// TODO(kschimpf) other forms of move.
void Assembler::mov(Register rd, Operand o, Condition cond) {
EmitType01(cond, o.type(), MOV, 0, R0, rd, o);
diff --git a/src/DartARM32/assembler_arm.h b/src/DartARM32/assembler_arm.h
index 46cba56..cc8f6a3 100644
--- a/src/DartARM32/assembler_arm.h
+++ b/src/DartARM32/assembler_arm.h
@@ -481,11 +481,12 @@
void cmn(Register rn, Operand o, Condition cond = AL);
+#if 0
+ // Moved to ARM32::IceAssemblerARM32::orr().
void orr(Register rd, Register rn, Operand o, Condition cond = AL);
void orrs(Register rd, Register rn, Operand o, Condition cond = AL);
-#if 0
- // Moved to IceAssemblerARM32::mov()
+ // Moved to ARM32::IceAssemblerARM32::mov()
void mov(Register rd, Operand o, Condition cond = AL);
void movs(Register rd, Operand o, Condition cond = AL);
#endif
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 4e5549d..eda6e74 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -442,7 +442,7 @@
// adc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
//
// cccc0010101snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
- // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8.
+ // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags))
// Conditions of rule violated.
return setNeedsTextFixup();
@@ -490,7 +490,7 @@
// add{s}<c> <Rd>, sp, #<RotatedImm8>
//
// cccc0010100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
- // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8.
+ // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags))
// Conditions of rule violated.
return setNeedsTextFixup();
@@ -722,7 +722,7 @@
// sbc{s}<c> <Rd>, <Rn>, #<RotatedImm8>
//
// cccc0010110snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
- // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8.
+ // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
if ((Rd == RegARM32::Encoded_Reg_pc && SetFlags))
// Conditions of rule violated.
return setNeedsTextFixup();
@@ -768,6 +768,50 @@
emitMemOp(Cond, kInstTypeMemImmediate, IsLoad, IsByte, Rt, Address);
}
+void AssemblerARM32::orr(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();
+ constexpr IValueT Orr = B3 | B2; // i.e. 1100
+ IValueT Src1Value;
+ // TODO(kschimpf) Handle other possible decodings of orr.
+ switch (decodeOperand(OpSrc1, Src1Value)) {
+ default:
+ return setNeedsTextFixup();
+ case DecodedAsRegister: {
+ // ORR (register) - ARM Section A8.8.123, encoding A1:
+ // orr{s}<c> <Rd>, <Rn>, <Rm>
+ //
+ // cccc0001100snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
+ // mmmm=Rm, iiiii=shift, tt=ShiftKind,, and s=SetFlags.
+ constexpr IValueT Shift = 0;
+ Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Shift);
+ if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags))
+ // Conditions of rule violated.
+ return setNeedsTextFixup();
+ emitType01(Cond, kInstTypeDataRegister, Orr, SetFlags, Rn, Rd, Src1Value);
+ return;
+ }
+ case DecodedAsRotatedImm8: {
+ // ORR (register) - ARM Section A8.8.123, encoding A1:
+ // orr{s}<c> <Rd>, <Rn>, #<RotatedImm8>
+ //
+ // cccc0001100snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
+ // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
+ if (Rd == RegARM32::Encoded_Reg_pc && SetFlags)
+ // Conditions of rule violated.
+ return setNeedsTextFixup();
+ emitType01(Cond, kInstTypeDataImmediate, Orr, SetFlags, Rn, Rd, Src1Value);
+ return;
+ }
+ }
+}
+
void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
@@ -816,7 +860,8 @@
//
// cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
// mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags.
- Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, 0);
+ constexpr IValueT Shift = 0;
+ Src1Value = encodeShiftRotateImm5(Src1Value, OperandARM32::kNoShift, Shift);
if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags))
// Conditions of rule violated.
return setNeedsTextFixup();
@@ -830,7 +875,7 @@
// sub{s}<c> sp, <Rn>, #<RotatedImm8>
//
// cccc0010010snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
- // s=SetFlags and iiiiiiiiiiii=Src1Value=RotatedImm8
+ // s=SetFlags and iiiiiiiiiiii=Src1Value defining RotatedImm8.
if (Rd == RegARM32::Encoded_Reg_pc)
// Conditions of rule violated.
return setNeedsTextFixup();
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index 2bf53a5..0443869 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -161,6 +161,9 @@
void movt(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
+ void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
+ bool SetFlags, CondARM32::Cond Cond);
+
void sbc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
diff --git a/src/IceInstARM32.cpp b/src/IceInstARM32.cpp
index e9a0922..8f3872a 100644
--- a/src/IceInstARM32.cpp
+++ b/src/IceInstARM32.cpp
@@ -365,6 +365,13 @@
emitUsingTextFixup(Func);
}
+template <> void InstARM32Orr::emitIAS(const Cfg *Func) const {
+ ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+ Asm->orr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
+ if (Asm->needsTextFixup())
+ emitUsingTextFixup(Func);
+}
+
template <> void InstARM32Mul::emitIAS(const Cfg *Func) const {
ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->mul(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
diff --git a/tests_lit/assembler/arm32/orr.ll b/tests_lit/assembler/arm32/orr.ll
new file mode 100644
index 0000000..480b99a
--- /dev/null
+++ b/tests_lit/assembler/arm32/orr.ll
@@ -0,0 +1,110 @@
+; Show that we know how to translate or.
+
+; NOTE: We use -O2 to get rid of memory stores.
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
+; RUN: | FileCheck %s --check-prefix=ASM
+
+; Show bytes in assembled standalone code.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
+; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
+; RUN: | FileCheck %s --check-prefix=IASM
+
+; Show bytes in assembled integrated code.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
+; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
+
+define internal i32 @Or1WithR0(i32 %p) {
+ %v = or i32 %p, 1
+ ret i32 %v
+}
+
+; ASM-LABEL:Or1WithR0:
+; ASM-NEXT:.LOr1WithR0$__0:
+; ASM-NEXT: orr r0, r0, #1
+
+; DIS-LABEL:00000000 <Or1WithR0>:
+; DIS-NEXT: 0: e3800001
+
+; IASM-LABEL:Or1WithR0:
+; IASM-NEXT:.LOr1WithR0$__0:
+; IASM-NEXT: .byte 0x1
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x80
+; IASM-NEXT: .byte 0xe3
+
+define internal i32 @Or2Regs(i32 %p1, i32 %p2) {
+ %v = or i32 %p1, %p2
+ ret i32 %v
+}
+
+; ASM-LABEL:Or2Regs:
+; ASM-NEXT:.LOr2Regs$__0:
+; ASM-NEXT: orr r0, r0, r1
+
+; DIS-LABEL:00000010 <Or2Regs>:
+; DIS-NEXT: 10: e1800001
+
+; IASM-LABEL:Or2Regs:
+; IASM-NEXT:.LOr2Regs$__0:
+; IASM-NEXT: .byte 0x1
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x80
+; IASM-NEXT: .byte 0xe1
+
+define internal i64 @OrI64WithR0R1(i64 %p) {
+ %v = or i64 %p, 1
+ ret i64 %v
+}
+
+; ASM-LABEL:OrI64WithR0R1:
+; ASM-NEXT:.LOrI64WithR0R1$__0:
+; ASM-NEXT: orr r0, r0, #1
+; ASM-NEXT: orr r1, r1, #0
+
+; DIS-LABEL:00000020 <OrI64WithR0R1>:
+; DIS-NEXT: 20: e3800001
+; DIS-NEXT: 24: e3811000
+
+; IASM-LABEL:OrI64WithR0R1:
+; IASM-NEXT:.LOrI64WithR0R1$__0:
+; IASM-NEXT: .byte 0x1
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x80
+; IASM-NEXT: .byte 0xe3
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x10
+; IASM-NEXT: .byte 0x81
+; IASM-NEXT: .byte 0xe3
+
+
+define internal i64 @OrI64Regs(i64 %p1, i64 %p2) {
+ %v = or i64 %p1, %p2
+ ret i64 %v
+}
+
+; ASM-LABEL:OrI64Regs:
+; ASM-NEXT:.LOrI64Regs$__0:
+; ASM-NEXT: orr r0, r0, r2
+; ASM-NEXT: orr r1, r1, r3
+
+; DIS-LABEL:00000030 <OrI64Regs>:
+; DIS-NEXT: 30: e1800002
+; DIS-NEXT: 34: e1811003
+
+; IASM-LABEL:OrI64Regs:
+; IASM-NEXT:.LOrI64Regs$__0:
+; IASM-NEXT: .byte 0x2
+; IASM-NEXT: .byte 0x0
+; IASM-NEXT: .byte 0x80
+; IASM-NEXT: .byte 0xe1
+; IASM-NEXT: .byte 0x3
+; IASM-NEXT: .byte 0x10
+; IASM-NEXT: .byte 0x81
+; IASM-NEXT: .byte 0xe1