ARM: Use stm/ldm for live registers save/restore in SlowPathCode.

In case when there is more than 4 register to save/restore in the
SlowPathCode stm/ldm can save some code size.

Test: m test-art-target; m test-art-host

Change-Id: I2d5b44bab58b67207105302cd7d8ee3300b9040a
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index f5ccf40..2269ba2 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -3372,6 +3372,30 @@
   ldm(IA_W, SP, regs, cond);
 }
 
+void Thumb2Assembler::StoreList(RegList regs, size_t stack_offset) {
+  DCHECK_NE(regs, 0u);
+  DCHECK_EQ(regs & (1u << IP), 0u);
+  if (IsPowerOfTwo(regs)) {
+    Register reg = static_cast<Register>(CTZ(static_cast<uint32_t>(regs)));
+    str(reg, Address(SP, stack_offset));
+  } else {
+    add(IP, SP, ShifterOperand(stack_offset));
+    stm(IA, IP, regs);
+  }
+}
+
+void Thumb2Assembler::LoadList(RegList regs, size_t stack_offset) {
+  DCHECK_NE(regs, 0u);
+  DCHECK_EQ(regs & (1u << IP), 0u);
+  if (IsPowerOfTwo(regs)) {
+    Register reg = static_cast<Register>(CTZ(static_cast<uint32_t>(regs)));
+    ldr(reg, Address(SP, stack_offset));
+  } else {
+    Register lowest_reg = static_cast<Register>(CTZ(static_cast<uint32_t>(regs)));
+    add(lowest_reg, SP, ShifterOperand(stack_offset));
+    ldm(IA, lowest_reg, regs);
+  }
+}
 
 void Thumb2Assembler::Mov(Register rd, Register rm, Condition cond) {
   if (cond != AL || rd != rm) {