Commit 5ff0cfb4 by Karl Schimpf

Handle another form of MOVW in ARM integrated assembler.

Extends assembler movw method to handle integer constants in addition to relocatable constants, since (32-bit) integer constants are frequently used in movw instructions. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1440693002 .
parent 7b3d9cbb
......@@ -754,32 +754,56 @@ void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
emitType01(Mov, Rd, Rn, OpSrc, SetFlags, Cond);
}
void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16,
bool SetFlags, CondARM32::Cond Cond) {
if (!isConditionDefined(Cond) || !Utils::IsAbsoluteUint(16, Imm16))
return setNeedsTextFixup();
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode |
(encodeBool(SetFlags) << kSShift) |
((Imm16 >> 12) << 16) | Rd << kRdShift |
(Imm16 & 0xfff);
emitInst(Encoding);
}
void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) {
IValueT Rd;
if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
return setNeedsTextFixup();
auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc);
if (Src == nullptr)
if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) {
// MOVW (immediate) - ARM section A8.8.102, encoding A2:
// movw<c> <Rd>, #<imm16>
//
// cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
// iiiiiiiiiiiiiiii=imm16.
if (!isConditionDefined(Cond))
// Conditions of rule violated.
return setNeedsTextFixup();
// Use 0 for the lower 16 bits of the relocatable, and add a fixup to
// install the correct bits.
constexpr bool IsMovW = true;
emitFixup(createMoveFixup(IsMovW, Src));
constexpr IValueT Imm16 = 0;
constexpr bool SetFlags = false;
emitMovw(B25 | B24, Rd, Imm16, SetFlags, Cond);
return;
}
IValueT ConstVal;
if (decodeOperand(OpSrc, ConstVal) != DecodedAsConstI32)
return setNeedsTextFixup();
// MOVW (immediate) - ARM section A8.8.102, encoding A2:
// movw<c> <Rd>, #<imm16>
// TODO(kschimpf): Determine if we want to handle rotated immediate 8 values
// to handle cases where the constant is greater than 16 bits (encoding A1
// below). For now, handle using encoding A2.
constexpr bool SetFlags = 0;
emitMovw(B25 | B24, Rd, ConstVal, SetFlags, Cond);
return;
// MOVW (immediate) - ARM section A8.8.102, encoding A1:
// movw<c> <Rd>, #<RotatedImm8>
//
// cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
// iiiiiiiiiiiiiiii=imm16.
if (!isConditionDefined(Cond))
// Conditions of rule violated.
return setNeedsTextFixup();
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
// Use 0 for the lower 16 bits of the relocatable, and add a fixup to
// install the correct bits.
constexpr bool IsMovW = true;
emitFixup(createMoveFixup(IsMovW, Src));
constexpr IValueT Imm16 = 0;
const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 |
B24 | ((Imm16 >> 12) << 16) | Rd << kRdShift |
(Imm16 & 0xfff);
emitInst(Encoding);
// cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, s=SetFlags=0,
// and iiiiiiiiiiii is a shift-rotated value defining RotatedImm8.
}
void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc,
......
......@@ -314,6 +314,12 @@ private:
// Returns the offset encoded in the branch instruction Inst.
static IOffsetT decodeBranchOffset(IValueT Inst);
// Implements movw, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii where
// cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and
// iiiiiiiiiiiiiiii=Imm16.
void emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, bool SetFlags,
CondARM32::Cond Cond);
};
} // end of namespace ARM32
......
; Show that we handle constants in a movw, when it isn't represented as
; ConstantRelocatable (see mov-imm.ll for the ConstantRelocatable case).
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --test-stack-extra 4084 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --test-stack-extra 4084 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 -unsafe-ias \
; RUN: --test-stack-extra 4084 | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 -unsafe-ias --test-stack-extra 4084 \
; RUN: | FileCheck %s --check-prefix=DIS
define internal i32 @foo(i32 %x) {
entry:
; ASM-LABEL: foo:
; ASM-NEXT: .Lfoo$entry:
; ******* Movw case to check *******
; ASM-NEXT: movw ip, #4092
; ASM-NEXT: sub sp, sp, ip
; ASM-NEXT: str r0, [sp, #4088]
; DIS-LABEL: 00000000 <foo>:
; DIS-NEXT: 0: e300cffc
; DIS-NEXT: 4: e04dd00c
; DIS-NEXT: 8: e58d0ff8
; IASM-LABEL: foo:
; IASM-NEXT: .Lfoo$entry:
; IASM-NEXT: .byte 0xfc
; IASM-NEXT: .byte 0xcf
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe3
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0xf8
; IASM-NEXT: .byte 0xf
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
%mul = mul i32 %x, %x
; ASM-NEXT: ldr r0, [sp, #4088]
; ASM-NEXT: ldr r1, [sp, #4088]
; ASM-NEXT: mul r0, r0, r1
; ASM-NEXT: str r0, [sp, #4084]
; DIS-NEXT: c: e59d0ff8
; DIS-NEXT: 10: e59d1ff8
; DIS-NEXT: 14: e0000190
; DIS-NEXT: 18: e58d0ff4
; IASM-NEXT: .byte 0xf8
; IASM-NEXT: .byte 0xf
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; IASM-NEXT: .byte 0xf8
; IASM-NEXT: .byte 0x1f
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; IASM-NEXT: .byte 0x90
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0xf4
; IASM-NEXT: .byte 0xf
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
ret i32 %mul
; ASM-NEXT: ldr r0, [sp, #4084]
; ******* Movw case to check *******
; ASM-NEXT: movw ip, #4092
; ASM-NEXT: add sp, sp, ip
; ASM-NEXT: bx lr
; DIS-NEXT: 1c: e59d0ff4
; DIS-NEXT: 20: e300cffc
; DIS-NEXT: 24: e08dd00c
; DIS-NEXT: 28: e12fff1e
; IASM-NEXT: .byte 0xf4
; IASM-NEXT: .byte 0xf
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; IASM-NEXT: .byte 0xfc
; IASM-NEXT: .byte 0xcf
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe3
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe0
; 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