Commit 08f79107 by Karl Schimpf

Fix vldrd/vstrd handling of immediate offsets in ARM.

Fixes the ARM integrated assembler by dividing the immediate offset of the instruction by 4 before encoding. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1619703008 .
parent ac2388c3
...@@ -180,6 +180,9 @@ RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) { ...@@ -180,6 +180,9 @@ RegARM32::GPRRegister getGPRReg(IValueT Shift, IValueT Value) {
enum OpEncoding { enum OpEncoding {
// No alternate layout specified. // No alternate layout specified.
DefaultOpEncoding, DefaultOpEncoding,
// Alternate encoding for ImmRegOffset, where the offset is divided by 4
// before encoding.
ImmRegOffsetDiv4,
// Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and // Alternate encoding 3 for memory operands (like in strb, strh, ldrb, and
// ldrh. // ldrh.
OpEncoding3, OpEncoding3,
...@@ -381,6 +384,9 @@ IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, ...@@ -381,6 +384,9 @@ IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg,
switch (AddressEncoding) { switch (AddressEncoding) {
case DefaultOpEncoding: case DefaultOpEncoding:
return encodeImmRegOffset(Reg, Offset, Mode); return encodeImmRegOffset(Reg, Offset, Mode);
case ImmRegOffsetDiv4:
assert((Offset & 0x3) == 0);
return encodeImmRegOffset(Reg, Offset >> 2, Mode);
case OpEncoding3: case OpEncoding3:
return encodeImmRegOffsetEnc3(Reg, Offset, Mode); return encodeImmRegOffsetEnc3(Reg, Offset, Mode);
case OpEncodingMemEx: case OpEncodingMemEx:
...@@ -2214,14 +2220,16 @@ void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress, ...@@ -2214,14 +2220,16 @@ void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress,
// vldr<c> <Dd>, [<Rn>{, #+/-<imm>}] // vldr<c> <Dd>, [<Rn>{, #+/-<imm>}]
// //
// cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, // cccc1101UD01nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
// iiiiiiii=abs(Opcode), and U=1 if Opcode>=0, // iiiiiiii=abs(Imm >> 2), and U=1 if Opcode>=0.
constexpr const char *Vldrd = "vldrd"; constexpr const char *Vldrd = "vldrd";
IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd); IValueT Dd = encodeDRegister(OpDd, "Dd", Vldrd);
assert(CondARM32::isDefined(Cond)); assert(CondARM32::isDefined(Cond));
IValueT Address; IValueT Address;
EncodedOperand AddressEncoding = encodeAddress(OpAddress, Address, TInfo); EncodedOperand AddressEncoding =
(void)AddressEncoding; encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4);
assert(AddressEncoding == EncodedAsImmRegOffset); if (AddressEncoding != EncodedAsImmRegOffset)
// TODO(kschimpf) Fix this.
return setNeedsTextFixup();
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 | IValueT Encoding = B27 | B26 | B24 | B20 | B11 | B9 | B8 |
(encodeCondition(Cond) << kConditionShift) | (encodeCondition(Cond) << kConditionShift) |
...@@ -2285,16 +2293,19 @@ void AssemblerARM32::vmuld(const Operand *OpDd, const Operand *OpDn, ...@@ -2285,16 +2293,19 @@ void AssemblerARM32::vmuld(const Operand *OpDd, const Operand *OpDn,
void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress, void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress,
CondARM32::Cond Cond, const TargetInfo &TInfo) { CondARM32::Cond Cond, const TargetInfo &TInfo) {
// VSTR - ARM section A8.8.413, encoding A1: // VSTR - ARM section A8.8.413, encoding A1:
// vstr<c> <Dd>, [<Rn>{, #+/-<imm>}] // vstr<c> <Dd>, [<Rn>{, #+/-<Imm>}]
// //
// cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd, // cccc1101UD00nnnndddd1011iiiiiiii where cccc=Cond, nnnn=Rn, Ddddd=Rd,
// iiiiiiii=abs(Opcode), and U=1 if Opcode>=0, // iiiiiiii=abs(Imm >> 2), and U=1 if Imm>=0.
constexpr const char *Vstrd = "vstrd"; constexpr const char *Vstrd = "vstrd";
IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd); IValueT Dd = encodeDRegister(OpDd, "Dd", Vstrd);
assert(CondARM32::isDefined(Cond)); assert(CondARM32::isDefined(Cond));
IValueT Address; IValueT Address;
if (encodeAddress(OpAddress, Address, TInfo) != EncodedAsImmRegOffset) IValueT AddressEncoding =
assert(false); encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4);
if (AddressEncoding != EncodedAsImmRegOffset)
// TODO(kschimpf) Fix this.
return setNeedsTextFixup();
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 | IValueT Encoding = B27 | B26 | B24 | B11 | B9 | B8 |
(encodeCondition(Cond) << kConditionShift) | (encodeCondition(Cond) << kConditionShift) |
......
...@@ -1372,13 +1372,21 @@ template <> void InstARM32Ldr::emit(const Cfg *Func) const { ...@@ -1372,13 +1372,21 @@ template <> void InstARM32Ldr::emit(const Cfg *Func) const {
template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const { template <> void InstARM32Ldr::emitIAS(const Cfg *Func) const {
assert(getSrcSize() == 1); assert(getSrcSize() == 1);
Variable *Dest = getDest(); Variable *Dest = getDest();
Type DestTy = Dest->getType(); const Type DestTy = Dest->getType();
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
if (isScalarFloatingType(DestTy)) { if (isScalarFloatingType(DestTy)) {
if (DestTy == IceType_f32) switch (DestTy) {
default:
// TODO(kschimpf) Does this happen?
Asm->setNeedsTextFixup();
break;
case IceType_f32:
Asm->vldrs(Dest, getSrc(0), getPredicate(), Func->getTarget()); Asm->vldrs(Dest, getSrc(0), getPredicate(), Func->getTarget());
else break;
case IceType_f64:
Asm->vldrd(Dest, getSrc(0), getPredicate(), Func->getTarget()); Asm->vldrd(Dest, getSrc(0), getPredicate(), Func->getTarget());
break;
}
} else if (isVectorType(DestTy)) } else if (isVectorType(DestTy))
// TODO(kschimpf) Handle case. // TODO(kschimpf) Handle case.
Asm->setNeedsTextFixup(); Asm->setNeedsTextFixup();
...@@ -1677,10 +1685,18 @@ void InstARM32Str::emitIAS(const Cfg *Func) const { ...@@ -1677,10 +1685,18 @@ void InstARM32Str::emitIAS(const Cfg *Func) const {
Type Ty = getSrc(0)->getType(); Type Ty = getSrc(0)->getType();
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
if (isScalarFloatingType(Ty)) { if (isScalarFloatingType(Ty)) {
if (Ty == IceType_f32) switch (Ty) {
default:
// TODO(kschimpf) Does this happen?
Asm->setNeedsTextFixup();
break;
case IceType_f32:
Asm->vstrs(getSrc(0), getSrc(1), getPredicate(), Func->getTarget()); Asm->vstrs(getSrc(0), getSrc(1), getPredicate(), Func->getTarget());
else break;
case IceType_f64:
Asm->vstrd(getSrc(0), getSrc(1), getPredicate(), Func->getTarget()); Asm->vstrd(getSrc(0), getSrc(1), getPredicate(), Func->getTarget());
break;
}
} else if (isVectorType(Ty)) } else if (isVectorType(Ty))
// TODO(kschimpf) Handle case. // TODO(kschimpf) Handle case.
Asm->setNeedsTextFixup(); Asm->setNeedsTextFixup();
......
; Test vldrd and vstrd when address is offset with an immediate.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: -reg-use d20 \
; 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 \
; RUN: -reg-use d20 \
; RUN: | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: -reg-use d20 \
; 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 \
; RUN: -reg-use d20 \
; RUN: | FileCheck %s --check-prefix=DIS
define internal i64 @testVldrStrImm(double %d) {
; ASM-LABEL: testVldrStrImm:
; DIS-LABEL: 00000000 <testVldrStrImm>:
; IASM-LABEL: testVldrStrImm:
entry:
; ASM-NEXT: .LtestVldrStrImm$entry:
; IASM-NEXT: .LtestVldrStrImm$entry:
; ASM: vstr d0, [sp, #8]
; DIS: 4: ed8d0b02
; IASM-NOT: vstr
%v = bitcast double %d to i64
; ASM: vldr d20, [sp, #8]
; DIS: 8: eddd4b02
; IASM-NOT: vldr
ret i64 %v
}
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