Commit a990f0c5 by Karl Schimpf

Add mls instruction to the ARM integrated assembler.

parent 19413a56
......@@ -390,9 +390,8 @@ void Assembler::mla(Register rd, Register rn,
// Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
EmitMulOp(cond, B21, ra, rd, rn, rm);
}
#endif
// Moved to ARM32::AssemblerARM32::mla()
void Assembler::mls(Register rd, Register rn,
Register rm, Register ra, Condition cond) {
// rd <- ra - rn * rm.
......@@ -404,7 +403,7 @@ void Assembler::mls(Register rd, Register rn,
sub(rd, ra, Operand(IP), cond);
}
}
#endif
void Assembler::smull(Register rd_lo, Register rd_hi,
Register rn, Register rm, Condition cond) {
......
......@@ -140,9 +140,7 @@ class Operand : public ValueObject {
type_ = 1;
encoding_ = immediate;
}
#endif
#if 0
// Moved to decodeOperand() and encodeRotatedImm8() in IceAssemblerARM32.cpp
// Data-processing operands - Rotated immediate.
Operand(uint32_t rotate, uint32_t immed8) {
......@@ -450,9 +448,7 @@ class Assembler : public ValueObject {
// Moved to ARM32::AssemblerARM32::and_()
// Data-processing instructions.
void and_(Register rd, Register rn, Operand o, Condition cond = AL);
#endif
#if 0
// Moved to ARM32::AssemblerARM32::eor()
void eor(Register rd, Register rn, Operand o, Condition cond = AL);
......@@ -503,9 +499,7 @@ class Assembler : public ValueObject {
// Moved to ARM32::IceAssemblerARM32::mov()
void mov(Register rd, Operand o, Condition cond = AL);
void movs(Register rd, Operand o, Condition cond = AL);
#endif
#if 0
// Moved to ARM32::IceAssemblerARM32::bic()
void bic(Register rd, Register rn, Operand o, Condition cond = AL);
void bics(Register rd, Register rn, Operand o, Condition cond = AL);
......@@ -527,11 +521,14 @@ class Assembler : public ValueObject {
// Moved to ARM32::AssemblerARM32::mla()
void mla(Register rd, Register rn, Register rm, Register ra,
Condition cond = AL);
#endif
// Moved to ARM32::AssemblerARM32::mls()
void mls(Register rd, Register rn, Register rm, Register ra,
Condition cond = AL);
#endif
void smull(Register rd_lo, Register rd_hi, Register rn, Register rm,
Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::umull();
void umull(Register rd_lo, Register rd_hi, Register rn, Register rm,
......@@ -564,10 +561,12 @@ class Assembler : public ValueObject {
void ldrb(Register rd, Address ad, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::str()
void strb(Register rd, Address ad, Condition cond = AL);
#endif
// Moved to ARM32::AssemblerARM32::ldr()
void ldrh(Register rd, Address ad, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::str()
void strh(Register rd, Address ad, Condition cond = AL);
#endif
void ldrsb(Register rd, Address ad, Condition cond = AL);
void ldrsh(Register rd, Address ad, Condition cond = AL);
......@@ -597,6 +596,7 @@ class Assembler : public ValueObject {
// Miscellaneous instructions.
void clrex();
#if 0
// Moved to ARM32::AssemblerARM32::nop().
void nop(Condition cond = AL);
......
......@@ -1753,9 +1753,27 @@ void AssemblerARM32::mla(const Operand *OpRd, const Operand *OpRn,
verifyRegNotPc(Rm, "Rm", MlaName);
verifyRegNotPc(Ra, "Ra", MlaName);
constexpr IValueT MlaOpcode = B21;
constexpr bool SetFlags = false;
constexpr bool SetFlags = true;
// Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, !SetFlags, MlaName);
}
void AssemblerARM32::mls(const Operand *OpRd, const Operand *OpRn,
const Operand *OpRm, const Operand *OpRa,
CondARM32::Cond Cond) {
constexpr const char *MlsName = "mls";
IValueT Rd = encodeRegister(OpRd, "Rd", MlsName);
IValueT Rn = encodeRegister(OpRn, "Rn", MlsName);
IValueT Rm = encodeRegister(OpRm, "Rm", MlsName);
IValueT Ra = encodeRegister(OpRa, "Ra", MlsName);
verifyRegNotPc(Rd, "Rd", MlsName);
verifyRegNotPc(Rn, "Rn", MlsName);
verifyRegNotPc(Rm, "Rm", MlsName);
verifyRegNotPc(Ra, "Ra", MlsName);
constexpr IValueT MlsOpcode = B22 | B21;
constexpr bool SetFlags = true;
// Assembler registers rd, rn, rm, ra are encoded as rn, rm, rs, rd.
emitMulOp(Cond, MlaOpcode, Ra, Rd, Rn, Rm, SetFlags, MlaName);
emitMulOp(Cond, MlsOpcode, Ra, Rd, Rn, Rm, !SetFlags, MlsName);
}
void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
......
......@@ -242,6 +242,9 @@ public:
void mla(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm,
const Operand *OpRa, CondARM32::Cond Cond);
void mls(const Operand *OpRd, const Operand *OpRn, const Operand *OpRm,
const Operand *OpRa, CondARM32::Cond Cond);
void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
......
......@@ -230,6 +230,14 @@ template <> void InstARM32Mla::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func);
}
template <> void InstARM32Mls::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 3);
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->mls(getDest(), getSrc(0), getSrc(1), getSrc(2), getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
void InstARM32Pred::emitCmpLike(const char *Opcode, const InstARM32Pred *Inst,
const Cfg *Func) {
if (!BuildDefs::dump())
......
; Show that we know how to translate mls.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 --mattr=hwdiv-arm \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --mattr=hwdiv-arm | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 --mattr=hwdiv-arm \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --mattr=hwdiv-arm | FileCheck %s --check-prefix=DIS
define internal i32 @testMls(i32 %a, i32 %b) {
; ASM-LABEL: testMls:
; DIS-LABEL: 00000000 <testMls>:
; IASM-LABEL: testMls:
entry:
; ASM-NEXT: .LtestMls$entry:
; IASM-NEXT: .LtestMls$entry:
; 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
; IASM-NEXT: .byte 0xe5
%rem = srem i32 %a, %b
; ASM-NEXT: ldr r0, [sp, #8]
; DIS-NEXT: c: e59d0008
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r1, [sp, #4]
; DIS-NEXT: 10: e59d1004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: tst r1, r1
; DIS-NEXT: 14: e1110001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x11
; IASM-NEXT: .byte 0xe1
; ASM-NEXT: bne .LtestMls$local$__0
; DIS-NEXT: 18: 1a000000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1a
; ASM-NEXT: .long 0xe7fedef0
; DIS-NEXT: 1c: e7fedef0
; IASM-NEXT: .long 0xe7fedef0
; ASM-NEXT: .LtestMls$local$__0:
; IASM-NEXT: .LtestMls$local$__0:
; ASM-NEXT: ldr r1, [sp, #4]
; DIS-NEXT: 20: e59d1004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: sdiv r2, r0, r1
; DIS-NEXT: 24: e712f110
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xf1
; IASM-NEXT: .byte 0x12
; IASM-NEXT: .byte 0xe7
; ASM-NEXT: mls r0, r2, r1, r0
; DIS-NEXT: 28: e0600192
; IASM-NEXT: .byte 0x92
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0xe0
ret i32 %rem
}
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