Commit 1956788f by Karl Schimpf

More coverage of load/stores in ARM integrated assembler.

Adds many more cases of ldr{b,h}/str{b,h} instructions to the ARM integerated assembler. Also refactored decodeAddress() to deal with the fact that immediate/register arguments for LDR/LDRB/STR/STRB differ for LDRH/LDRD/STRH/STRD, by passing in the layout wanted. Note: LDRD/STRD instructions are currently not used by Subzero. BUG=https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1486263002 .
parent c39ec10e
......@@ -28,6 +28,8 @@ DECLARE_FLAG(bool, allow_absolute_addresses);
DEFINE_FLAG(bool, print_stop_message, true, "Print stop message.");
DECLARE_FLAG(bool, inline_alloc);
#if 0
// Moved to encodeImmRegOffsetEnc3 in IceAssemblerARM32.cpp
uint32_t Address::encoding3() const {
if (kind_ == Immediate) {
uint32_t offset = encoding_ & kOffset12Mask;
......@@ -38,7 +40,7 @@ uint32_t Address::encoding3() const {
ASSERT(kind_ == IndexRegister);
return encoding_;
}
#endif
uint32_t Address::vencoding() const {
ASSERT(kind_ == Immediate);
......@@ -117,8 +119,8 @@ void Assembler::EmitMemOp(Condition cond,
ad.encoding();
Emit(encoding);
}
#endif
// Moved to AssemblerARM32::emitMemOpEnc3();
void Assembler::EmitMemOpAddressMode3(Condition cond,
int32_t mode,
Register rd,
......@@ -132,7 +134,6 @@ void Assembler::EmitMemOpAddressMode3(Condition cond,
Emit(encoding);
}
#if 0
// Moved to ARM32::AssemblerARM32::emitMuliMemOp()
void Assembler::EmitMultiMemOp(Condition cond,
BlockAddressMode am,
......@@ -191,9 +192,7 @@ void Assembler::EmitShiftRegister(Condition cond,
void Assembler::and_(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), AND, 0, rn, rd, o);
}
#endif
#if 0
// Moved to ARM32::AssemberARM32::eor()
void Assembler::eor(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), EOR, 0, rn, rd, o);
......@@ -213,7 +212,6 @@ void Assembler::rsbs(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), RSB, 1, rn, rd, o);
}
#if 0
// Moved to ARM32::AssemberARM32::add()
void Assembler::add(Register rd, Register rn, Operand o, Condition cond) {
......@@ -241,7 +239,6 @@ void Assembler::adcs(Register rd, Register rn, Operand o, Condition cond) {
}
#endif
void Assembler::sbc(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), SBC, 0, rn, rd, o);
}
......@@ -267,7 +264,6 @@ void Assembler::teq(Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), TEQ, 1, rn, R0, o);
}
#if 0
// Moved to ARM32::AssemblerARM32::cmp()
void Assembler::cmp(Register rn, Operand o, Condition cond) {
......@@ -339,7 +335,7 @@ void Assembler::clz(Register rd, Register rm, Condition cond) {
}
#if
#if 0
// Moved to ARM32::AssemblerARM32::movw()
void Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
ASSERT(cond != kNoCondition);
......@@ -358,9 +354,7 @@ void Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
static_cast<int32_t>(rd) << kRdShift | (imm16 & 0xfff);
Emit(encoding);
}
#endif
#if 0
// Moved to ARM32::AssemblerARM32::emitMulOp()
void Assembler::EmitMulOp(Condition cond, int32_t opcode,
Register rd, Register rn,
......@@ -2611,7 +2605,6 @@ void Assembler::Lsl(Register rd, Register rm, Register rs, Condition cond) {
}
#endif
void Assembler::Lsr(Register rd, Register rm, const Operand& shift_imm,
Condition cond) {
ASSERT(shift_imm.type() == 1);
......
......@@ -342,8 +342,11 @@ class Address : public ValueObject {
uint32_t encoding() const { return encoding_; }
#if 0
// Moved to encodeImmRegOffsetEnc3 in IceAssemblerARM32.cpp
// Encoding for addressing mode 3.
uint32_t encoding3() const;
#endif
// Encoding for vfp load/store addressing.
uint32_t vencoding() const;
......@@ -1183,14 +1186,13 @@ class Assembler : public ValueObject {
bool byte,
Register rd,
Address ad);
#endif
// Moved to AssemblerARM32::emitMemOpEnc3();
void EmitMemOpAddressMode3(Condition cond,
int32_t mode,
Register rd,
Address ad);
#if 0
// Moved to ARM32::AssemblerARM32::emitMultiMemOp()
void EmitMultiMemOp(Condition cond,
BlockAddressMode am,
......
......@@ -337,12 +337,20 @@ private:
void emitType05(CondARM32::Cond COnd, int32_t Offset, bool Link);
// Pattern ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond, ooo=InstType,
// l=isLoad, b=isByte, and aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that
// Address is assumed to be defined by decodeAddress() in
// IceAssemblerARM32.cpp.
// Emit ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond,
// ooo=InstType, l=isLoad, b=isByte, and
// aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that Address is assumed to be
// defined by decodeAddress() in IceAssemblerARM32.cpp.
void emitMemOp(CondARM32::Cond Cond, IValueT InstType, bool IsLoad,
bool IsByte, uint32_t Rt, uint32_t Address);
bool IsByte, IValueT Rt, IValueT Address);
// Emit ldr/ldrb/str/strb instruction with given address.
void emitMemOp(CondARM32::Cond Cond, bool IsLoad, bool IsByte, IValueT Rt,
const Operand *OpAddress, const TargetInfo &TInfo);
// Emit ldrh/ldrd/strh/strd instruction with given address using encoding 3.
void emitMemOpEnc3(CondARM32::Cond Cond, IValueT Opcode, IValueT Rt,
const Operand *OpAddress, const TargetInfo &TInfo);
// Pattern cccc100aaaalnnnnrrrrrrrrrrrrrrrr where cccc=Cond,
// aaaa<<21=AddressMode, l=IsLoad, nnnn=BaseReg, and
......
......@@ -375,9 +375,9 @@ public:
Bic,
Br,
Call,
Clz,
Cmn,
Cmp,
Clz,
Dmb,
Eor,
Label,
......
......@@ -20,33 +20,30 @@
define internal void @mult_fwd_branches(i32 %a, i32 %b) {
; ASM-LABEL:mult_fwd_branches:
; ASM-LABEL:.Lmult_fwd_branches$__0:
; ASM-NEXT: sub sp, sp, #12
; ASM-NEXT: str r0, [sp, #8]
; ASM-NEXT: # [sp, #8] = def.pseudo
; ASM-NEXT: str r1, [sp, #4]
; ASM-NEXT: # [sp, #4] = def.pseudo
; DIS-LABEL:00000000 <mult_fwd_branches>:
; DIS-NEXT: 0: e24dd00c
; DIS-NEXT: 4: e58d0008
; DIS-NEXT: 8: e58d1004
; IASM-LABEL:mult_fwd_branches:
; ASM-LABEL:.Lmult_fwd_branches$__0:
; IASM-LABEL:.Lmult_fwd_branches$__0:
; ASM-NEXT: sub sp, sp, #12
; DIS-NEXT: 0: e24dd00c
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: str r0, [sp, #8]
; ASM-NEXT: # [sp, #8] = def.pseudo
; DIS-NEXT: 4: e58d0008
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: str r1, [sp, #4]
; ASM-NEXT: # [sp, #4] = def.pseudo
; DIS-NEXT: 8: e58d1004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x8d
......@@ -55,71 +52,73 @@ define internal void @mult_fwd_branches(i32 %a, i32 %b) {
%cmp = icmp slt i32 %a, %b
; ASM-NEXT: mov r0, #0
; ASM-NEXT: ldr r1, [sp, #8]
; ASM-NEXT: ldr r2, [sp, #4]
; ASM-NEXT: cmp r1, r2
; ASM-NEXT: movlt r0, #1
; ASM-NEXT: strb r0, [sp]
; ASM-NEXT: # [sp] = def.pseudo
; DIS-NEXT: c: e3a00000
; DIS-NEXT: 10: e59d1008
; DIS-NEXT: 14: e59d2004
; DIS-NEXT: 18: e1510002
; DIS-NEXT: 1c: b3a00001
; DIS-NEXT: 20: e5cd0000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe3
; ASM-NEXT: ldr r1, [sp, #8]
; DIS-NEXT: 10: e59d1008
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r2, [sp, #4]
; DIS-NEXT: 14: e59d2004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: cmp r1, r2
; DIS-NEXT: 18: e1510002
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x51
; IASM-NEXT: .byte 0xe1
; ASM-NEXT: movlt r0, #1
; DIS-NEXT: 1c: b3a00001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xb3
; IASM-NEXT: strb r0, [sp]
; ASM-NEXT: strb r0, [sp]
; ASM-NEXT: # [sp] = def.pseudo
; DIS-NEXT: 20: e5cd0000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xcd
; IASM-NEXT: .byte 0xe5
br i1 %cmp, label %then, label %else
; ASM-NEXT: ldrb r0, [sp]
; ASM-NEXT: tst r0, #1
; ASM-NEXT: bne .Lmult_fwd_branches$then
; ASM-NEXT: b .Lmult_fwd_branches$else
; DIS-NEXT: 24: e5dd0000
; DIS-NEXT: 28: e3100001
; DIS-NEXT: 2c: 1a000000
; DIS-NEXT: 30: ea000000
; IASM-NEXT: ldrb r0, [sp]
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xdd
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: tst r0, #1
; DIS-NEXT: 28: e3100001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xe3
; ASM-NEXT: bne .Lmult_fwd_branches$then
; DIS-NEXT: 2c: 1a000000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1a
; ASM-NEXT: b .Lmult_fwd_branches$else
; DIS-NEXT: 30: ea000000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
......@@ -130,10 +129,9 @@ then:
; IASM-LABEL:.Lmult_fwd_branches$then:
br label %end
; ASM-NEXT: b .Lmult_fwd_branches$end
; ASM-NEXT: b .Lmult_fwd_branches$end
; DIS-NEXT: 34: ea000000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
......@@ -145,9 +143,7 @@ else:
br label %end
; ASM-NEXT: b .Lmult_fwd_branches$end
; DIS-NEXT: 38: eaffffff
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0xff
......@@ -161,16 +157,14 @@ end:
ret void
; ASM-NEXT: add sp, sp, #12
; ASM-NEXT: bx lr
; DIS-NEXT: 3c: e28dd00c
; DIS-NEXT: 40: e12fff1e
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: bx lr
; DIS-NEXT: 40: e12fff1e
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
......
; Show that we know how to translate LDR (register).
; Show that we know how to translate LDR/LDRH (register) instructions.
; NOTE: We use -O2 to get rid of memory stores.
......@@ -20,70 +20,97 @@
; RUN: %lc2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
; Define some global arrays to access.
@ArrayInitPartial = internal global [40 x i8] c"<\00\00\00F\00\00\00P\00\00\00Z\00\00\00d\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", align 4
@NumArraysElements = internal global [4 x i8] c"\01\00\00\00", align 4
@Arrays = internal constant <{ i32, [4 x i8] }> <{ i32 ptrtoint ([40 x i8]* @ArrayInitPartial to i32), [4 x i8] c"\14\00\00\00" }>, align 4
define internal void @_Z8getArrayjRj(i32 %WhichArray, i32 %Len) {
; ASM-LABEL:_Z8getArrayjRj:
; DIS-LABEL:00000000 <_Z8getArrayjRj>:
; IASM-LABEL:_Z8getArrayjRj:
; Index elements of an array.
define internal i32 @IndexArray(i32 %WhichArray, i32 %Len) {
; ASM-LABEL:IndexArray:
; DIS-LABEL:00000000 <IndexArray>:
; IASM-LABEL:IndexArray:
entry:
; ASM-NEXT:.L_Z8getArrayjRj$entry:
; IASM-NEXT:.L_Z8getArrayjRj$entry:
; ASM-NEXT:.LIndexArray$entry:
; IASM-NEXT:.LIndexArray$entry:
%gep_array = mul i32 %WhichArray, 8
; ASM-NEXT: push {r4}
; DIS-NEXT: 0: e52d4004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x40
; IASM-NEXT: .byte 0x2d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: lsl r2, r0, #3
; DIS-NEXT: 4: e1a02180
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0x21
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe1
%expanded1 = ptrtoint <{ i32, [4 x i8] }>* @Arrays to i32
%gep = add i32 %expanded1, %gep_array
; ASM-NEXT: movw r2, #:lower16:Arrays
; ASM-NEXT: movt r2, #:upper16:Arrays
; DIS-NEXT: 0: e3002000
; DIS-NEXT: 4: e3402000
; IASM-NEXT: movw r2, #:lower16:Arrays @ .word e3002000
; IASM-NEXT: movt r2, #:upper16:Arrays @ .word e3402000
; ASM-NEXT: movw r3, #:lower16:Arrays
; DIS-NEXT: 8: e3003000
; IASM-NEXT: movw r3, #:lower16:Arrays @ .word e3003000
; ASM-NEXT: movt r3, #:upper16:Arrays
; DIS-NEXT: c: e3403000
; IASM-NEXT: movt r3, #:upper16:Arrays @ .word e3403000
%gep3 = add i32 %gep, 4
; ASM-NEXT: add r2, r2, #4
; DIS-NEXT: 8: e2822004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: add r4, r3, #4
; DIS-NEXT: 10: e2834004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x40
; IASM-NEXT: .byte 0x83
; IASM-NEXT: .byte 0xe2
; ***** Here is the use of a LDR (register) instruction.
%gep3.asptr = inttoptr i32 %gep3 to i32*
%v1 = load i32, i32* %gep3.asptr, align 1
; ASM-NEXT: ldr r2, [r2, r0, lsl #3]
; DIS-NEXT: c: e7922180
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0x21
; IASM-NEXT: .byte 0x92
; IASM-NEXT: .byte 0xe7
; ASM-NEXT: ldr r4, [r4, r0, lsl #3]
; DIS-NEXT: 14: e7944180
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0x41
; IASM-NEXT: .byte 0x94
; IASM-NEXT: .byte 0xe7
%Len.asptr3 = inttoptr i32 %Len to i32*
store i32 %v1, i32* %Len.asptr3, align 1
; ASM-NEXT: str r2, [r1]
; DIS-NEXT: 10: e5812000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x81
; IASM-NEXT: .byte 0xe5
ret void
; ASM-NEXT: bx lr
; DIS-NEXT: 14: e12fff1e
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
; ASM-NEXT: str r4, [r1]
; DIS-NEXT: 18: e5814000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x40
; IASM-NEXT: .byte 0x81
; IASM-NEXT: .byte 0xe5
; Now read the value as an i16 to test ldrh (register).
%gep3.i16ptr = inttoptr i32 %gep3 to i16*
%v16 = load i16, i16* %gep3.i16ptr, align 1
; ASM-NEXT: add r3, r3, #4
; DIS-NEXT: 1c: e2833004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0x83
; IASM-NEXT: .byte 0xe2
; ***** Here is the use of a LDRH (register) instruction.
; ASM-NEXT: ldrh r3, [r3, r2]
; DIS-NEXT: 20: e19330b2
; IASM-NEXT: .byte 0xb2
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0x93
; IASM-NEXT: .byte 0xe1
%ret = sext i16 %v16 to i32
ret i32 %ret
}
......@@ -69,7 +69,10 @@ entry:
; ASM-NEXT: strb r0, [sp, #12]
; ASM-NEXT: # [sp, #12] = def.pseudo
; DIS-NEXT: 14: e5cd000c
; IASM-NEXT: strb r0, [sp, #12]
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xcd
; IASM-NEXT: .byte 0xe5
%a.arg_trunc = trunc i32 %a to i1
......@@ -90,13 +93,19 @@ entry:
; ASM-NEXT: strb r0, [sp, #8]
; ASM-NEXT: # [sp, #8] = def.pseudo
; DIS-NEXT: 20: e5cd0008
; IASM-NEXT: strb r0, [sp, #8]
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xcd
; IASM-NEXT: .byte 0xe5
%conv = zext i1 %a.arg_trunc to i32
; ASM-NEXT: ldrb r0, [sp, #8]
; DIS-NEXT: 24: e5dd0008
; IASM-NEXT: ldrb r0, [sp, #8]
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xdd
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: str r0, [sp, #4]
; ASM-NEXT: # [sp, #4] = def.pseudo
......@@ -117,7 +126,10 @@ entry:
; ASM-NEXT: ldrb r1, [sp, #12]
; DIS-NEXT: 30: e5dd100c
; IASM-NEXT: ldrb r1, [sp, #12]
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xdd
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: tst r1, #1
; DIS-NEXT: 34: e3110001
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment