diff options
author | 2016-07-15 15:01:13 +0100 | |
---|---|---|
committer | 2016-08-11 18:43:23 +0100 | |
commit | cb3cf4a5c4edf0d9796ed08f2f4e1140f53dae4d (patch) | |
tree | 9ffb088c8bcd2ea68c387ba7093f83d7cd97eb65 | |
parent | 33699c9529add1c1ec4bb5dcb0807942709de224 (diff) |
ARM: Add vldm/vstm assembler support.
Change-Id: Id97417de8ebd07fc1fbee5d17e4b1c620a2c44cc
-rw-r--r-- | compiler/utils/arm/assembler_arm.h | 2 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm32.cc | 12 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_arm32.h | 2 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_thumb2.cc | 59 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_thumb2.h | 10 | ||||
-rw-r--r-- | compiler/utils/arm/assembler_thumb2_test.cc | 42 |
6 files changed, 119 insertions, 8 deletions
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h index ff0bbafb9a..86548e153b 100644 --- a/compiler/utils/arm/assembler_arm.h +++ b/compiler/utils/arm/assembler_arm.h @@ -680,6 +680,8 @@ class ArmAssembler : public Assembler { virtual void vpushd(DRegister reg, int nregs, Condition cond = AL) = 0; virtual void vpops(SRegister reg, int nregs, Condition cond = AL) = 0; virtual void vpopd(DRegister reg, int nregs, Condition cond = AL) = 0; + virtual void vldmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) = 0; + virtual void vstmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) = 0; // Branch instructions. virtual void b(Label* label, Condition cond = AL) = 0; diff --git a/compiler/utils/arm/assembler_arm32.cc b/compiler/utils/arm/assembler_arm32.cc index 6f9d5f32af..b8eb60c387 100644 --- a/compiler/utils/arm/assembler_arm32.cc +++ b/compiler/utils/arm/assembler_arm32.cc @@ -1106,6 +1106,18 @@ void Arm32Assembler::vpopd(DRegister reg, int nregs, Condition cond) { } +void Arm32Assembler::vldmiad(Register, DRegister, int, Condition) { + LOG(FATAL) << "Unimplemented."; + UNREACHABLE(); +} + + +void Arm32Assembler::vstmiad(Register, DRegister, int, Condition) { + LOG(FATAL) << "Unimplemented."; + UNREACHABLE(); +} + + void Arm32Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) { CHECK_NE(cond, kNoCondition); CHECK_GT(nregs, 0); diff --git a/compiler/utils/arm/assembler_arm32.h b/compiler/utils/arm/assembler_arm32.h index 044eaa1edf..0cb6b171ce 100644 --- a/compiler/utils/arm/assembler_arm32.h +++ b/compiler/utils/arm/assembler_arm32.h @@ -212,6 +212,8 @@ class Arm32Assembler FINAL : public ArmAssembler { void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE; void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; + void vldmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) OVERRIDE; + void vstmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) OVERRIDE; // Branch instructions. void b(Label* label, Condition cond = AL) OVERRIDE; diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index ee69698ce8..ebdfc98554 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -3020,9 +3020,49 @@ void Thumb2Assembler::vpopd(DRegister reg, int nregs, Condition cond) { } +void Thumb2Assembler::vldmiad(Register base_reg, DRegister reg, int nregs, Condition cond) { + int32_t rest = B23; + EmitVLdmOrStm(rest, + static_cast<uint32_t>(reg), + nregs, + base_reg, + /*is_load*/ true, + /*dbl*/ true, + cond); +} + + +void Thumb2Assembler::vstmiad(Register base_reg, DRegister reg, int nregs, Condition cond) { + int32_t rest = B23; + EmitVLdmOrStm(rest, + static_cast<uint32_t>(reg), + nregs, + base_reg, + /*is_load*/ false, + /*dbl*/ true, + cond); +} + + void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, Condition cond) { + int32_t rest = B21 | (push ? B24 : B23); + EmitVLdmOrStm(rest, reg, nregs, SP, /*is_load*/ !push, dbl, cond); +} + + +void Thumb2Assembler::EmitVLdmOrStm(int32_t rest, + uint32_t reg, + int nregs, + Register rn, + bool is_load, + bool dbl, + Condition cond) { CheckCondition(cond); + DCHECK_GT(nregs, 0); + DCHECK_LE(reg + nregs, 32u); + DCHECK(!dbl || (nregs <= 16)); + uint32_t D; uint32_t Vd; if (dbl) { @@ -3034,14 +3074,17 @@ void Thumb2Assembler::EmitVPushPop(uint32_t reg, int nregs, bool push, bool dbl, D = reg & 1; Vd = (reg >> 1) & 15U /* 0b1111 */; } - int32_t encoding = B27 | B26 | B21 | B19 | B18 | B16 | - B11 | B9 | - (dbl ? B8 : 0) | - (push ? B24 : (B23 | B20)) | - 14U /* 0b1110 */ << 28 | - nregs << (dbl ? 1 : 0) | - D << 22 | - Vd << 12; + + int32_t encoding = rest | + 14U /* 0b1110 */ << 28 | + B27 | B26 | B11 | B9 | + (is_load ? B20 : 0) | + static_cast<int16_t>(rn) << 16 | + D << 22 | + Vd << 12 | + (dbl ? B8 : 0) | + nregs << (dbl ? 1 : 0); + Emit32(encoding); } diff --git a/compiler/utils/arm/assembler_thumb2.h b/compiler/utils/arm/assembler_thumb2.h index 1c1c98b52b..13f3becb6d 100644 --- a/compiler/utils/arm/assembler_thumb2.h +++ b/compiler/utils/arm/assembler_thumb2.h @@ -258,6 +258,8 @@ class Thumb2Assembler FINAL : public ArmAssembler { void vpushd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; void vpops(SRegister reg, int nregs, Condition cond = AL) OVERRIDE; void vpopd(DRegister reg, int nregs, Condition cond = AL) OVERRIDE; + void vldmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) OVERRIDE; + void vstmiad(Register base_reg, DRegister reg, int nregs, Condition cond = AL) OVERRIDE; // Branch instructions. void b(Label* label, Condition cond = AL); @@ -748,6 +750,14 @@ class Thumb2Assembler FINAL : public ArmAssembler { SRegister sn, SRegister sm); + void EmitVLdmOrStm(int32_t rest, + uint32_t reg, + int nregs, + Register rn, + bool is_load, + bool dbl, + Condition cond); + void EmitVFPddd(Condition cond, int32_t opcode, DRegister dd, diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc index 3ca37145d5..d0799d6112 100644 --- a/compiler/utils/arm/assembler_thumb2_test.cc +++ b/compiler/utils/arm/assembler_thumb2_test.cc @@ -1611,4 +1611,46 @@ TEST_F(AssemblerThumb2Test, LoadFromShiftedRegOffset) { DriverStr(expected, "LoadFromShiftedRegOffset"); } +TEST_F(AssemblerThumb2Test, VStmLdmPushPop) { + // Different D register numbers are used here, to test register encoding. + // Source register number is encoded as M:Vm, destination register number is encoded as D:Vd, + // For source and destination registers which use D0..D15, the M bit and D bit should be 0. + // For source and destination registers which use D16..D32, the M bit and D bit should be 1. + // Different data types (signed and unsigned) are also tested. + __ vstmiad(arm::R0, arm::D0, 4); + __ vldmiad(arm::R1, arm::D9, 5); + __ vpopd(arm::D0, 4); + __ vpushd(arm::D9, 5); + __ vpops(arm::S0, 4); + __ vpushs(arm::S9, 5); + __ vpushs(arm::S16, 5); + __ vpushd(arm::D0, 16); + __ vpushd(arm::D1, 15); + __ vpushd(arm::D8, 16); + __ vpushd(arm::D31, 1); + __ vpushs(arm::S0, 32); + __ vpushs(arm::S1, 31); + __ vpushs(arm::S16, 16); + __ vpushs(arm::S31, 1); + + std::string expected = + "vstmia r0, {d0 - d3}\n" + "vldmia r1, {d9 - d13}\n" + "vpop {d0 - d3}\n" + "vpush {d9 - d13}\n" + "vpop {s0 - s3}\n" + "vpush {s9 - s13}\n" + "vpush {s16 - s20}\n" + "vpush {d0 - d15}\n" + "vpush {d1 - d15}\n" + "vpush {d8 - d23}\n" + "vpush {d31}\n" + "vpush {s0 - s31}\n" + "vpush {s1 - s31}\n" + "vpush {s16 - s31}\n" + "vpush {s31}\n"; + + DriverStr(expected, "VStmLdmPushPop"); +} + } // namespace art |