Commit 7cfe9a0f by Karl Schimpf

Add missing form of movt to ARM integrated assembler.

Add allowing movt to work on integer constants that aren't relocatable. Also clean up code sharing between movw and movt. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1500073002 .
parent a761e410
...@@ -1189,15 +1189,25 @@ void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc, ...@@ -1189,15 +1189,25 @@ void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
MovName); MovName);
} }
void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, void AssemblerARM32::emitMovwt(CondARM32::Cond Cond, bool IsMovW,
bool SetFlags, CondARM32::Cond Cond) { const Operand *OpRd, const Operand *OpSrc,
constexpr const char *MovwName = "movw"; const char *MovName) {
verifyCondDefined(Cond, MovwName); IValueT Opcode = B25 | B24 | (IsMovW ? 0 : B22);
IValueT Rd = encodeRegister(OpRd, "Rd", MovName);
IValueT Imm16;
if (const auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc)) {
emitFixup(createMoveFixup(IsMovW, Src));
// Use 0 for the lower 16 bits of the relocatable, and add a fixup to
// install the correct bits.
Imm16 = 0;
} else if (encodeOperand(OpSrc, Imm16) != EncodedAsConstI32) {
llvm::report_fatal_error(std::string(MovName) + ": Not i32 constant");
}
verifyCondDefined(Cond, MovName);
if (!Utils::IsAbsoluteUint(16, Imm16)) if (!Utils::IsAbsoluteUint(16, Imm16))
llvm::report_fatal_error(std::string(MovwName) + ": Not I16 constant"); llvm::report_fatal_error(std::string(MovName) + ": Constant not i16");
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode | const IValueT Encoding = encodeCondition(Cond) << kConditionShift | Opcode |
(encodeBool(SetFlags) << kSShift) |
((Imm16 >> 12) << 16) | Rd << kRdShift | ((Imm16 >> 12) << 16) | Rd << kRdShift |
(Imm16 & 0xfff); (Imm16 & 0xfff);
emitInst(Encoding); emitInst(Encoding);
...@@ -1205,66 +1215,26 @@ void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, ...@@ -1205,66 +1215,26 @@ void AssemblerARM32::emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16,
void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc, void AssemblerARM32::movw(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) { CondARM32::Cond Cond) {
constexpr const char *MovwName = "movw"; // MOV (immediate) - ARM section A8.8.102, encoding A2:
IValueT Rd = encodeRegister(OpRd, "Rd", MovwName); // movw<c> <Rd>, #<imm16>
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.
verifyCondDefined(Cond, MovwName);
// 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 (encodeOperand(OpSrc, ConstVal) != EncodedAsConstI32)
llvm::report_fatal_error(std::string(MovwName) + ": Constant not i32");
// 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>
// //
// cccc0011101s0000ddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, s=SetFlags=0, // cccc00110000iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
// and iiiiiiiiiiii is a shift-rotated value defining RotatedImm8. // iiiiiiiiiiiiiiii=imm16.
constexpr const char *MovwName = "movw";
constexpr bool IsMovW = true;
emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovwName);
} }
void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc, void AssemblerARM32::movt(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) { CondARM32::Cond Cond) {
// MOVT - ARM section A8.8.102, encoding A2: // MOVT - ARM section A8.8.106, encoding A1:
// movt<c> <Rd>, #<imm16> // movt<c> <Rd>, #<imm16>
// //
// cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and // cccc00110100iiiiddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, and
// iiiiiiiiiiiiiiii=imm16. // iiiiiiiiiiiiiiii=imm16.
constexpr const char *MovtName = "movt"; constexpr const char *MovtName = "movt";
IValueT Rd = encodeRegister(OpRd, "Rd", MovtName);
auto *Src = llvm::dyn_cast<ConstantRelocatable>(OpSrc);
if (!Src)
// TODO(kschimpf) Figure out what else can appear here.
return setNeedsTextFixup();
verifyCondDefined(Cond, MovtName);
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 = false; constexpr bool IsMovW = false;
emitFixup(createMoveFixup(IsMovW, Src)); emitMovwt(Cond, IsMovW, OpRd, OpSrc, MovtName);
constexpr IValueT Imm16 = 0;
const IValueT Encoding = encodeCondition(Cond) << kConditionShift | B25 |
B24 | B22 | ((Imm16 >> 12) << 16) | Rd << kRdShift |
(Imm16 & 0xfff);
emitInst(Encoding);
} }
void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc, void AssemblerARM32::mvn(const Operand *OpRd, const Operand *OpSrc,
......
...@@ -393,11 +393,11 @@ private: ...@@ -393,11 +393,11 @@ private:
// Returns the offset encoded in the branch instruction Inst. // Returns the offset encoded in the branch instruction Inst.
static IOffsetT decodeBranchOffset(IValueT Inst); static IOffsetT decodeBranchOffset(IValueT Inst);
// Implements movw, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii where // Implements movw/movt, generating pattern ccccxxxxxxxsiiiiddddiiiiiiiiiiii
// cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and // where cccc=Cond, xxxxxxx<<21=Opcode, dddd=Rd, s=SetFlags, and
// iiiiiiiiiiiiiiii=Imm16. // iiiiiiiiiiiiiiii=Imm16.
void emitMovw(IValueT Opcode, IValueT Rd, IValueT Imm16, bool SetFlags, void emitMovwt(CondARM32::Cond Cond, bool IsMovw, const Operand *OpRd,
CondARM32::Cond Cond); const Operand *OpSrc, const char *MovName);
}; };
} // end of namespace ARM32 } // end of namespace ARM32
......
; Show that we handle constants in a movw, when it isn't represented as ; Show that we handle constants in movw and mvt, when it isn't represented as
; ConstantRelocatable (see mov-imm.ll for the ConstantRelocatable case). ; ConstantRelocatable (see mov-imm.ll for the ConstantRelocatable case).
; REQUIRES: allow_dump ; REQUIRES: allow_dump
...@@ -120,3 +120,85 @@ entry: ...@@ -120,3 +120,85 @@ entry:
; IASM-NEXT: .byte 0xe1 ; IASM-NEXT: .byte 0xe1
} }
define internal void @saveMinus1(i32 %loc) {
; ASM-LABEL:saveMinus1:
; DIS-LABEL:00000030 <saveMinus1>:
; IASM-LABEL:saveMinus1:
entry:
; ASM-NEXT:.LsaveMinus1$entry:
; ASM-NEXT: movw ip, #4088
; DIS-NEXT: 30: e300cff8
; IASM-NEXT:.LsaveMinus1$entry:
; ASM-NEXT: sub sp, sp, ip
; DIS-NEXT: 34: e04dd00c
; IASM-NEXT: .byte 0xf8
; IASM-NEXT: .byte 0xcf
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe3
; ASM-NEXT: str r0, [sp, #4084]
; ASM-NEXT: # [sp, #4084] = def.pseudo
; DIS-NEXT: 38: e58d0ff4
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe0
%loc.asptr = inttoptr i32 %loc to i32*
store i32 -1, i32* %loc.asptr, align 1
; ASM-NEXT: ldr r0, [sp, #4084]
; DIS-NEXT: 3c: e59d0ff4
; IASM-NEXT: .byte 0xf4
; IASM-NEXT: .byte 0xf
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: movw r1, #65535
; DIS-NEXT: 40: e30f1fff
; IASM-NEXT: .byte 0xf4
; IASM-NEXT: .byte 0xf
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: movt r1, #65535
; DIS-NEXT: 44: e34f1fff
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x1f
; IASM-NEXT: .byte 0xf
; IASM-NEXT: .byte 0xe3
; ASM-NEXT: str r1, [r0]
; DIS-NEXT: 48: e5801000
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x1f
; IASM-NEXT: .byte 0x4f
; IASM-NEXT: .byte 0xe3
ret void
; ASM-NEXT: movw ip, #4088
; DIS-NEXT: 4c: e300cff8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x80
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: add sp, sp, ip
; DIS-NEXT: 50: e08dd00c
; IASM-NEXT: .byte 0xf8
; IASM-NEXT: .byte 0xcf
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xe3
; ASM-NEXT: bx lr
; DIS-NEXT: 54: e12fff1e
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe0
}
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