Commit e559be77 by Karl Schimpf

Add MVN (register, immediate) to ARM integrated assembler.

Also removes redundant rule checks in emitType01(). BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=jpp@chromium.org Review URL: https://codereview.chromium.org/1460523005 .
parent f4198548
......@@ -92,7 +92,7 @@ void Assembler::EmitType01(Condition cond,
Emit(encoding);
}
// Moved to ARM32::AssemblerARM32::emitType05.
// Moved to ARM32::AssemblerARM32::emitType05()
void Assembler::EmitType5(Condition cond, int32_t offset, bool link) {
ASSERT(cond != kNoCondition);
int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
......@@ -304,26 +304,26 @@ void Assembler::movs(Register rd, Operand o, Condition cond) {
#if 0
// Moved to ARM32::AssemblerARM32::bic();
// Moved to ARM32::AssemblerARM32::bic()
void Assembler::bic(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), BIC, 0, rn, rd, o);
}
// Moved to ARM32::AssemblerARM32::bic();
// Moved to ARM32::AssemblerARM32::bic()
void Assembler::bics(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), BIC, 1, rn, rd, o);
}
#endif
// Moved to ARM32::AssemblerARM32::mvn()
void Assembler::mvn(Register rd, Operand o, Condition cond) {
EmitType01(cond, o.type(), MVN, 0, R0, rd, o);
}
// Moved to ARM32::AssemblerARM32::mvn()
void Assembler::mvns(Register rd, Operand o, Condition cond) {
EmitType01(cond, o.type(), MVN, 1, R0, rd, o);
}
#endif
void Assembler::clz(Register rd, Register rm, Condition cond) {
ASSERT(rd != kNoRegister);
......@@ -340,7 +340,7 @@ void Assembler::clz(Register rd, Register rm, Condition cond) {
#if
// Moved to ARM32::AssemblerARM32::movw
// Moved to ARM32::AssemblerARM32::movw()
void Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
ASSERT(cond != kNoCondition);
int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
......@@ -350,7 +350,7 @@ void Assembler::movw(Register rd, uint16_t imm16, Condition cond) {
}
// Moved to ARM32::AssemblerARM32::movt
// Moved to ARM32::AssemblerARM32::movt()
void Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
ASSERT(cond != kNoCondition);
int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
......@@ -361,7 +361,7 @@ void Assembler::movt(Register rd, uint16_t imm16, Condition cond) {
#endif
#if 0
// Moved to ARM32::AssemblerARM32::emitMulOp
// Moved to ARM32::AssemblerARM32::emitMulOp()
void Assembler::EmitMulOp(Condition cond, int32_t opcode,
Register rd, Register rn,
Register rm, Register rs) {
......@@ -380,7 +380,7 @@ void Assembler::EmitMulOp(Condition cond, int32_t opcode,
Emit(encoding);
}
// Moved to ARM32::AssemblerARM32::mul
// Moved to ARM32::AssemblerARM32::mul()
void Assembler::mul(Register rd, Register rn, Register rm, Condition cond) {
// Assembler registers rd, rn, rm are encoded as rn, rm, rs.
EmitMulOp(cond, 0, R0, rd, rn, rm);
......@@ -2104,7 +2104,7 @@ void Assembler::UpdateRangeFeedback(Register value,
}
#if 0
// Moved to ::canEncodeBranchoffset in IceAssemblerARM32.cpp.
// Moved to ::canEncodeBranchoffset() in IceAssemblerARM32.cpp.
static bool CanEncodeBranchOffset(int32_t offset) {
ASSERT(Utils::IsAligned(offset, 4));
// Note: This check doesn't take advantage of the fact that offset>>2
......@@ -2112,7 +2112,7 @@ static bool CanEncodeBranchOffset(int32_t offset) {
return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset);
}
// Moved to ARM32::AssemblerARM32::encodeBranchOffset.
// Moved to ARM32::AssemblerARM32::encodeBranchOffset()
int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
// The offset is off by 8 due to the way the ARM CPUs read PC.
offset -= Instr::kPCReadOffset;
......@@ -2129,7 +2129,7 @@ int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
return (inst & ~kBranchOffsetMask) | offset;
}
// Moved to AssemberARM32::decodeBranchOffset.
// Moved to AssemberARM32::decodeBranchOffset()
int Assembler::DecodeBranchOffset(int32_t inst) {
// Sign-extend, left-shift by 2, then add 8.
return ((((inst & kBranchOffsetMask) << 8) >> 6) + Instr::kPCReadOffset);
......
......@@ -507,10 +507,11 @@ class Assembler : public ValueObject {
// 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);
#endif
// Moved to ARM32::IceAssemblerARM32::mvn()
void mvn(Register rd, Operand o, Condition cond = AL);
void mvns(Register rd, Operand o, Condition cond = AL);
#endif
// Miscellaneous data-processing instructions.
void clz(Register rd, Register rm, Condition cond = AL);
......
......@@ -187,16 +187,17 @@ enum DecodedResult {
// Value=rrrriiiiiiii where rrrr is the rotation, and iiiiiiii is the imm8
// value.
DecodedAsRotatedImm8,
// i.e. 0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
// Value=0000000pu0w0nnnn0000iiiiiiiiiiii where nnnn is the base register Rn,
// p=1 if pre-indexed addressing, u=1 if offset positive, w=1 if writeback to
// Rn should be used, and iiiiiiiiiiii defines the rotated Imm8 value.
DecodedAsImmRegOffset,
// i.e. 0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn,
// Value=0000000pu0w00nnnnttttiiiiiss0mmmm where nnnn is the base register Rn,
// mmmm is the index register Rm, iiiii is the shift amount, ss is the shift
// kind, p=1 if pre-indexed addressing, u=1 if offset positive, and w=1 if
// writeback to Rn.
DecodedAsShiftRotateImm5,
// i.e. 000000000000000000000iiiii0000000 iiii defines Imm5 value to shift.
// Value=000000000000000000000iiiii0000000 iiii defines the Imm5 value to
// shift.
DecodedAsShiftImm5,
// Value is 32bit integer constant.
DecodedAsConstI32
......@@ -218,8 +219,8 @@ IValueT encodeShiftRotateImm5(IValueT Rm, OperandARM32::ShiftKind Shift,
return (imm5 << kShiftImmShift) | (encodeShift(Shift) << kShiftShift) | Rm;
}
// Encodes mmmmtt01ssss for data-processing (2nd) operands where mmmm=Rm,
// ssss=Rs, and tt=Shift.
// Encodes mmmmtt01ssss for data-processing operands where mmmm=Rm, ssss=Rs, and
// tt=Shift.
IValueT encodeShiftRotateReg(IValueT Rm, OperandARM32::ShiftKind Shift,
IValueT Rs) {
return (Rs << kRsShift) | (encodeShift(Shift) << kShiftShift) | B4 |
......@@ -481,15 +482,6 @@ void AssemblerARM32::emitType01(IValueT Opcode, const Operand *OpRd,
void AssemblerARM32::emitType01(IValueT Opcode, IValueT Rd, IValueT Rn,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond, EmitChecks RuleChecks) {
switch (RuleChecks) {
case NoChecks:
break;
case RdIsPcAndSetFlags:
if (((Rd == RegARM32::Encoded_Reg_pc) && SetFlags))
// Conditions of rule violated.
return setNeedsTextFixup();
break;
}
IValueT Src1Value;
// TODO(kschimpf) Other possible decodings of data operations.
......@@ -564,8 +556,9 @@ void AssemblerARM32::emitCompareOp(IValueT Opcode, const Operand *OpRn,
// XXX (register)
// XXX<c> <Rn>, <Rm>{, <shift>}
//
// ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm,
// iiiii=Shift, tt=ShiftKind, yyy=kInstTypeDataRegister, and xxxx=Opcode.
// ccccyyyxxxx1nnnn0000iiiiitt0mmmm where cccc=Cond, nnnn=Rn, mmmm=Rm, iiiii
// defines shift constant, tt=ShiftKind, yyy=kInstTypeDataRegister, and
// xxxx=Opcode.
//
// XXX (immediate)
// XXX<c> <Rn>, #<RotatedImm8>
......@@ -1047,6 +1040,28 @@ void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc,
emitInst(Encoding);
}
void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) {
// MVN (immediate) - ARM section A8.8.115, encoding A1:
// mvn{s}<c> <Rd>, #<const>
//
// cccc0011111s0000ddddiiiiiiiiiiii where cccc=Cond, s=SetFlags=0, dddd=Rd,
// and iiiiiiiiiiii=const
//
// MVN (register) - ARM section A8.8.116, encoding A1:
// mvn{s}<c> <Rd>, <Rm>{, <shift>
//
// cccc0001111s0000ddddiiiiitt0mmmm where cccc=Cond, s=SetFlags=0, dddd=Rd,
// mmmm=Rm, iiii defines shift constant, and tt=ShiftKind.
IValueT Rd;
if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
return setNeedsTextFixup();
constexpr IValueT MvnOpcode = B3 | B2 | B1 | B0; // i.e. 1111
constexpr IValueT Rn = 0;
constexpr bool SetFlags = false;
emitType01(MvnOpcode, Rd, Rn, OpSrc, SetFlags, Cond, RdIsPcAndSetFlags);
}
void AssemblerARM32::sbc(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
......
......@@ -238,6 +238,8 @@ public:
void mul(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void mvn(const Operand *OpRd, const Operand *OpScc, CondARM32::Cond Cond);
void orr(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
......
......@@ -1158,6 +1158,14 @@ template <> void InstARM32Movt::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func);
}
template <> void InstARM32Mvn::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1);
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->mvn(getDest(), getSrc(0), getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
template <> void InstARM32Uxt::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1);
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
......
; Tests MVN instruction.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; 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 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; 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 | FileCheck %s --check-prefix=DIS
define internal void @mvmEx(i32 %a, i32 %b) {
; ASM-LABEL:mvmEx:
; DIS-LABEL:00000000 <mvmEx>:
; IASM-LABEL:mvmEx:
entry:
; ASM-NEXT:.LmvmEx$entry:
; IASM-NEXT:.LmvmEx$entry:
; ASM-NEXT: sub sp, sp, #24
; DIS-NEXT: 0: e24dd018
; IASM-NEXT: .byte 0x18
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: str r0, [sp, #20]
; ASM-NEXT: # [sp, #20] = def.pseudo
; DIS-NEXT: 4: e58d0014
; IASM-NEXT: .byte 0x14
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: str r1, [sp, #16]
; ASM-NEXT: # [sp, #16] = def.pseudo
; DIS-NEXT: 8: e58d1010
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
%b.arg_trunc = trunc i32 %b to i1
; ASM-NEXT: ldr r0, [sp, #16]
; DIS-NEXT: c: e59d0010
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: and r0, r0, #1
; DIS-NEXT: 10: e2000001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: strb r0, [sp, #12]
; ASM-NEXT: # [sp, #12] = def.pseudo
; DIS-NEXT: 14: e5cd000c
; IASM-NEXT: strb r0, [sp, #12]
%a.arg_trunc = trunc i32 %a to i1
; ASM-NEXT: ldr r0, [sp, #20]
; DIS-NEXT: 18: e59d0014
; IASM-NEXT: .byte 0x14
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: and r0, r0, #1
; DIS-NEXT: 1c: e2000001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: strb r0, [sp, #8]
; ASM-NEXT: # [sp, #8] = def.pseudo
; DIS-NEXT: 20: e5cd0008
; IASM-NEXT: strb r0, [sp, #8]
%conv = zext i1 %a.arg_trunc to i32
; ASM-NEXT: ldrb r0, [sp, #8]
; DIS-NEXT: 24: e5dd0008
; IASM-NEXT: ldrb r0, [sp, #8]
; ASM-NEXT: str r0, [sp, #4]
; ASM-NEXT: # [sp, #4] = def.pseudo
; DIS-NEXT: 28: e58d0004
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
%ignore = sext i1 %b.arg_trunc to i32
; ASM-NEXT: mov r0, #0
; DIS-NEXT: 2c: e3a00000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe3
; ASM-NEXT: ldrb r1, [sp, #12]
; DIS-NEXT: 30: e5dd100c
; IASM-NEXT: ldrb r1, [sp, #12]
; ASM-NEXT: tst r1, #1
; DIS-NEXT: 34: e3110001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x11
; IASM-NEXT: .byte 0xe3
; ********* Use of MVN ********
; ASM-NEXT: mvn r1, #0
; DIS-NEXT: 38: e3e01000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0xe3
; ASM-NEXT: movne r0, r1
; DIS-NEXT: 3c: 11a00001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0x11
ret void
}
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