Commit 430e8447 by Karl Schimpf

Add UMULL to ARM integrated assembler.

Also formatted IceCfg.cpp, since it needed it. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1422253003 .
parent b9f27229
...@@ -393,7 +393,7 @@ void Assembler::muls(Register rd, Register rn, Register rm, Condition cond) { ...@@ -393,7 +393,7 @@ void Assembler::muls(Register rd, Register rn, Register rm, Condition cond) {
} }
#if 0 #if 0
// Moved to ARM32::AssemblerARM32::mla // Moved to ARM32::AssemblerARM32::mla()
void Assembler::mla(Register rd, Register rn, void Assembler::mla(Register rd, Register rn,
Register rm, Register ra, Condition cond) { Register rm, Register ra, Condition cond) {
// rd <- ra + rn * rm. // rd <- ra + rn * rm.
...@@ -422,13 +422,14 @@ void Assembler::smull(Register rd_lo, Register rd_hi, ...@@ -422,13 +422,14 @@ void Assembler::smull(Register rd_lo, Register rd_hi,
EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm); EmitMulOp(cond, B23 | B22, rd_lo, rd_hi, rn, rm);
} }
#if 0
// Moved to ARM32::AssemblerARM32::umull()
void Assembler::umull(Register rd_lo, Register rd_hi, void Assembler::umull(Register rd_lo, Register rd_hi,
Register rn, Register rm, Condition cond) { Register rn, Register rm, Condition cond) {
// Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs. // Assembler registers rd_lo, rd_hi, rn, rm are encoded as rd, rn, rm, rs.
EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm); EmitMulOp(cond, B23, rd_lo, rd_hi, rn, rm);
} }
#endif
void Assembler::umlal(Register rd_lo, Register rd_hi, void Assembler::umlal(Register rd_lo, Register rd_hi,
Register rn, Register rm, Condition cond) { Register rn, Register rm, Condition cond) {
......
...@@ -530,8 +530,11 @@ class Assembler : public ValueObject { ...@@ -530,8 +530,11 @@ class Assembler : public ValueObject {
Condition cond = AL); Condition cond = AL);
void smull(Register rd_lo, Register rd_hi, Register rn, Register rm, void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
Condition cond = AL); Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::umull();
void umull(Register rd_lo, Register rd_hi, Register rn, Register rm, void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
Condition cond = AL); Condition cond = AL);
#endif
void smlal(Register rd_lo, Register rd_hi, Register rn, Register rm, void smlal(Register rd_lo, Register rd_hi, Register rn, Register rm,
Condition cond = AL); Condition cond = AL);
void umlal(Register rd_lo, Register rd_hi, Register rn, Register rm, void umlal(Register rd_lo, Register rd_hi, Register rn, Register rm,
......
...@@ -48,6 +48,7 @@ static constexpr IValueT B15 = 1 << 15; ...@@ -48,6 +48,7 @@ static constexpr IValueT B15 = 1 << 15;
static constexpr IValueT B20 = 1 << 20; static constexpr IValueT B20 = 1 << 20;
static constexpr IValueT B21 = 1 << 21; static constexpr IValueT B21 = 1 << 21;
static constexpr IValueT B22 = 1 << 22; static constexpr IValueT B22 = 1 << 22;
static constexpr IValueT B23 = 1 << 23;
static constexpr IValueT B24 = 1 << 24; static constexpr IValueT B24 = 1 << 24;
static constexpr IValueT B25 = 1 << 25; static constexpr IValueT B25 = 1 << 25;
static constexpr IValueT B26 = 1 << 26; static constexpr IValueT B26 = 1 << 26;
...@@ -1004,7 +1005,7 @@ void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn, ...@@ -1004,7 +1005,7 @@ void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn,
return setNeedsTextFixup(); return setNeedsTextFixup();
if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc || if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc ||
Rm == RegARM32::Encoded_Reg_pc) Rm == RegARM32::Encoded_Reg_pc)
llvm::report_fatal_error("Sdiv instruction unpredictable on pc"); llvm::report_fatal_error("Udiv instruction unpredictable on pc");
// Assembler registers rd, rn, rm are encoded as rn, rm, rs. // Assembler registers rd, rn, rm are encoded as rn, rm, rs.
constexpr IValueT Opcode = B21; constexpr IValueT Opcode = B21;
emitDivOp(Cond, Opcode, Rd, Rn, Rm); emitDivOp(Cond, Opcode, Rd, Rn, Rm);
...@@ -1049,5 +1050,30 @@ void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1, ...@@ -1049,5 +1050,30 @@ void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1,
emitCompareOp(Opcode, OpRn, OpSrc1, Cond); emitCompareOp(Opcode, OpRn, OpSrc1, Cond);
} }
void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi,
const Operand *OpRn, const Operand *OpRm,
CondARM32::Cond Cond) {
// UMULL - ARM section A8.8.257, encoding A1:
// umull<c> <RdLo>, <RdHi>, <Rn>, <Rm>
//
// cccc0000100shhhhllllmmmm1001nnnn where hhhh=RdHi, llll=RdLo, nnnn=Rn,
// mmmm=Rm, and s=SetFlags
IValueT RdLo;
IValueT RdHi;
IValueT Rn;
IValueT Rm;
if (decodeOperand(OpRdLo, RdLo) != DecodedAsRegister ||
decodeOperand(OpRdHi, RdHi) != DecodedAsRegister ||
decodeOperand(OpRn, Rn) != DecodedAsRegister ||
decodeOperand(OpRm, Rm) != DecodedAsRegister)
return setNeedsTextFixup();
if (RdHi == RegARM32::Encoded_Reg_pc || RdLo == RegARM32::Encoded_Reg_pc ||
Rn == RegARM32::Encoded_Reg_pc || Rm == RegARM32::Encoded_Reg_pc ||
RdHi == RdLo)
llvm::report_fatal_error("Umull instruction unpredictable on pc");
constexpr bool SetFlags = false;
emitMulOp(Cond, B23, RdLo, RdHi, Rn, Rm, SetFlags);
}
} // end of namespace ARM32 } // end of namespace ARM32
} // end of namespace Ice } // end of namespace Ice
...@@ -210,6 +210,9 @@ public: ...@@ -210,6 +210,9 @@ public:
void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
CondARM32::Cond Cond); CondARM32::Cond Cond);
void umull(const Operand *OpRdLo, const Operand *OpRdHi, const Operand *OpRn,
const Operand *OpRm, CondARM32::Cond Cond);
static bool classof(const Assembler *Asm) { static bool classof(const Assembler *Asm) {
return Asm->getKind() == Asm_ARM32; return Asm->getKind() == Asm_ARM32;
} }
......
...@@ -1398,6 +1398,14 @@ void InstARM32Umull::emit(const Cfg *Func) const { ...@@ -1398,6 +1398,14 @@ void InstARM32Umull::emit(const Cfg *Func) const {
getSrc(1)->emit(Func); getSrc(1)->emit(Func);
} }
void InstARM32Umull::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 2);
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->umull(getDest(), DestHi, getSrc(0), getSrc(1), getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
void InstARM32Umull::dump(const Cfg *Func) const { void InstARM32Umull::dump(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -1086,6 +1086,7 @@ public: ...@@ -1086,6 +1086,7 @@ public:
InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate);
} }
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override; void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); }
......
...@@ -73,7 +73,12 @@ define internal i64 @MulTwoI64Regs(i64 %a, i64 %b) { ...@@ -73,7 +73,12 @@ define internal i64 @MulTwoI64Regs(i64 %a, i64 %b) {
; IASM-NEXT: .byte 0x31 ; IASM-NEXT: .byte 0x31
; IASM-NEXT: .byte 0x21 ; IASM-NEXT: .byte 0x21
; IASM-NEXT: .byte 0xe0 ; IASM-NEXT: .byte 0xe0
; IASM-NEXT: umull r0, r2, r0, r2
; IASM-NEXT: .byte 0x90
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x82
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x1 ; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x20 ; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x82 ; IASM-NEXT: .byte 0x82
......
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