Commit e078db8e by Karl Schimpf

Fix vldrs/vstrs handling of immediate offsets in ARM.

A previous patch fixed vldrd/vstrd by dividing the immediate offset of the instruction by 4 before encoding. This does the same for vldrs/vstrs. It fixes the remaining problems with compiling spec2k using -filetype=iasm. It also fixes a minor bug in the divsion by 4, in the case that the immediate value is negative. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=jpp@chromium.org Review URL: https://codereview.chromium.org/1617993005 .
parent 94cc3e61
...@@ -356,14 +356,14 @@ EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value, ...@@ -356,14 +356,14 @@ EncodedOperand encodeOperand(const Operand *Opnd, IValueT &Value,
} }
IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset, IValueT encodeImmRegOffset(IValueT Reg, IOffsetT Offset,
OperandARM32Mem::AddrMode Mode) { OperandARM32Mem::AddrMode Mode,
IValueT OffsetShift = 0) {
IValueT Value = Mode | (Reg << kRnShift); IValueT Value = Mode | (Reg << kRnShift);
if (Offset < 0) { if (Offset < 0) {
Value = (Value ^ U) | -Offset; // Flip U to adjust sign. Offset = -Offset;
} else { Value ^= U; // Flip U to adjust sign.
Value |= Offset;
} }
return Value; return Value | (Offset >> OffsetShift);
} }
// Encodes immediate register offset using encoding 3. // Encodes immediate register offset using encoding 3.
...@@ -384,9 +384,11 @@ IValueT encodeImmRegOffset(OpEncoding AddressEncoding, IValueT Reg, ...@@ -384,9 +384,11 @@ 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: case ImmRegOffsetDiv4: {
assert((Offset & 0x3) == 0); assert((Offset & 0x3) == 0);
return encodeImmRegOffset(Reg, Offset >> 2, Mode); constexpr IValueT RightShift2 = 2;
return encodeImmRegOffset(Reg, Offset, Mode, RightShift2);
}
case OpEncoding3: case OpEncoding3:
return encodeImmRegOffsetEnc3(Reg, Offset, Mode); return encodeImmRegOffsetEnc3(Reg, Offset, Mode);
case OpEncodingMemEx: case OpEncodingMemEx:
...@@ -608,7 +610,6 @@ IValueT AssemblerARM32::encodeBranchOffset(IOffsetT Offset, IValueT Inst) { ...@@ -608,7 +610,6 @@ IValueT AssemblerARM32::encodeBranchOffset(IOffsetT Offset, IValueT Inst) {
bool IsGoodOffset = canEncodeBranchOffset(Offset); bool IsGoodOffset = canEncodeBranchOffset(Offset);
assert(IsGoodOffset); assert(IsGoodOffset);
// Note: Following cast is for MINIMAL build.
(void)IsGoodOffset; (void)IsGoodOffset;
// Properly preserve only the bits supported in the instruction. // Properly preserve only the bits supported in the instruction.
...@@ -2242,9 +2243,8 @@ void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress, ...@@ -2242,9 +2243,8 @@ void AssemblerARM32::vldrd(const Operand *OpDd, const Operand *OpAddress,
IValueT Address; IValueT Address;
EncodedOperand AddressEncoding = EncodedOperand AddressEncoding =
encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4);
if (AddressEncoding != EncodedAsImmRegOffset) (void)AddressEncoding;
// TODO(kschimpf) Fix this. assert(AddressEncoding == EncodedAsImmRegOffset);
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) |
...@@ -2264,7 +2264,8 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, ...@@ -2264,7 +2264,8 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress,
IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs); IValueT Sd = encodeSRegister(OpSd, "Sd", Vldrs);
assert(CondARM32::isDefined(Cond)); assert(CondARM32::isDefined(Cond));
IValueT Address; IValueT Address;
EncodedOperand AddressEncoding = encodeAddress(OpAddress, Address, TInfo); EncodedOperand AddressEncoding =
encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4);
(void)AddressEncoding; (void)AddressEncoding;
assert(AddressEncoding == EncodedAsImmRegOffset); assert(AddressEncoding == EncodedAsImmRegOffset);
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
...@@ -2318,9 +2319,8 @@ void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress, ...@@ -2318,9 +2319,8 @@ void AssemblerARM32::vstrd(const Operand *OpDd, const Operand *OpAddress,
IValueT Address; IValueT Address;
IValueT AddressEncoding = IValueT AddressEncoding =
encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4); encodeAddress(OpAddress, Address, TInfo, ImmRegOffsetDiv4);
if (AddressEncoding != EncodedAsImmRegOffset) (void)AddressEncoding;
// TODO(kschimpf) Fix this. assert(AddressEncoding == EncodedAsImmRegOffset);
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) |
...@@ -2340,8 +2340,10 @@ void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress, ...@@ -2340,8 +2340,10 @@ void AssemblerARM32::vstrs(const Operand *OpSd, const Operand *OpAddress,
IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs); IValueT Sd = encodeSRegister(OpSd, "Sd", Vstrs);
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);
(void)AddressEncoding;
assert(AddressEncoding == EncodedAsImmRegOffset);
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = IValueT Encoding =
B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) | B27 | B26 | B24 | B11 | B9 | (encodeCondition(Cond) << kConditionShift) |
......
; Test vldrd and vstrd when address is offset with an immediate. ; Test vldr{s,d} and vstr{s,d} when address is offset with an immediate.
; REQUIRES: allow_dump ; REQUIRES: allow_dump
...@@ -24,23 +24,45 @@ ...@@ -24,23 +24,45 @@
; RUN: -reg-use d20 \ ; RUN: -reg-use d20 \
; RUN: | FileCheck %s --check-prefix=DIS ; RUN: | FileCheck %s --check-prefix=DIS
define internal i64 @testVldrStrImm(double %d) { define internal i32 @testFloatImm(float %f) {
; ASM-LABEL: testVldrStrImm: ; ASM-LABEL: testFloatImm:
; DIS-LABEL: 00000000 <testVldrStrImm>: ; DIS-LABEL: 00000000 <testFloatImm>:
; IASM-LABEL: testVldrStrImm: ; IASM-LABEL: testFloatImm:
entry: entry:
; ASM-NEXT: .LtestVldrStrImm$entry: ; ASM: .LtestFloatImm$entry:
; IASM-NEXT: .LtestVldrStrImm$entry: ; IASM: .LtestFloatImm$entry:
; ASM: vstr s0, [sp, #4]
; DIS: 4: ed8d0a01
; IASM-NOT: vstr
%v = bitcast float %f to i32
; ASM: vldr s0, [sp, #4]
; DIS: 8: ed9d0a01
; IASM-NOT: vldr
ret i32 %v
}
define internal i64 @testDoubleImm(double %d) {
; ASM-LABEL: testDoubleImm:
; DIS-LABEL: 00000020 <testDoubleImm>:
; IASM-LABEL: testDoubleImm:
entry:
; ASM: .LtestDoubleImm$entry:
; IASM: .LtestDoubleImm$entry:
; ASM: vstr d0, [sp, #8] ; ASM: vstr d0, [sp, #8]
; DIS: 4: ed8d0b02 ; DIS: 24: ed8d0b02
; IASM-NOT: vstr ; IASM-NOT: vstr
%v = bitcast double %d to i64 %v = bitcast double %d to i64
; ASM: vldr d20, [sp, #8] ; ASM: vldr d20, [sp, #8]
; DIS: 8: eddd4b02 ; DIS: 28: eddd4b02
; IASM-NOT: vldr ; IASM-NOT: vldr
ret i64 %v 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