blob: ef0cc72a5cb9106e51e21d1f153f3da559be60eb [file] [log] [blame]
buzbee67bf8852011-08-17 17:51:35 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
buzbee1bc37c62012-11-20 13:35:41 -080017#include "arm_lir.h"
buzbee02031b12012-11-23 09:41:35 -080018#include "codegen_arm.h"
Ian Rogers8d3a1172013-06-04 01:13:28 -070019#include "compiler/dex/quick/mir_to_lir-inl.h"
buzbee1bc37c62012-11-20 13:35:41 -080020
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080021namespace art {
22
buzbeeb046e162012-10-30 15:48:42 -070023/* This file contains codegen for the Thumb ISA. */
buzbee67bf8852011-08-17 17:51:35 -070024
buzbeeaad94382012-11-21 07:40:50 -080025static int EncodeImmSingle(int value)
buzbee67bf8852011-08-17 17:51:35 -070026{
Bill Buzbeea114add2012-05-03 15:00:40 -070027 int res;
buzbeefa57c472012-11-21 12:06:18 -080028 int bit_a = (value & 0x80000000) >> 31;
29 int not_bit_b = (value & 0x40000000) >> 30;
30 int bit_b = (value & 0x20000000) >> 29;
31 int b_smear = (value & 0x3e000000) >> 25;
Bill Buzbeea114add2012-05-03 15:00:40 -070032 int slice = (value & 0x01f80000) >> 19;
33 int zeroes = (value & 0x0007ffff);
34 if (zeroes != 0)
35 return -1;
buzbeefa57c472012-11-21 12:06:18 -080036 if (bit_b) {
37 if ((not_bit_b != 0) || (b_smear != 0x1f))
Bill Buzbeea114add2012-05-03 15:00:40 -070038 return -1;
39 } else {
buzbeefa57c472012-11-21 12:06:18 -080040 if ((not_bit_b != 1) || (b_smear != 0x0))
Bill Buzbeea114add2012-05-03 15:00:40 -070041 return -1;
42 }
buzbeefa57c472012-11-21 12:06:18 -080043 res = (bit_a << 7) | (bit_b << 6) | slice;
Bill Buzbeea114add2012-05-03 15:00:40 -070044 return res;
buzbee67bf8852011-08-17 17:51:35 -070045}
46
buzbee4ef3e452012-12-14 13:35:28 -080047/*
48 * Determine whether value can be encoded as a Thumb2 floating point
49 * immediate. If not, return -1. If so return encoded 8-bit value.
50 */
51static int EncodeImmDouble(int64_t value)
52{
53 int res;
54 int bit_a = (value & 0x8000000000000000ll) >> 63;
55 int not_bit_b = (value & 0x4000000000000000ll) >> 62;
56 int bit_b = (value & 0x2000000000000000ll) >> 61;
57 int b_smear = (value & 0x3fc0000000000000ll) >> 54;
58 int slice = (value & 0x003f000000000000ll) >> 48;
59 uint64_t zeroes = (value & 0x0000ffffffffffffll);
60 if (zeroes != 0)
61 return -1;
62 if (bit_b) {
63 if ((not_bit_b != 0) || (b_smear != 0xff))
64 return -1;
65 } else {
66 if ((not_bit_b != 1) || (b_smear != 0x0))
67 return -1;
68 }
69 res = (bit_a << 7) | (bit_b << 6) | slice;
70 return res;
71}
72
buzbee1fd33462013-03-25 13:40:45 -070073LIR* ArmMir2Lir::LoadFPConstantValue(int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -070074{
buzbeefa57c472012-11-21 12:06:18 -080075 DCHECK(ARM_SINGLEREG(r_dest));
buzbee7da142f2012-11-29 16:33:42 -080076 if (value == 0) {
77 // TODO: we need better info about the target CPU. a vector exclusive or
78 // would probably be better here if we could rely on its existance.
79 // Load an immediate +2.0 (which encodes to 0)
buzbee1fd33462013-03-25 13:40:45 -070080 NewLIR2(kThumb2Vmovs_IMM8, r_dest, 0);
buzbee7da142f2012-11-29 16:33:42 -080081 // +0.0 = +2.0 - +2.0
buzbee1fd33462013-03-25 13:40:45 -070082 return NewLIR3(kThumb2Vsubs, r_dest, r_dest, r_dest);
buzbee7da142f2012-11-29 16:33:42 -080083 } else {
84 int encoded_imm = EncodeImmSingle(value);
85 if (encoded_imm >= 0) {
buzbee1fd33462013-03-25 13:40:45 -070086 return NewLIR2(kThumb2Vmovs_IMM8, r_dest, encoded_imm);
buzbee7da142f2012-11-29 16:33:42 -080087 }
Bill Buzbeea114add2012-05-03 15:00:40 -070088 }
buzbee1fd33462013-03-25 13:40:45 -070089 LIR* data_target = ScanLiteralPool(literal_list_, value, 0);
buzbeefa57c472012-11-21 12:06:18 -080090 if (data_target == NULL) {
buzbee1fd33462013-03-25 13:40:45 -070091 data_target = AddWordData(&literal_list_, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070092 }
buzbee1fd33462013-03-25 13:40:45 -070093 LIR* load_pc_rel = RawLIR(current_dalvik_offset_, kThumb2Vldrs,
buzbeefa57c472012-11-21 12:06:18 -080094 r_dest, r15pc, 0, 0, 0, data_target);
buzbee1fd33462013-03-25 13:40:45 -070095 SetMemRefType(load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -080096 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
buzbee1fd33462013-03-25 13:40:45 -070097 AppendLIR(load_pc_rel);
buzbeefa57c472012-11-21 12:06:18 -080098 return load_pc_rel;
buzbee67bf8852011-08-17 17:51:35 -070099}
100
buzbeeaad94382012-11-21 07:40:50 -0800101static int LeadingZeros(uint32_t val)
buzbee67bf8852011-08-17 17:51:35 -0700102{
buzbeeeaf09bc2012-11-15 14:51:41 -0800103 uint32_t alt;
Bill Buzbeea114add2012-05-03 15:00:40 -0700104 int n;
105 int count;
buzbee67bf8852011-08-17 17:51:35 -0700106
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 count = 16;
108 n = 32;
109 do {
110 alt = val >> count;
111 if (alt != 0) {
112 n = n - count;
113 val = alt;
114 }
115 count >>= 1;
116 } while (count);
117 return n - val;
buzbee67bf8852011-08-17 17:51:35 -0700118}
119
120/*
121 * Determine whether value can be encoded as a Thumb2 modified
122 * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
123 */
buzbee1fd33462013-03-25 13:40:45 -0700124int ArmMir2Lir::ModifiedImmediate(uint32_t value)
buzbee67bf8852011-08-17 17:51:35 -0700125{
buzbeefa57c472012-11-21 12:06:18 -0800126 int z_leading;
127 int z_trailing;
buzbeeeaf09bc2012-11-15 14:51:41 -0800128 uint32_t b0 = value & 0xff;
buzbee67bf8852011-08-17 17:51:35 -0700129
130 /* Note: case of value==0 must use 0:000:0:0000000 encoding */
131 if (value <= 0xFF)
Bill Buzbeea114add2012-05-03 15:00:40 -0700132 return b0; // 0:000:a:bcdefgh
buzbee67bf8852011-08-17 17:51:35 -0700133 if (value == ((b0 << 16) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700134 return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700135 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700136 return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700137 b0 = (value >> 8) & 0xff;
138 if (value == ((b0 << 24) | (b0 << 8)))
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700140 /* Can we do it with rotation? */
buzbeefa57c472012-11-21 12:06:18 -0800141 z_leading = LeadingZeros(value);
142 z_trailing = 32 - LeadingZeros(~value & (value - 1));
buzbee67bf8852011-08-17 17:51:35 -0700143 /* A run of eight or fewer active bits? */
buzbeefa57c472012-11-21 12:06:18 -0800144 if ((z_leading + z_trailing) < 24)
Bill Buzbeea114add2012-05-03 15:00:40 -0700145 return -1; /* No - bail */
buzbee67bf8852011-08-17 17:51:35 -0700146 /* left-justify the constant, discarding msb (known to be 1) */
buzbeefa57c472012-11-21 12:06:18 -0800147 value <<= z_leading + 1;
buzbee67bf8852011-08-17 17:51:35 -0700148 /* Create bcdefgh */
149 value >>= 25;
150 /* Put it all together */
buzbeefa57c472012-11-21 12:06:18 -0800151 return value | ((0x8 + z_leading) << 7); /* [01000..11111]:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700152}
153
buzbee1fd33462013-03-25 13:40:45 -0700154bool ArmMir2Lir::InexpensiveConstantInt(int32_t value)
buzbeee6285f92012-12-06 15:57:46 -0800155{
buzbee4ef3e452012-12-14 13:35:28 -0800156 return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
157}
158
buzbee1fd33462013-03-25 13:40:45 -0700159bool ArmMir2Lir::InexpensiveConstantFloat(int32_t value)
buzbee4ef3e452012-12-14 13:35:28 -0800160{
161 return EncodeImmSingle(value) >= 0;
162}
163
buzbee1fd33462013-03-25 13:40:45 -0700164bool ArmMir2Lir::InexpensiveConstantLong(int64_t value)
buzbee4ef3e452012-12-14 13:35:28 -0800165{
166 return InexpensiveConstantInt(High32Bits(value)) && InexpensiveConstantInt(Low32Bits(value));
167}
168
buzbee1fd33462013-03-25 13:40:45 -0700169bool ArmMir2Lir::InexpensiveConstantDouble(int64_t value)
buzbee4ef3e452012-12-14 13:35:28 -0800170{
171 return EncodeImmDouble(value) >= 0;
buzbeee6285f92012-12-06 15:57:46 -0800172}
173
buzbee67bf8852011-08-17 17:51:35 -0700174/*
175 * Load a immediate using a shortcut if possible; otherwise
176 * grab from the per-translation literal pool.
177 *
178 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -0800179 * 1) r_dest is freshly returned from AllocTemp or
buzbee67bf8852011-08-17 17:51:35 -0700180 * 2) The codegen is under fixed register usage
181 */
buzbee1fd33462013-03-25 13:40:45 -0700182LIR* ArmMir2Lir::LoadConstantNoClobber(int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700183{
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800185 int mod_imm;
buzbee67bf8852011-08-17 17:51:35 -0700186
buzbeefa57c472012-11-21 12:06:18 -0800187 if (ARM_FPREG(r_dest)) {
buzbee1fd33462013-03-25 13:40:45 -0700188 return LoadFPConstantValue(r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700189 }
buzbee67bf8852011-08-17 17:51:35 -0700190
Bill Buzbeea114add2012-05-03 15:00:40 -0700191 /* See if the value can be constructed cheaply */
buzbeefa57c472012-11-21 12:06:18 -0800192 if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) {
buzbee1fd33462013-03-25 13:40:45 -0700193 return NewLIR2(kThumbMovImm, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700194 }
195 /* Check Modified immediate special cases */
buzbeefa57c472012-11-21 12:06:18 -0800196 mod_imm = ModifiedImmediate(value);
197 if (mod_imm >= 0) {
buzbee1fd33462013-03-25 13:40:45 -0700198 res = NewLIR2(kThumb2MovImmShift, r_dest, mod_imm);
buzbee67bf8852011-08-17 17:51:35 -0700199 return res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700200 }
buzbeefa57c472012-11-21 12:06:18 -0800201 mod_imm = ModifiedImmediate(~value);
202 if (mod_imm >= 0) {
buzbee1fd33462013-03-25 13:40:45 -0700203 res = NewLIR2(kThumb2MvnImm12, r_dest, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700204 return res;
205 }
206 /* 16-bit immediate? */
207 if ((value & 0xffff) == value) {
buzbee1fd33462013-03-25 13:40:45 -0700208 res = NewLIR2(kThumb2MovImm16, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700209 return res;
210 }
buzbee4ef3e452012-12-14 13:35:28 -0800211 /* Do a low/high pair */
buzbee1fd33462013-03-25 13:40:45 -0700212 res = NewLIR2(kThumb2MovImm16, r_dest, Low16Bits(value));
213 NewLIR2(kThumb2MovImm16H, r_dest, High16Bits(value));
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 return res;
buzbee67bf8852011-08-17 17:51:35 -0700215}
216
buzbee1fd33462013-03-25 13:40:45 -0700217LIR* ArmMir2Lir::OpUnconditionalBranch(LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700218{
buzbee1fd33462013-03-25 13:40:45 -0700219 LIR* res = NewLIR1(kThumbBUncond, 0 /* offset to be patched during assembly*/);
buzbee02031b12012-11-23 09:41:35 -0800220 res->target = target;
221 return res;
buzbee67bf8852011-08-17 17:51:35 -0700222}
223
buzbee1fd33462013-03-25 13:40:45 -0700224LIR* ArmMir2Lir::OpCondBranch(ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700225{
buzbee1fd33462013-03-25 13:40:45 -0700226 LIR* branch = NewLIR2(kThumb2BCond, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -0800227 ArmConditionEncoding(cc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 branch->target = target;
229 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700230}
231
buzbee1fd33462013-03-25 13:40:45 -0700232LIR* ArmMir2Lir::OpReg(OpKind op, int r_dest_src)
buzbee67bf8852011-08-17 17:51:35 -0700233{
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 ArmOpcode opcode = kThumbBkpt;
235 switch (op) {
236 case kOpBlx:
237 opcode = kThumbBlxR;
238 break;
239 default:
buzbeecbd6d442012-11-17 14:11:25 -0800240 LOG(FATAL) << "Bad opcode " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 }
buzbee1fd33462013-03-25 13:40:45 -0700242 return NewLIR1(opcode, r_dest_src);
buzbee67bf8852011-08-17 17:51:35 -0700243}
244
buzbee1fd33462013-03-25 13:40:45 -0700245LIR* ArmMir2Lir::OpRegRegShift(OpKind op, int r_dest_src1, int r_src2,
buzbee02031b12012-11-23 09:41:35 -0800246 int shift)
buzbee67bf8852011-08-17 17:51:35 -0700247{
buzbeefa57c472012-11-21 12:06:18 -0800248 bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2));
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 ArmOpcode opcode = kThumbBkpt;
250 switch (op) {
251 case kOpAdc:
buzbeefa57c472012-11-21 12:06:18 -0800252 opcode = (thumb_form) ? kThumbAdcRR : kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 break;
254 case kOpAnd:
buzbeefa57c472012-11-21 12:06:18 -0800255 opcode = (thumb_form) ? kThumbAndRR : kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 break;
257 case kOpBic:
buzbeefa57c472012-11-21 12:06:18 -0800258 opcode = (thumb_form) ? kThumbBicRR : kThumb2BicRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700259 break;
260 case kOpCmn:
261 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800262 opcode = (thumb_form) ? kThumbCmnRR : kThumb2CmnRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700263 break;
264 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800265 if (thumb_form)
Bill Buzbeea114add2012-05-03 15:00:40 -0700266 opcode = kThumbCmpRR;
buzbeefa57c472012-11-21 12:06:18 -0800267 else if ((shift == 0) && !ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 opcode = kThumbCmpHH;
buzbeefa57c472012-11-21 12:06:18 -0800269 else if ((shift == 0) && ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 opcode = kThumbCmpLH;
271 else if (shift == 0)
272 opcode = kThumbCmpHL;
273 else
274 opcode = kThumb2CmpRR;
275 break;
276 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800277 opcode = (thumb_form) ? kThumbEorRR : kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700278 break;
279 case kOpMov:
280 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800281 if (ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 opcode = kThumbMovRR;
buzbeefa57c472012-11-21 12:06:18 -0800283 else if (!ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 opcode = kThumbMovRR_H2H;
buzbeefa57c472012-11-21 12:06:18 -0800285 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 opcode = kThumbMovRR_H2L;
287 else
288 opcode = kThumbMovRR_L2H;
289 break;
290 case kOpMul:
291 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800292 opcode = (thumb_form) ? kThumbMul : kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 break;
294 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800295 opcode = (thumb_form) ? kThumbMvn : kThumb2MnvRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700296 break;
297 case kOpNeg:
298 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800299 opcode = (thumb_form) ? kThumbNeg : kThumb2NegRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700300 break;
301 case kOpOr:
buzbeefa57c472012-11-21 12:06:18 -0800302 opcode = (thumb_form) ? kThumbOrr : kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 break;
304 case kOpSbc:
buzbeefa57c472012-11-21 12:06:18 -0800305 opcode = (thumb_form) ? kThumbSbc : kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 break;
307 case kOpTst:
buzbeefa57c472012-11-21 12:06:18 -0800308 opcode = (thumb_form) ? kThumbTst : kThumb2TstRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700309 break;
310 case kOpLsl:
311 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800312 opcode = (thumb_form) ? kThumbLslRR : kThumb2LslRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 break;
314 case kOpLsr:
315 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800316 opcode = (thumb_form) ? kThumbLsrRR : kThumb2LsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 break;
318 case kOpAsr:
319 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800320 opcode = (thumb_form) ? kThumbAsrRR : kThumb2AsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 break;
322 case kOpRor:
323 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800324 opcode = (thumb_form) ? kThumbRorRR : kThumb2RorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700325 break;
326 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800327 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700328 break;
329 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800330 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 break;
332 case kOp2Byte:
333 DCHECK_EQ(shift, 0);
buzbee1fd33462013-03-25 13:40:45 -0700334 return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 8);
Bill Buzbeea114add2012-05-03 15:00:40 -0700335 case kOp2Short:
336 DCHECK_EQ(shift, 0);
buzbee1fd33462013-03-25 13:40:45 -0700337 return NewLIR4(kThumb2Sbfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700338 case kOp2Char:
339 DCHECK_EQ(shift, 0);
buzbee1fd33462013-03-25 13:40:45 -0700340 return NewLIR4(kThumb2Ubfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700341 default:
buzbeecbd6d442012-11-17 14:11:25 -0800342 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700343 break;
344 }
345 DCHECK_GE(static_cast<int>(opcode), 0);
346 if (EncodingMap[opcode].flags & IS_BINARY_OP)
buzbee1fd33462013-03-25 13:40:45 -0700347 return NewLIR2(opcode, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700348 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
buzbeefa57c472012-11-21 12:06:18 -0800349 if (EncodingMap[opcode].field_loc[2].kind == kFmtShift)
buzbee1fd33462013-03-25 13:40:45 -0700350 return NewLIR3(opcode, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700351 else
buzbee1fd33462013-03-25 13:40:45 -0700352 return NewLIR3(opcode, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700353 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbee1fd33462013-03-25 13:40:45 -0700354 return NewLIR4(opcode, r_dest_src1, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700355 else {
356 LOG(FATAL) << "Unexpected encoding operand count";
357 return NULL;
358 }
buzbee67bf8852011-08-17 17:51:35 -0700359}
360
buzbee1fd33462013-03-25 13:40:45 -0700361LIR* ArmMir2Lir::OpRegReg(OpKind op, int r_dest_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700362{
buzbee1fd33462013-03-25 13:40:45 -0700363 return OpRegRegShift(op, r_dest_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700364}
365
buzbee1fd33462013-03-25 13:40:45 -0700366LIR* ArmMir2Lir::OpRegRegRegShift(OpKind op, int r_dest, int r_src1,
buzbee02031b12012-11-23 09:41:35 -0800367 int r_src2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700368{
Bill Buzbeea114add2012-05-03 15:00:40 -0700369 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800370 bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1) &&
371 ARM_LOWREG(r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700372 switch (op) {
373 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800374 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700375 break;
376 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800377 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700378 break;
379 case kOpRsub:
380 opcode = kThumb2RsubRRR;
381 break;
382 case kOpAdc:
383 opcode = kThumb2AdcRRR;
384 break;
385 case kOpAnd:
386 opcode = kThumb2AndRRR;
387 break;
388 case kOpBic:
389 opcode = kThumb2BicRRR;
390 break;
391 case kOpXor:
392 opcode = kThumb2EorRRR;
393 break;
394 case kOpMul:
395 DCHECK_EQ(shift, 0);
396 opcode = kThumb2MulRRR;
397 break;
398 case kOpOr:
399 opcode = kThumb2OrrRRR;
400 break;
401 case kOpSbc:
402 opcode = kThumb2SbcRRR;
403 break;
404 case kOpLsl:
405 DCHECK_EQ(shift, 0);
406 opcode = kThumb2LslRRR;
407 break;
408 case kOpLsr:
409 DCHECK_EQ(shift, 0);
410 opcode = kThumb2LsrRRR;
411 break;
412 case kOpAsr:
413 DCHECK_EQ(shift, 0);
414 opcode = kThumb2AsrRRR;
415 break;
416 case kOpRor:
417 DCHECK_EQ(shift, 0);
418 opcode = kThumb2RorRRR;
419 break;
420 default:
buzbeecbd6d442012-11-17 14:11:25 -0800421 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700422 break;
423 }
424 DCHECK_GE(static_cast<int>(opcode), 0);
425 if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbee1fd33462013-03-25 13:40:45 -0700426 return NewLIR4(opcode, r_dest, r_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 else {
428 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
buzbee1fd33462013-03-25 13:40:45 -0700429 return NewLIR3(opcode, r_dest, r_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700430 }
buzbee67bf8852011-08-17 17:51:35 -0700431}
432
buzbee1fd33462013-03-25 13:40:45 -0700433LIR* ArmMir2Lir::OpRegRegReg(OpKind op, int r_dest, int r_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700434{
buzbee1fd33462013-03-25 13:40:45 -0700435 return OpRegRegRegShift(op, r_dest, r_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700436}
437
buzbee1fd33462013-03-25 13:40:45 -0700438LIR* ArmMir2Lir::OpRegRegImm(OpKind op, int r_dest, int r_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700439{
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 LIR* res;
441 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800442 int abs_value = (neg) ? -value : value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700443 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800444 ArmOpcode alt_opcode = kThumbBkpt;
445 bool all_low_regs = (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1));
446 int mod_imm = ModifiedImmediate(value);
447 int mod_imm_neg = ModifiedImmediate(-value);
buzbee67bf8852011-08-17 17:51:35 -0700448
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 switch (op) {
450 case kOpLsl:
buzbeefa57c472012-11-21 12:06:18 -0800451 if (all_low_regs)
buzbee1fd33462013-03-25 13:40:45 -0700452 return NewLIR3(kThumbLslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 else
buzbee1fd33462013-03-25 13:40:45 -0700454 return NewLIR3(kThumb2LslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 case kOpLsr:
buzbeefa57c472012-11-21 12:06:18 -0800456 if (all_low_regs)
buzbee1fd33462013-03-25 13:40:45 -0700457 return NewLIR3(kThumbLsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 else
buzbee1fd33462013-03-25 13:40:45 -0700459 return NewLIR3(kThumb2LsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 case kOpAsr:
buzbeefa57c472012-11-21 12:06:18 -0800461 if (all_low_regs)
buzbee1fd33462013-03-25 13:40:45 -0700462 return NewLIR3(kThumbAsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700463 else
buzbee1fd33462013-03-25 13:40:45 -0700464 return NewLIR3(kThumb2AsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700465 case kOpRor:
buzbee1fd33462013-03-25 13:40:45 -0700466 return NewLIR3(kThumb2RorRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800468 if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700469 (value <= 1020) && ((value & 0x3)==0)) {
buzbee1fd33462013-03-25 13:40:45 -0700470 return NewLIR3(kThumbAddSpRel, r_dest, r_src1, value >> 2);
buzbeefa57c472012-11-21 12:06:18 -0800471 } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700472 (value <= 1020) && ((value & 0x3)==0)) {
buzbee1fd33462013-03-25 13:40:45 -0700473 return NewLIR3(kThumbAddPcRel, r_dest, r_src1, value >> 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700474 }
475 // Note: intentional fallthrough
476 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800477 if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700478 if (op == kOpAdd)
479 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
buzbee67bf8852011-08-17 17:51:35 -0700480 else
Bill Buzbeea114add2012-05-03 15:00:40 -0700481 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
buzbee1fd33462013-03-25 13:40:45 -0700482 return NewLIR3(opcode, r_dest, r_src1, abs_value);
buzbeefa57c472012-11-21 12:06:18 -0800483 } else if ((abs_value & 0xff) == abs_value) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 if (op == kOpAdd)
485 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
486 else
487 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
buzbee1fd33462013-03-25 13:40:45 -0700488 return NewLIR3(opcode, r_dest, r_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700489 }
buzbeefa57c472012-11-21 12:06:18 -0800490 if (mod_imm_neg >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 op = (op == kOpAdd) ? kOpSub : kOpAdd;
buzbeefa57c472012-11-21 12:06:18 -0800492 mod_imm = mod_imm_neg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700493 }
494 if (op == kOpSub) {
495 opcode = kThumb2SubRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800496 alt_opcode = kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 } else {
498 opcode = kThumb2AddRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800499 alt_opcode = kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 }
501 break;
buzbeec7d1f912013-02-07 15:22:39 -0800502 case kOpRsub:
503 opcode = kThumb2RsubRRI8;
504 alt_opcode = kThumb2RsubRRR;
505 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 case kOpAdc:
507 opcode = kThumb2AdcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800508 alt_opcode = kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700509 break;
510 case kOpSbc:
511 opcode = kThumb2SbcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800512 alt_opcode = kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 break;
514 case kOpOr:
515 opcode = kThumb2OrrRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800516 alt_opcode = kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 break;
518 case kOpAnd:
519 opcode = kThumb2AndRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800520 alt_opcode = kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700521 break;
522 case kOpXor:
523 opcode = kThumb2EorRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800524 alt_opcode = kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 break;
526 case kOpMul:
527 //TUNING: power of 2, shift & add
buzbeefa57c472012-11-21 12:06:18 -0800528 mod_imm = -1;
529 alt_opcode = kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700530 break;
531 case kOpCmp: {
buzbeefa57c472012-11-21 12:06:18 -0800532 int mod_imm = ModifiedImmediate(value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800534 if (mod_imm >= 0) {
buzbee1fd33462013-03-25 13:40:45 -0700535 res = NewLIR2(kThumb2CmpRI12, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700536 } else {
buzbee1fd33462013-03-25 13:40:45 -0700537 int r_tmp = AllocTemp();
538 res = LoadConstant(r_tmp, value);
539 OpRegReg(kOpCmp, r_src1, r_tmp);
540 FreeTemp(r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 }
542 return res;
buzbee67bf8852011-08-17 17:51:35 -0700543 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700544 default:
buzbeecbd6d442012-11-17 14:11:25 -0800545 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700546 }
547
buzbeefa57c472012-11-21 12:06:18 -0800548 if (mod_imm >= 0) {
buzbee1fd33462013-03-25 13:40:45 -0700549 return NewLIR3(opcode, r_dest, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 } else {
buzbee1fd33462013-03-25 13:40:45 -0700551 int r_scratch = AllocTemp();
552 LoadConstant(r_scratch, value);
buzbeefa57c472012-11-21 12:06:18 -0800553 if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
buzbee1fd33462013-03-25 13:40:45 -0700554 res = NewLIR4(alt_opcode, r_dest, r_src1, r_scratch, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 else
buzbee1fd33462013-03-25 13:40:45 -0700556 res = NewLIR3(alt_opcode, r_dest, r_src1, r_scratch);
557 FreeTemp(r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700558 return res;
559 }
buzbee67bf8852011-08-17 17:51:35 -0700560}
561
buzbee52a77fc2012-11-20 19:50:46 -0800562/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
buzbee1fd33462013-03-25 13:40:45 -0700563LIR* ArmMir2Lir::OpRegImm(OpKind op, int r_dest_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700564{
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800566 int abs_value = (neg) ? -value : value;
567 bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700568 ArmOpcode opcode = kThumbBkpt;
569 switch (op) {
570 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800571 if ( !neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 DCHECK_EQ((value & 0x3), 0);
buzbee1fd33462013-03-25 13:40:45 -0700573 return NewLIR1(kThumbAddSpI7, value >> 2);
buzbeefa57c472012-11-21 12:06:18 -0800574 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
576 }
577 break;
578 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800579 if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 DCHECK_EQ((value & 0x3), 0);
buzbee1fd33462013-03-25 13:40:45 -0700581 return NewLIR1(kThumbSubSpI7, value >> 2);
buzbeefa57c472012-11-21 12:06:18 -0800582 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700583 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
584 }
585 break;
586 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800587 if (ARM_LOWREG(r_dest_src1) && short_form)
588 opcode = (short_form) ? kThumbCmpRI8 : kThumbCmpRR;
589 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 opcode = kThumbCmpRR;
591 else {
buzbeefa57c472012-11-21 12:06:18 -0800592 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700593 opcode = kThumbCmpHL;
594 }
595 break;
596 default:
buzbee52a77fc2012-11-20 19:50:46 -0800597 /* Punt to OpRegRegImm - if bad case catch it there */
buzbeefa57c472012-11-21 12:06:18 -0800598 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700599 break;
600 }
buzbeefa57c472012-11-21 12:06:18 -0800601 if (short_form)
buzbee1fd33462013-03-25 13:40:45 -0700602 return NewLIR2(opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 else {
buzbee1fd33462013-03-25 13:40:45 -0700604 return OpRegRegImm(op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700605 }
buzbee67bf8852011-08-17 17:51:35 -0700606}
607
buzbee1fd33462013-03-25 13:40:45 -0700608LIR* ArmMir2Lir::LoadConstantWide(int r_dest_lo, int r_dest_hi, int64_t value)
buzbee67bf8852011-08-17 17:51:35 -0700609{
buzbee4ef3e452012-12-14 13:35:28 -0800610 LIR* res = NULL;
611 int32_t val_lo = Low32Bits(value);
612 int32_t val_hi = High32Bits(value);
buzbee7da142f2012-11-29 16:33:42 -0800613 int target_reg = S2d(r_dest_lo, r_dest_hi);
buzbeefa57c472012-11-21 12:06:18 -0800614 if (ARM_FPREG(r_dest_lo)) {
buzbee7da142f2012-11-29 16:33:42 -0800615 if ((val_lo == 0) && (val_hi == 0)) {
616 // TODO: we need better info about the target CPU. a vector exclusive or
617 // would probably be better here if we could rely on its existance.
618 // Load an immediate +2.0 (which encodes to 0)
buzbee1fd33462013-03-25 13:40:45 -0700619 NewLIR2(kThumb2Vmovd_IMM8, target_reg, 0);
buzbee7da142f2012-11-29 16:33:42 -0800620 // +0.0 = +2.0 - +2.0
buzbee1fd33462013-03-25 13:40:45 -0700621 res = NewLIR3(kThumb2Vsubd, target_reg, target_reg, target_reg);
buzbee67bf8852011-08-17 17:51:35 -0700622 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800623 int encoded_imm = EncodeImmDouble(value);
buzbee7da142f2012-11-29 16:33:42 -0800624 if (encoded_imm >= 0) {
buzbee1fd33462013-03-25 13:40:45 -0700625 res = NewLIR2(kThumb2Vmovd_IMM8, target_reg, encoded_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700626 }
buzbee67bf8852011-08-17 17:51:35 -0700627 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700628 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800629 if ((InexpensiveConstantInt(val_lo) && (InexpensiveConstantInt(val_hi)))) {
buzbee1fd33462013-03-25 13:40:45 -0700630 res = LoadConstantNoClobber(r_dest_lo, val_lo);
631 LoadConstantNoClobber(r_dest_hi, val_hi);
buzbee4ef3e452012-12-14 13:35:28 -0800632 }
633 }
634 if (res == NULL) {
635 // No short form - load from the literal pool.
buzbee1fd33462013-03-25 13:40:45 -0700636 LIR* data_target = ScanLiteralPoolWide(literal_list_, val_lo, val_hi);
buzbee4ef3e452012-12-14 13:35:28 -0800637 if (data_target == NULL) {
buzbee1fd33462013-03-25 13:40:45 -0700638 data_target = AddWideData(&literal_list_, val_lo, val_hi);
buzbee4ef3e452012-12-14 13:35:28 -0800639 }
640 if (ARM_FPREG(r_dest_lo)) {
buzbee1fd33462013-03-25 13:40:45 -0700641 res = RawLIR(current_dalvik_offset_, kThumb2Vldrd,
buzbee4ef3e452012-12-14 13:35:28 -0800642 target_reg, r15pc, 0, 0, 0, data_target);
643 } else {
buzbee1fd33462013-03-25 13:40:45 -0700644 res = RawLIR(current_dalvik_offset_, kThumb2LdrdPcRel8,
buzbee4ef3e452012-12-14 13:35:28 -0800645 r_dest_lo, r_dest_hi, r15pc, 0, 0, data_target);
646 }
buzbee1fd33462013-03-25 13:40:45 -0700647 SetMemRefType(res, true, kLiteral);
buzbee4ef3e452012-12-14 13:35:28 -0800648 res->alias_info = reinterpret_cast<uintptr_t>(data_target);
buzbee1fd33462013-03-25 13:40:45 -0700649 AppendLIR(res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700650 }
651 return res;
buzbee67bf8852011-08-17 17:51:35 -0700652}
653
buzbee1fd33462013-03-25 13:40:45 -0700654int ArmMir2Lir::EncodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700656}
657
buzbee1fd33462013-03-25 13:40:45 -0700658LIR* ArmMir2Lir::LoadBaseIndexed(int rBase, int r_index, int r_dest,
buzbee02031b12012-11-23 09:41:35 -0800659 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700660{
buzbeefa57c472012-11-21 12:06:18 -0800661 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 LIR* load;
663 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800664 bool thumb_form = (all_low_regs && (scale == 0));
665 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700666
buzbeefa57c472012-11-21 12:06:18 -0800667 if (ARM_FPREG(r_dest)) {
668 if (ARM_SINGLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700669 DCHECK((size == kWord) || (size == kSingle));
670 opcode = kThumb2Vldrs;
671 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700672 } else {
buzbeefa57c472012-11-21 12:06:18 -0800673 DCHECK(ARM_DOUBLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800675 DCHECK_EQ((r_dest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700676 opcode = kThumb2Vldrd;
677 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700678 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700679 } else {
680 if (size == kSingle)
681 size = kWord;
682 }
buzbee67bf8852011-08-17 17:51:35 -0700683
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 switch (size) {
685 case kDouble: // fall-through
686 case kSingle:
buzbee1fd33462013-03-25 13:40:45 -0700687 reg_ptr = AllocTemp();
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 if (scale) {
buzbee1fd33462013-03-25 13:40:45 -0700689 NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800690 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700691 } else {
buzbee1fd33462013-03-25 13:40:45 -0700692 OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700693 }
buzbee1fd33462013-03-25 13:40:45 -0700694 load = NewLIR3(opcode, r_dest, reg_ptr, 0);
695 FreeTemp(reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 return load;
697 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800698 opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 break;
700 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800701 opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700702 break;
703 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800704 opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700705 break;
706 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800707 opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700708 break;
709 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800710 opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700711 break;
712 default:
buzbeecbd6d442012-11-17 14:11:25 -0800713 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700714 }
buzbeefa57c472012-11-21 12:06:18 -0800715 if (thumb_form)
buzbee1fd33462013-03-25 13:40:45 -0700716 load = NewLIR3(opcode, r_dest, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700717 else
buzbee1fd33462013-03-25 13:40:45 -0700718 load = NewLIR4(opcode, r_dest, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700719
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 return load;
buzbee67bf8852011-08-17 17:51:35 -0700721}
722
buzbee1fd33462013-03-25 13:40:45 -0700723LIR* ArmMir2Lir::StoreBaseIndexed(int rBase, int r_index, int r_src,
buzbee02031b12012-11-23 09:41:35 -0800724 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700725{
buzbeefa57c472012-11-21 12:06:18 -0800726 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
buzbee4ef3e452012-12-14 13:35:28 -0800727 LIR* store = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700728 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800729 bool thumb_form = (all_low_regs && (scale == 0));
730 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700731
buzbeefa57c472012-11-21 12:06:18 -0800732 if (ARM_FPREG(r_src)) {
733 if (ARM_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700734 DCHECK((size == kWord) || (size == kSingle));
735 opcode = kThumb2Vstrs;
736 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700737 } else {
buzbeefa57c472012-11-21 12:06:18 -0800738 DCHECK(ARM_DOUBLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700739 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800740 DCHECK_EQ((r_src & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700741 opcode = kThumb2Vstrd;
742 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700743 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700744 } else {
745 if (size == kSingle)
746 size = kWord;
747 }
buzbee67bf8852011-08-17 17:51:35 -0700748
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 switch (size) {
750 case kDouble: // fall-through
751 case kSingle:
buzbee1fd33462013-03-25 13:40:45 -0700752 reg_ptr = AllocTemp();
Bill Buzbeea114add2012-05-03 15:00:40 -0700753 if (scale) {
buzbee1fd33462013-03-25 13:40:45 -0700754 NewLIR4(kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800755 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700756 } else {
buzbee1fd33462013-03-25 13:40:45 -0700757 OpRegRegReg(kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700758 }
buzbee1fd33462013-03-25 13:40:45 -0700759 store = NewLIR3(opcode, r_src, reg_ptr, 0);
760 FreeTemp(reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 return store;
762 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800763 opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700764 break;
765 case kUnsignedHalf:
766 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800767 opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700768 break;
769 case kUnsignedByte:
770 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800771 opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700772 break;
773 default:
buzbeecbd6d442012-11-17 14:11:25 -0800774 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 }
buzbeefa57c472012-11-21 12:06:18 -0800776 if (thumb_form)
buzbee1fd33462013-03-25 13:40:45 -0700777 store = NewLIR3(opcode, r_src, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700778 else
buzbee1fd33462013-03-25 13:40:45 -0700779 store = NewLIR4(opcode, r_src, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700780
Bill Buzbeea114add2012-05-03 15:00:40 -0700781 return store;
buzbee67bf8852011-08-17 17:51:35 -0700782}
783
784/*
785 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800786 * on base (which must have an associated s_reg and MIR). If not
buzbee67bf8852011-08-17 17:51:35 -0700787 * performing null check, incoming MIR can be null.
788 */
buzbee1fd33462013-03-25 13:40:45 -0700789LIR* ArmMir2Lir::LoadBaseDispBody(int rBase, int displacement, int r_dest,
buzbee02031b12012-11-23 09:41:35 -0800790 int r_dest_hi, OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700791{
buzbee4ef3e452012-12-14 13:35:28 -0800792 LIR* load = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700793 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800794 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700795 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800796 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
797 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700798 bool is64bit = false;
buzbee4ef3e452012-12-14 13:35:28 -0800799 bool already_generated = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700800 switch (size) {
801 case kDouble:
802 case kLong:
803 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800804 if (ARM_FPREG(r_dest)) {
805 if (ARM_SINGLEREG(r_dest)) {
806 DCHECK(ARM_FPREG(r_dest_hi));
buzbee1fd33462013-03-25 13:40:45 -0700807 r_dest = S2d(r_dest, r_dest_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 }
809 opcode = kThumb2Vldrd;
810 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800811 short_form = true;
812 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 }
814 break;
815 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800816 if (displacement <= 1020) {
buzbee1fd33462013-03-25 13:40:45 -0700817 load = NewLIR4(kThumb2LdrdI8, r_dest, r_dest_hi, rBase, displacement >> 2);
buzbee4ef3e452012-12-14 13:35:28 -0800818 } else {
buzbee1fd33462013-03-25 13:40:45 -0700819 load = LoadBaseDispBody(rBase, displacement, r_dest,
buzbee4ef3e452012-12-14 13:35:28 -0800820 -1, kWord, s_reg);
buzbee1fd33462013-03-25 13:40:45 -0700821 LoadBaseDispBody(rBase, displacement + 4, r_dest_hi,
buzbee4ef3e452012-12-14 13:35:28 -0800822 -1, kWord, INVALID_SREG);
823 }
824 already_generated = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700825 }
826 case kSingle:
827 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800828 if (ARM_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700829 opcode = kThumb2Vldrs;
830 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800831 short_form = true;
832 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700833 }
834 break;
835 }
buzbeefa57c472012-11-21 12:06:18 -0800836 if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800838 short_form = true;
839 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 opcode = kThumbLdrPcRel;
buzbeefa57c472012-11-21 12:06:18 -0800841 } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800843 short_form = true;
844 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700845 opcode = kThumbLdrSpRel;
buzbeefa57c472012-11-21 12:06:18 -0800846 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700847 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800848 short_form = true;
849 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700850 opcode = kThumbLdrRRI5;
851 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800852 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700853 opcode = kThumb2LdrRRI12;
854 }
855 break;
856 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800857 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700858 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800859 short_form = true;
860 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700861 opcode = kThumbLdrhRRI5;
862 } else if (displacement < 4092 && displacement >= 0) {
buzbeefa57c472012-11-21 12:06:18 -0800863 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700864 opcode = kThumb2LdrhRRI12;
865 }
866 break;
867 case kSignedHalf:
868 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800869 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700870 opcode = kThumb2LdrshRRI12;
871 }
872 break;
873 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800874 if (all_low_regs && displacement < 32 && displacement >= 0) {
875 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700876 opcode = kThumbLdrbRRI5;
877 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800878 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700879 opcode = kThumb2LdrbRRI12;
880 }
881 break;
882 case kSignedByte:
883 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800884 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700885 opcode = kThumb2LdrsbRRI12;
886 }
887 break;
888 default:
buzbeecbd6d442012-11-17 14:11:25 -0800889 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700890 }
buzbee67bf8852011-08-17 17:51:35 -0700891
buzbee4ef3e452012-12-14 13:35:28 -0800892 if (!already_generated) {
893 if (short_form) {
buzbee1fd33462013-03-25 13:40:45 -0700894 load = NewLIR3(opcode, r_dest, rBase, encoded_disp);
buzbee4ef3e452012-12-14 13:35:28 -0800895 } else {
buzbee1fd33462013-03-25 13:40:45 -0700896 int reg_offset = AllocTemp();
897 LoadConstant(reg_offset, encoded_disp);
898 load = LoadBaseIndexed(rBase, reg_offset, r_dest, 0, size);
899 FreeTemp(reg_offset);
buzbee4ef3e452012-12-14 13:35:28 -0800900 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700901 }
buzbee67bf8852011-08-17 17:51:35 -0700902
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800904 if (rBase == rARM_SP) {
buzbee1fd33462013-03-25 13:40:45 -0700905 AnnotateDalvikRegAccess(load, displacement >> 2, true /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 }
907 return load;
buzbee67bf8852011-08-17 17:51:35 -0700908}
909
buzbee1fd33462013-03-25 13:40:45 -0700910LIR* ArmMir2Lir::LoadBaseDisp(int rBase, int displacement, int r_dest,
buzbee02031b12012-11-23 09:41:35 -0800911 OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700912{
buzbee1fd33462013-03-25 13:40:45 -0700913 return LoadBaseDispBody(rBase, displacement, r_dest, -1, size, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700914}
915
buzbee1fd33462013-03-25 13:40:45 -0700916LIR* ArmMir2Lir::LoadBaseDispWide(int rBase, int displacement, int r_dest_lo,
buzbee02031b12012-11-23 09:41:35 -0800917 int r_dest_hi, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700918{
buzbee1fd33462013-03-25 13:40:45 -0700919 return LoadBaseDispBody(rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700920}
921
922
buzbee1fd33462013-03-25 13:40:45 -0700923LIR* ArmMir2Lir::StoreBaseDispBody(int rBase, int displacement,
buzbee02031b12012-11-23 09:41:35 -0800924 int r_src, int r_src_hi, OpSize size) {
buzbee4ef3e452012-12-14 13:35:28 -0800925 LIR* store = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800927 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700928 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800929 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
930 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700931 bool is64bit = false;
buzbee4ef3e452012-12-14 13:35:28 -0800932 bool already_generated = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 switch (size) {
934 case kLong:
935 case kDouble:
936 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800937 if (!ARM_FPREG(r_src)) {
buzbee4ef3e452012-12-14 13:35:28 -0800938 if (displacement <= 1020) {
buzbee1fd33462013-03-25 13:40:45 -0700939 store = NewLIR4(kThumb2StrdI8, r_src, r_src_hi, rBase, displacement >> 2);
buzbee4ef3e452012-12-14 13:35:28 -0800940 } else {
buzbee1fd33462013-03-25 13:40:45 -0700941 store = StoreBaseDispBody(rBase, displacement, r_src, -1, kWord);
942 StoreBaseDispBody(rBase, displacement + 4, r_src_hi, -1, kWord);
buzbee4ef3e452012-12-14 13:35:28 -0800943 }
944 already_generated = true;
945 } else {
946 if (ARM_SINGLEREG(r_src)) {
947 DCHECK(ARM_FPREG(r_src_hi));
buzbee1fd33462013-03-25 13:40:45 -0700948 r_src = S2d(r_src, r_src_hi);
buzbee4ef3e452012-12-14 13:35:28 -0800949 }
950 opcode = kThumb2Vstrd;
951 if (displacement <= 1020) {
952 short_form = true;
953 encoded_disp >>= 2;
954 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700955 }
956 break;
957 case kSingle:
958 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800959 if (ARM_FPREG(r_src)) {
960 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700961 opcode = kThumb2Vstrs;
962 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800963 short_form = true;
964 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700965 }
Sebastien Hertza188cd42013-03-28 17:23:23 +0100966 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700967 }
Sebastien Hertza188cd42013-03-28 17:23:23 +0100968 if (ARM_LOWREG(r_src) && (rBase == r13sp) &&
969 (displacement <= 1020) && (displacement >= 0)) {
970 short_form = true;
971 encoded_disp >>= 2;
972 opcode = kThumbStrSpRel;
973 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700974 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800975 short_form = true;
976 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 opcode = kThumbStrRRI5;
978 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800979 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 opcode = kThumb2StrRRI12;
981 }
982 break;
983 case kUnsignedHalf:
984 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800985 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800987 short_form = true;
988 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700989 opcode = kThumbStrhRRI5;
990 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800991 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 opcode = kThumb2StrhRRI12;
993 }
994 break;
995 case kUnsignedByte:
996 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800997 if (all_low_regs && displacement < 32 && displacement >= 0) {
998 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700999 opcode = kThumbStrbRRI5;
1000 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -08001001 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 opcode = kThumb2StrbRRI12;
1003 }
1004 break;
1005 default:
buzbeecbd6d442012-11-17 14:11:25 -08001006 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -07001007 }
buzbee4ef3e452012-12-14 13:35:28 -08001008 if (!already_generated) {
1009 if (short_form) {
buzbee1fd33462013-03-25 13:40:45 -07001010 store = NewLIR3(opcode, r_src, rBase, encoded_disp);
buzbee4ef3e452012-12-14 13:35:28 -08001011 } else {
buzbee1fd33462013-03-25 13:40:45 -07001012 int r_scratch = AllocTemp();
1013 LoadConstant(r_scratch, encoded_disp);
1014 store = StoreBaseIndexed(rBase, r_scratch, r_src, 0, size);
1015 FreeTemp(r_scratch);
buzbee4ef3e452012-12-14 13:35:28 -08001016 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001017 }
buzbee67bf8852011-08-17 17:51:35 -07001018
Bill Buzbeea114add2012-05-03 15:00:40 -07001019 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -08001020 if (rBase == rARM_SP) {
buzbee1fd33462013-03-25 13:40:45 -07001021 AnnotateDalvikRegAccess(store, displacement >> 2, false /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -07001022 }
buzbee4ef3e452012-12-14 13:35:28 -08001023 return store;
buzbee67bf8852011-08-17 17:51:35 -07001024}
1025
buzbee1fd33462013-03-25 13:40:45 -07001026LIR* ArmMir2Lir::StoreBaseDisp(int rBase, int displacement, int r_src,
buzbee02031b12012-11-23 09:41:35 -08001027 OpSize size)
buzbee67bf8852011-08-17 17:51:35 -07001028{
buzbee1fd33462013-03-25 13:40:45 -07001029 return StoreBaseDispBody(rBase, displacement, r_src, -1, size);
buzbee67bf8852011-08-17 17:51:35 -07001030}
1031
buzbee1fd33462013-03-25 13:40:45 -07001032LIR* ArmMir2Lir::StoreBaseDispWide(int rBase, int displacement,
buzbee02031b12012-11-23 09:41:35 -08001033 int r_src_lo, int r_src_hi)
buzbee67bf8852011-08-17 17:51:35 -07001034{
buzbee1fd33462013-03-25 13:40:45 -07001035 return StoreBaseDispBody(rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbee67bf8852011-08-17 17:51:35 -07001036}
1037
buzbee1fd33462013-03-25 13:40:45 -07001038LIR* ArmMir2Lir::OpFpRegCopy(int r_dest, int r_src)
buzbee67bf8852011-08-17 17:51:35 -07001039{
Bill Buzbeea114add2012-05-03 15:00:40 -07001040 int opcode;
buzbeefa57c472012-11-21 12:06:18 -08001041 DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
1042 if (ARM_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001043 opcode = kThumb2Vmovd;
1044 } else {
buzbeefa57c472012-11-21 12:06:18 -08001045 if (ARM_SINGLEREG(r_dest)) {
1046 opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001047 } else {
buzbeefa57c472012-11-21 12:06:18 -08001048 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001050 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001051 }
buzbee1fd33462013-03-25 13:40:45 -07001052 LIR* res = RawLIR(current_dalvik_offset_, opcode, r_dest, r_src);
1053 if (!(cu_->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
buzbeefa57c472012-11-21 12:06:18 -08001054 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001055 }
1056 return res;
buzbee67bf8852011-08-17 17:51:35 -07001057}
1058
buzbee1fd33462013-03-25 13:40:45 -07001059LIR* ArmMir2Lir::OpThreadMem(OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -07001060{
buzbee52a77fc2012-11-20 19:50:46 -08001061 LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001062 return NULL;
1063}
buzbee67bf8852011-08-17 17:51:35 -07001064
buzbee1fd33462013-03-25 13:40:45 -07001065LIR* ArmMir2Lir::OpMem(OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -07001066{
buzbee52a77fc2012-11-20 19:50:46 -08001067 LOG(FATAL) << "Unexpected use of OpMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001068 return NULL;
1069}
1070
buzbee1fd33462013-03-25 13:40:45 -07001071LIR* ArmMir2Lir::StoreBaseIndexedDisp(int rBase, int r_index, int scale,
buzbee02031b12012-11-23 09:41:35 -08001072 int displacement, int r_src, int r_src_hi, OpSize size,
1073 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001074{
buzbee52a77fc2012-11-20 19:50:46 -08001075 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001076 return NULL;
1077}
1078
buzbee1fd33462013-03-25 13:40:45 -07001079LIR* ArmMir2Lir::OpRegMem(OpKind op, int r_dest, int rBase, int offset)
buzbeeb046e162012-10-30 15:48:42 -07001080{
buzbee52a77fc2012-11-20 19:50:46 -08001081 LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001082 return NULL;
1083}
1084
buzbee1fd33462013-03-25 13:40:45 -07001085LIR* ArmMir2Lir::LoadBaseIndexedDisp(int rBase, int r_index, int scale,
buzbee02031b12012-11-23 09:41:35 -08001086 int displacement, int r_dest, int r_dest_hi, OpSize size,
1087 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001088{
buzbee52a77fc2012-11-20 19:50:46 -08001089 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001090 return NULL;
1091}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001092
1093} // namespace art