diff options
| author | 2016-08-04 16:46:17 +0000 | |
|---|---|---|
| committer | 2016-08-04 16:46:17 +0000 | |
| commit | 1a2e5e67bc6fd9df4154f0add1d1163af6aa9bf2 (patch) | |
| tree | ace009be8b3d29fa54dff3c833aa4c2f67e6ba2f /compiler/utils/arm/assembler_thumb2.cc | |
| parent | e250cb82e55e47009fdddbebaec9c3f09b36a41b (diff) | |
| parent | 3a656e183ab3131d4a0e1fa79acc79e8da762508 (diff) | |
Merge "Thumb2: Clean up 16-bit LDR/STR detection."
Diffstat (limited to 'compiler/utils/arm/assembler_thumb2.cc')
| -rw-r--r-- | compiler/utils/arm/assembler_thumb2.cc | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc index 353c729249..4be7aae243 100644 --- a/compiler/utils/arm/assembler_thumb2.cc +++ b/compiler/utils/arm/assembler_thumb2.cc @@ -2325,7 +2325,7 @@ void Thumb2Assembler::EmitLoadStore(Condition cond, } Register rn = ad.GetRegister(); - if (IsHighRegister(rn) && rn != SP && rn != PC) { + if (IsHighRegister(rn) && (byte || half || (rn != SP && rn != PC))) { must_be_32bit = true; } @@ -2337,24 +2337,24 @@ void Thumb2Assembler::EmitLoadStore(Condition cond, // Immediate offset int32_t offset = ad.GetOffset(); - // The 16 bit SP relative instruction can only have a 10 bit offset. - if (rn == SP && offset >= (1 << 10)) { - must_be_32bit = true; - } - if (byte) { // 5 bit offset, no shift. - if (offset >= (1 << 5)) { + if ((offset & ~0x1f) != 0) { must_be_32bit = true; } } else if (half) { - // 6 bit offset, shifted by 1. - if (offset >= (1 << 6)) { + // 5 bit offset, shifted by 1. + if ((offset & ~(0x1f << 1)) != 0) { + must_be_32bit = true; + } + } else if (rn == SP || rn == PC) { + // The 16 bit SP/PC relative instruction can only have an (imm8 << 2) offset. + if ((offset & ~(0xff << 2)) != 0) { must_be_32bit = true; } } else { - // 7 bit offset, shifted by 2. - if (offset >= (1 << 7)) { + // 5 bit offset, shifted by 2. + if ((offset & ~(0x1f << 2)) != 0) { must_be_32bit = true; } } @@ -2370,7 +2370,7 @@ void Thumb2Assembler::EmitLoadStore(Condition cond, } else { // 16 bit thumb1. uint8_t opA = 0; - bool sp_relative = false; + bool sp_or_pc_relative = false; if (byte) { opA = 7U /* 0b0111 */; @@ -2379,7 +2379,10 @@ void Thumb2Assembler::EmitLoadStore(Condition cond, } else { if (rn == SP) { opA = 9U /* 0b1001 */; - sp_relative = true; + sp_or_pc_relative = true; + } else if (rn == PC) { + opA = 4U; + sp_or_pc_relative = true; } else { opA = 6U /* 0b0110 */; } @@ -2388,7 +2391,7 @@ void Thumb2Assembler::EmitLoadStore(Condition cond, (load ? B11 : 0); CHECK_GE(offset, 0); - if (sp_relative) { + if (sp_or_pc_relative) { // SP relative, 10 bit offset. CHECK_LT(offset, (1 << 10)); CHECK_ALIGNED(offset, 4); |