Commit 745ad1d8 by Karl Schimpf

Handle stack spills in ARM integrated assembler.

Add code to handle spilling stack variables. That is, add code to handle loading and storing to stack addresses. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334 R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1402403002 .
parent 1fb030c6
...@@ -72,7 +72,7 @@ void Assembler::Emit(int32_t value) { ...@@ -72,7 +72,7 @@ void Assembler::Emit(int32_t value) {
} }
#if 0 #if 0
// Moved to class AssemblerARM32. // Moved to ARM32::AssemblerARM32::emitType01()
void Assembler::EmitType01(Condition cond, void Assembler::EmitType01(Condition cond,
int type, int type,
Opcode opcode, Opcode opcode,
...@@ -102,6 +102,8 @@ void Assembler::EmitType5(Condition cond, int32_t offset, bool link) { ...@@ -102,6 +102,8 @@ void Assembler::EmitType5(Condition cond, int32_t offset, bool link) {
} }
#if 0
// Moved to ARM32::AssemblerARM32::emitMemOp()
void Assembler::EmitMemOp(Condition cond, void Assembler::EmitMemOp(Condition cond,
bool load, bool load,
bool byte, bool byte,
...@@ -117,7 +119,7 @@ void Assembler::EmitMemOp(Condition cond, ...@@ -117,7 +119,7 @@ void Assembler::EmitMemOp(Condition cond,
ad.encoding(); ad.encoding();
Emit(encoding); Emit(encoding);
} }
#endif
void Assembler::EmitMemOpAddressMode3(Condition cond, void Assembler::EmitMemOpAddressMode3(Condition cond,
int32_t mode, int32_t mode,
...@@ -194,10 +196,12 @@ void Assembler::eor(Register rd, Register rn, Operand o, Condition cond) { ...@@ -194,10 +196,12 @@ void Assembler::eor(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), EOR, 0, rn, rd, o); EmitType01(cond, o.type(), EOR, 0, rn, rd, o);
} }
#if 0
// Moved to ARM32::AssemberARM32::sub()
void Assembler::sub(Register rd, Register rn, Operand o, Condition cond) { void Assembler::sub(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), SUB, 0, rn, rd, o); EmitType01(cond, o.type(), SUB, 0, rn, rd, o);
} }
#endif
void Assembler::rsb(Register rd, Register rn, Operand o, Condition cond) { void Assembler::rsb(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), RSB, 0, rn, rd, o); EmitType01(cond, o.type(), RSB, 0, rn, rd, o);
...@@ -209,22 +213,23 @@ void Assembler::rsbs(Register rd, Register rn, Operand o, Condition cond) { ...@@ -209,22 +213,23 @@ void Assembler::rsbs(Register rd, Register rn, Operand o, Condition cond) {
#if 0 #if 0
// Moved to IceAssemberARM32::add. // Moved to ARM32::AssemberARM32::add()
void Assembler::add(Register rd, Register rn, Operand o, Condition cond) { void Assembler::add(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ADD, 0, rn, rd, o); EmitType01(cond, o.type(), ADD, 0, rn, rd, o);
} }
// Moved to ARM32::AssemberARM32::add()
void Assembler::adds(Register rd, Register rn, Operand o, Condition cond) { void Assembler::adds(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ADD, 1, rn, rd, o); EmitType01(cond, o.type(), ADD, 1, rn, rd, o);
} }
#endif #endif
#if 0
// Moved to ARM32::AssemberARM32::sub()
void Assembler::subs(Register rd, Register rn, Operand o, Condition cond) { void Assembler::subs(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), SUB, 1, rn, rd, o); EmitType01(cond, o.type(), SUB, 1, rn, rd, o);
} }
#endif
void Assembler::adc(Register rd, Register rn, Operand o, Condition cond) { void Assembler::adc(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ADC, 0, rn, rd, o); EmitType01(cond, o.type(), ADC, 0, rn, rd, o);
...@@ -464,25 +469,27 @@ void Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) { ...@@ -464,25 +469,27 @@ void Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) {
} }
#if 0
// Moved to ARM32::AssemblerARM32::ldr()
void Assembler::ldr(Register rd, Address ad, Condition cond) { void Assembler::ldr(Register rd, Address ad, Condition cond) {
EmitMemOp(cond, true, false, rd, ad); EmitMemOp(cond, true, false, rd, ad);
} }
// Moved to ARM32::AssemblerARM32::str()
void Assembler::str(Register rd, Address ad, Condition cond) { void Assembler::str(Register rd, Address ad, Condition cond) {
EmitMemOp(cond, false, false, rd, ad); EmitMemOp(cond, false, false, rd, ad);
} }
// Moved to ARM32::AssemblerARM32::ldr()
void Assembler::ldrb(Register rd, Address ad, Condition cond) { void Assembler::ldrb(Register rd, Address ad, Condition cond) {
EmitMemOp(cond, true, true, rd, ad); EmitMemOp(cond, true, true, rd, ad);
} }
// Moved to ARM32::AssemblerARM32::str()
void Assembler::strb(Register rd, Address ad, Condition cond) { void Assembler::strb(Register rd, Address ad, Condition cond) {
EmitMemOp(cond, false, true, rd, ad); EmitMemOp(cond, false, true, rd, ad);
} }
#endif
void Assembler::ldrh(Register rd, Address ad, Condition cond) { void Assembler::ldrh(Register rd, Address ad, Condition cond) {
EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad); EmitMemOpAddressMode3(cond, L | B7 | H | B4, rd, ad);
...@@ -1441,7 +1448,7 @@ void Assembler::vcgtqs(QRegister qd, QRegister qn, QRegister qm) { ...@@ -1441,7 +1448,7 @@ void Assembler::vcgtqs(QRegister qd, QRegister qn, QRegister qm) {
#if 0 #if 0
// Moved to: ARM32::AssemblerARM32. // Moved to: ARM32::AssemblerARM32::bkpt()
void Assembler::bkpt(uint16_t imm16) { void Assembler::bkpt(uint16_t imm16) {
Emit(BkptEncoding(imm16)); Emit(BkptEncoding(imm16));
} }
...@@ -1458,7 +1465,7 @@ void Assembler::bl(Label* label, Condition cond) { ...@@ -1458,7 +1465,7 @@ void Assembler::bl(Label* label, Condition cond) {
} }
#if 0 #if 0
// Moved to: ARM32::AssemblerARM32. // Moved to: ARM32::AssemblerARM32::bx()
void Assembler::bx(Register rm, Condition cond) { void Assembler::bx(Register rm, Condition cond) {
ASSERT(rm != kNoRegister); ASSERT(rm != kNoRegister);
ASSERT(cond != kNoCondition); ASSERT(cond != kNoCondition);
...@@ -2327,7 +2334,7 @@ void Assembler::BindARMv6(Label* label) { ...@@ -2327,7 +2334,7 @@ void Assembler::BindARMv6(Label* label) {
} }
#if 0 #if 0
// Moved to: ARM32::AssemblerARM32 as method bind(Label* Label) // Moved to: ARM32::AssemblerARM32::bind(Label* Label)
// Note: Most of this code isn't needed because instruction selection has // Note: Most of this code isn't needed because instruction selection has
// already been handler // already been handler
void Assembler::BindARMv7(Label* label) { void Assembler::BindARMv7(Label* label) {
......
...@@ -140,7 +140,7 @@ class Operand : public ValueObject { ...@@ -140,7 +140,7 @@ class Operand : public ValueObject {
} }
#if 0 #if 0
// Moved to decode in IceAssemblerARM32.cpp // Moved to decodeOperand() in IceAssemblerARM32.cpp
// Data-processing operands - Rotated immediate. // Data-processing operands - Rotated immediate.
Operand(uint32_t rotate, uint32_t immed8) { Operand(uint32_t rotate, uint32_t immed8) {
ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits))); ASSERT((rotate < (1 << kRotateBits)) && (immed8 < (1 << kImmed8Bits)));
...@@ -150,7 +150,7 @@ class Operand : public ValueObject { ...@@ -150,7 +150,7 @@ class Operand : public ValueObject {
#endif #endif
#if 0 #if 0
// Moved to decode in IceAssemblerARM32.cpp // Moved to decodeOperand() in IceAssemblerARM32.cpp
// Data-processing operands - Register. // Data-processing operands - Register.
explicit Operand(Register rm) { explicit Operand(Register rm) {
type_ = 0; type_ = 0;
...@@ -277,6 +277,9 @@ class Address : public ValueObject { ...@@ -277,6 +277,9 @@ class Address : public ValueObject {
return (encoding_ == other.encoding_) && (kind_ == other.kind_); return (encoding_ == other.encoding_) && (kind_ == other.kind_);
} }
#if 0
// Moved to decodeImmRegOffset() in IceAssemblerARM32.cpp.
// Used to model stack offsets.
explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) { explicit Address(Register rn, int32_t offset = 0, Mode am = Offset) {
ASSERT(Utils::IsAbsoluteUint(12, offset)); ASSERT(Utils::IsAbsoluteUint(12, offset));
kind_ = Immediate; kind_ = Immediate;
...@@ -287,6 +290,7 @@ class Address : public ValueObject { ...@@ -287,6 +290,7 @@ class Address : public ValueObject {
} }
encoding_ |= static_cast<uint32_t>(rn) << kRnShift; encoding_ |= static_cast<uint32_t>(rn) << kRnShift;
} }
#endif
// There is no register offset mode unless Mode is Offset, in which case the // There is no register offset mode unless Mode is Offset, in which case the
// shifted register case below should be used. // shifted register case below should be used.
...@@ -440,14 +444,17 @@ class Assembler : public ValueObject { ...@@ -440,14 +444,17 @@ class Assembler : public ValueObject {
void eor(Register rd, Register rn, Operand o, Condition cond = AL); void eor(Register rd, Register rn, Operand o, Condition cond = AL);
#if 0
// Moved to ARM32::AssemberARM32::sub()
void sub(Register rd, Register rn, Operand o, Condition cond = AL); void sub(Register rd, Register rn, Operand o, Condition cond = AL);
void subs(Register rd, Register rn, Operand o, Condition cond = AL); void subs(Register rd, Register rn, Operand o, Condition cond = AL);
#endif
void rsb(Register rd, Register rn, Operand o, Condition cond = AL); void rsb(Register rd, Register rn, Operand o, Condition cond = AL);
void rsbs(Register rd, Register rn, Operand o, Condition cond = AL); void rsbs(Register rd, Register rn, Operand o, Condition cond = AL);
#if 0 #if 0
// Moved to IceAssemblerARM32::mov // Moved to ARM32::AssemblerARM32::add()
void add(Register rd, Register rn, Operand o, Condition cond = AL); void add(Register rd, Register rn, Operand o, Condition cond = AL);
void adds(Register rd, Register rn, Operand o, Condition cond = AL); void adds(Register rd, Register rn, Operand o, Condition cond = AL);
...@@ -475,7 +482,7 @@ class Assembler : public ValueObject { ...@@ -475,7 +482,7 @@ class Assembler : public ValueObject {
void orrs(Register rd, Register rn, Operand o, Condition cond = AL); void orrs(Register rd, Register rn, Operand o, Condition cond = AL);
#if 0 #if 0
// Moved to IceAssemblerARM32::mov // Moved to IceAssemblerARM32::mov()
void mov(Register rd, Operand o, Condition cond = AL); void mov(Register rd, Operand o, Condition cond = AL);
void movs(Register rd, Operand o, Condition cond = AL); void movs(Register rd, Operand o, Condition cond = AL);
#endif #endif
...@@ -514,12 +521,18 @@ class Assembler : public ValueObject { ...@@ -514,12 +521,18 @@ class Assembler : public ValueObject {
void sdiv(Register rd, Register rn, Register rm, Condition cond = AL); void sdiv(Register rd, Register rn, Register rm, Condition cond = AL);
void udiv(Register rd, Register rn, Register rm, Condition cond = AL); void udiv(Register rd, Register rn, Register rm, Condition cond = AL);
#if 0
// Moved to AssemblerARM32::ldr()
// Load/store instructions. // Load/store instructions.
void ldr(Register rd, Address ad, Condition cond = AL); void ldr(Register rd, Address ad, Condition cond = AL);
// Moved to AssemblerARM32::str()
void str(Register rd, Address ad, Condition cond = AL); void str(Register rd, Address ad, Condition cond = AL);
// Moved to AssemblerARM32::ldr()
void ldrb(Register rd, Address ad, Condition cond = AL); void ldrb(Register rd, Address ad, Condition cond = AL);
// Moved to AssemblerARM32::str()
void strb(Register rd, Address ad, Condition cond = AL); void strb(Register rd, Address ad, Condition cond = AL);
#endif
void ldrh(Register rd, Address ad, Condition cond = AL); void ldrh(Register rd, Address ad, Condition cond = AL);
void strh(Register rd, Address ad, Condition cond = AL); void strh(Register rd, Address ad, Condition cond = AL);
...@@ -546,7 +559,7 @@ class Assembler : public ValueObject { ...@@ -546,7 +559,7 @@ class Assembler : public ValueObject {
void nop(Condition cond = AL); void nop(Condition cond = AL);
#if 0 #if 0
// Moved to: ARM32::AssemblerARM32. // Moved to: ARM32::AssemblerARM32::bkpt()
// Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0. // Note that gdb sets breakpoints using the undefined instruction 0xe7f001f0.
void bkpt(uint16_t imm16); void bkpt(uint16_t imm16);
...@@ -677,7 +690,7 @@ class Assembler : public ValueObject { ...@@ -677,7 +690,7 @@ class Assembler : public ValueObject {
void b(Label* label, Condition cond = AL); void b(Label* label, Condition cond = AL);
void bl(Label* label, Condition cond = AL); void bl(Label* label, Condition cond = AL);
#if 0 #if 0
// Moved to: ARM32::AssemblerARM32. // Moved to: ARM32::AssemblerARM32::bx()
void bx(Register rm, Condition cond = AL); void bx(Register rm, Condition cond = AL);
#endif #endif
void blx(Register rm, Condition cond = AL); void blx(Register rm, Condition cond = AL);
...@@ -1097,7 +1110,7 @@ class Assembler : public ValueObject { ...@@ -1097,7 +1110,7 @@ class Assembler : public ValueObject {
Register pp); Register pp);
#if 0 #if 0
// Moved to class AssemblerARM32. // Moved to ARM32::AssemblerARM32::emitType01()
void EmitType01(Condition cond, void EmitType01(Condition cond,
int type, int type,
Opcode opcode, Opcode opcode,
...@@ -1109,11 +1122,14 @@ class Assembler : public ValueObject { ...@@ -1109,11 +1122,14 @@ class Assembler : public ValueObject {
void EmitType5(Condition cond, int32_t offset, bool link); void EmitType5(Condition cond, int32_t offset, bool link);
#if 0
// Moved to ARM32::AssemberARM32::emitMemOp()
void EmitMemOp(Condition cond, void EmitMemOp(Condition cond,
bool load, bool load,
bool byte, bool byte,
Register rd, Register rd,
Address ad); Address ad);
#endif
void EmitMemOpAddressMode3(Condition cond, void EmitMemOpAddressMode3(Condition cond,
int32_t mode, int32_t mode,
......
...@@ -103,10 +103,14 @@ public: ...@@ -103,10 +103,14 @@ public:
void bkpt(uint16_t Imm16); void bkpt(uint16_t Imm16);
void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond);
void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond); void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL); void bx(RegARM32::GPRRegister Rm, CondARM32::Cond Cond = CondARM32::AL);
void str(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond);
void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond); bool SetFlags, CondARM32::Cond Cond);
...@@ -130,6 +134,13 @@ private: ...@@ -130,6 +134,13 @@ private:
// oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM section A5.2.3). // oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM section A5.2.3).
void emitType01(CondARM32::Cond Cond, uint32_t Type, uint32_t Opcode, void emitType01(CondARM32::Cond Cond, uint32_t Type, uint32_t Opcode,
bool SetCc, uint32_t Rn, uint32_t Rd, uint32_t imm12); bool SetCc, uint32_t Rn, uint32_t Rd, uint32_t imm12);
// 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.
void emitMemOp(CondARM32::Cond Cond, uint32_t InstType, bool IsLoad,
bool IsByte, uint32_t Rt, uint32_t Address);
}; };
} // end of namespace ARM32 } // end of namespace ARM32
......
...@@ -617,13 +617,28 @@ void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { ...@@ -617,13 +617,28 @@ void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
// Note: Loop is used so that we can short circuit using break. // Note: Loop is used so that we can short circuit using break.
do { do {
if (Dest->hasReg()) { if (Dest->hasReg()) {
Type DestTy = Dest->getType(); const Type DestTy = Dest->getType();
const bool DestIsVector = isVectorType(DestTy); const bool DestIsVector = isVectorType(DestTy);
const bool DestIsScalarFP = isScalarFloatingType(DestTy); const bool DestIsScalarFP = isScalarFloatingType(DestTy);
const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
if (DestIsVector || DestIsScalarFP || CoreVFPMove) if (DestIsVector || DestIsScalarFP || CoreVFPMove)
break; break;
Asm->mov(Dest, Src0, getPredicate()); if (isMemoryAccess(Src0)) {
// TODO(kschimpf) Figure out how to do ldr on CoreVPFMove? (see
// emitSingleDestSingleSource, local variable LoadOpcode).
Asm->ldr(Dest, Src0, getPredicate());
} else {
Asm->mov(Dest, Src0, getPredicate());
}
return;
} else {
const Type Src0Type = Src0->getType();
const bool Src0IsVector = isVectorType(Src0Type);
const bool Src0IsScalarFP = isScalarFloatingType(Src0Type);
const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
if (Src0IsVector || Src0IsScalarFP || CoreVFPMove)
break;
Asm->str(Src0, Dest, getPredicate());
return; return;
} }
} while (0); } while (0);
......
; Show that we can handle variable (i.e. stack) spills.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=ASM
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=IASM
define internal i32 @add1ToR0(i32 %p) {
%v = add i32 %p, 1
ret i32 %v
}
; ASM-LABEL: add1ToR0:
; IASM-LABEL: add1ToR0:
; ASM: sub sp, sp, #8
; IASM: .byte 0x8
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: str r0, [sp, #4]
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r0, [sp, #4]
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: add r0, r0, #1
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: str r0, [sp]
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r0, [sp]
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: add sp, sp, #8
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: bx lr
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
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