blob: a670199580f4482d8e7a736d4ebb4fba75803402 [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"
Brian Carlstrom641ce032013-01-31 15:21:37 -080019#include "compiler/codegen/codegen_util.h"
20#include "compiler/codegen/ralloc_util.h"
buzbee1bc37c62012-11-20 13:35:41 -080021
Elliott Hughes11d1b0c2012-01-23 16:57:47 -080022namespace art {
23
buzbeeb046e162012-10-30 15:48:42 -070024/* This file contains codegen for the Thumb ISA. */
buzbee67bf8852011-08-17 17:51:35 -070025
buzbeeaad94382012-11-21 07:40:50 -080026static int EncodeImmSingle(int value)
buzbee67bf8852011-08-17 17:51:35 -070027{
Bill Buzbeea114add2012-05-03 15:00:40 -070028 int res;
buzbeefa57c472012-11-21 12:06:18 -080029 int bit_a = (value & 0x80000000) >> 31;
30 int not_bit_b = (value & 0x40000000) >> 30;
31 int bit_b = (value & 0x20000000) >> 29;
32 int b_smear = (value & 0x3e000000) >> 25;
Bill Buzbeea114add2012-05-03 15:00:40 -070033 int slice = (value & 0x01f80000) >> 19;
34 int zeroes = (value & 0x0007ffff);
35 if (zeroes != 0)
36 return -1;
buzbeefa57c472012-11-21 12:06:18 -080037 if (bit_b) {
38 if ((not_bit_b != 0) || (b_smear != 0x1f))
Bill Buzbeea114add2012-05-03 15:00:40 -070039 return -1;
40 } else {
buzbeefa57c472012-11-21 12:06:18 -080041 if ((not_bit_b != 1) || (b_smear != 0x0))
Bill Buzbeea114add2012-05-03 15:00:40 -070042 return -1;
43 }
buzbeefa57c472012-11-21 12:06:18 -080044 res = (bit_a << 7) | (bit_b << 6) | slice;
Bill Buzbeea114add2012-05-03 15:00:40 -070045 return res;
buzbee67bf8852011-08-17 17:51:35 -070046}
47
buzbee4ef3e452012-12-14 13:35:28 -080048/*
49 * Determine whether value can be encoded as a Thumb2 floating point
50 * immediate. If not, return -1. If so return encoded 8-bit value.
51 */
52static int EncodeImmDouble(int64_t value)
53{
54 int res;
55 int bit_a = (value & 0x8000000000000000ll) >> 63;
56 int not_bit_b = (value & 0x4000000000000000ll) >> 62;
57 int bit_b = (value & 0x2000000000000000ll) >> 61;
58 int b_smear = (value & 0x3fc0000000000000ll) >> 54;
59 int slice = (value & 0x003f000000000000ll) >> 48;
60 uint64_t zeroes = (value & 0x0000ffffffffffffll);
61 if (zeroes != 0)
62 return -1;
63 if (bit_b) {
64 if ((not_bit_b != 0) || (b_smear != 0xff))
65 return -1;
66 } else {
67 if ((not_bit_b != 1) || (b_smear != 0x0))
68 return -1;
69 }
70 res = (bit_a << 7) | (bit_b << 6) | slice;
71 return res;
72}
73
buzbeefa57c472012-11-21 12:06:18 -080074static LIR* LoadFPConstantValue(CompilationUnit* cu, int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -070075{
buzbeefa57c472012-11-21 12:06:18 -080076 DCHECK(ARM_SINGLEREG(r_dest));
buzbee7da142f2012-11-29 16:33:42 -080077 if (value == 0) {
78 // TODO: we need better info about the target CPU. a vector exclusive or
79 // would probably be better here if we could rely on its existance.
80 // Load an immediate +2.0 (which encodes to 0)
81 NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, 0);
82 // +0.0 = +2.0 - +2.0
83 return NewLIR3(cu, kThumb2Vsubs, r_dest, r_dest, r_dest);
84 } else {
85 int encoded_imm = EncodeImmSingle(value);
86 if (encoded_imm >= 0) {
87 return NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, encoded_imm);
88 }
Bill Buzbeea114add2012-05-03 15:00:40 -070089 }
buzbeefa57c472012-11-21 12:06:18 -080090 LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0);
91 if (data_target == NULL) {
92 data_target = AddWordData(cu, &cu->literal_list, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070093 }
buzbeefa57c472012-11-21 12:06:18 -080094 LIR* load_pc_rel = RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrs,
95 r_dest, r15pc, 0, 0, 0, data_target);
buzbee02031b12012-11-23 09:41:35 -080096 SetMemRefType(cu, load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -080097 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
98 AppendLIR(cu, load_pc_rel);
99 return load_pc_rel;
buzbee67bf8852011-08-17 17:51:35 -0700100}
101
buzbeeaad94382012-11-21 07:40:50 -0800102static int LeadingZeros(uint32_t val)
buzbee67bf8852011-08-17 17:51:35 -0700103{
buzbeeeaf09bc2012-11-15 14:51:41 -0800104 uint32_t alt;
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 int n;
106 int count;
buzbee67bf8852011-08-17 17:51:35 -0700107
Bill Buzbeea114add2012-05-03 15:00:40 -0700108 count = 16;
109 n = 32;
110 do {
111 alt = val >> count;
112 if (alt != 0) {
113 n = n - count;
114 val = alt;
115 }
116 count >>= 1;
117 } while (count);
118 return n - val;
buzbee67bf8852011-08-17 17:51:35 -0700119}
120
121/*
122 * Determine whether value can be encoded as a Thumb2 modified
123 * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
124 */
buzbee02031b12012-11-23 09:41:35 -0800125int ArmCodegen::ModifiedImmediate(uint32_t value)
buzbee67bf8852011-08-17 17:51:35 -0700126{
buzbeefa57c472012-11-21 12:06:18 -0800127 int z_leading;
128 int z_trailing;
buzbeeeaf09bc2012-11-15 14:51:41 -0800129 uint32_t b0 = value & 0xff;
buzbee67bf8852011-08-17 17:51:35 -0700130
131 /* Note: case of value==0 must use 0:000:0:0000000 encoding */
132 if (value <= 0xFF)
Bill Buzbeea114add2012-05-03 15:00:40 -0700133 return b0; // 0:000:a:bcdefgh
buzbee67bf8852011-08-17 17:51:35 -0700134 if (value == ((b0 << 16) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700136 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700138 b0 = (value >> 8) & 0xff;
139 if (value == ((b0 << 24) | (b0 << 8)))
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700141 /* Can we do it with rotation? */
buzbeefa57c472012-11-21 12:06:18 -0800142 z_leading = LeadingZeros(value);
143 z_trailing = 32 - LeadingZeros(~value & (value - 1));
buzbee67bf8852011-08-17 17:51:35 -0700144 /* A run of eight or fewer active bits? */
buzbeefa57c472012-11-21 12:06:18 -0800145 if ((z_leading + z_trailing) < 24)
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 return -1; /* No - bail */
buzbee67bf8852011-08-17 17:51:35 -0700147 /* left-justify the constant, discarding msb (known to be 1) */
buzbeefa57c472012-11-21 12:06:18 -0800148 value <<= z_leading + 1;
buzbee67bf8852011-08-17 17:51:35 -0700149 /* Create bcdefgh */
150 value >>= 25;
151 /* Put it all together */
buzbeefa57c472012-11-21 12:06:18 -0800152 return value | ((0x8 + z_leading) << 7); /* [01000..11111]:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700153}
154
buzbee4ef3e452012-12-14 13:35:28 -0800155bool ArmCodegen::InexpensiveConstantInt(int32_t value)
buzbeee6285f92012-12-06 15:57:46 -0800156{
buzbee4ef3e452012-12-14 13:35:28 -0800157 return (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
158}
159
160bool ArmCodegen::InexpensiveConstantFloat(int32_t value)
161{
162 return EncodeImmSingle(value) >= 0;
163}
164
165bool ArmCodegen::InexpensiveConstantLong(int64_t value)
166{
167 return InexpensiveConstantInt(High32Bits(value)) && InexpensiveConstantInt(Low32Bits(value));
168}
169
170bool ArmCodegen::InexpensiveConstantDouble(int64_t value)
171{
172 return EncodeImmDouble(value) >= 0;
buzbeee6285f92012-12-06 15:57:46 -0800173}
174
buzbee67bf8852011-08-17 17:51:35 -0700175/*
176 * Load a immediate using a shortcut if possible; otherwise
177 * grab from the per-translation literal pool.
178 *
179 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -0800180 * 1) r_dest is freshly returned from AllocTemp or
buzbee67bf8852011-08-17 17:51:35 -0700181 * 2) The codegen is under fixed register usage
182 */
buzbee02031b12012-11-23 09:41:35 -0800183LIR* ArmCodegen::LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700184{
Bill Buzbeea114add2012-05-03 15:00:40 -0700185 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800186 int mod_imm;
buzbee67bf8852011-08-17 17:51:35 -0700187
buzbeefa57c472012-11-21 12:06:18 -0800188 if (ARM_FPREG(r_dest)) {
189 return LoadFPConstantValue(cu, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 }
buzbee67bf8852011-08-17 17:51:35 -0700191
Bill Buzbeea114add2012-05-03 15:00:40 -0700192 /* See if the value can be constructed cheaply */
buzbeefa57c472012-11-21 12:06:18 -0800193 if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) {
194 return NewLIR2(cu, kThumbMovImm, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700195 }
196 /* Check Modified immediate special cases */
buzbeefa57c472012-11-21 12:06:18 -0800197 mod_imm = ModifiedImmediate(value);
198 if (mod_imm >= 0) {
199 res = NewLIR2(cu, kThumb2MovImmShift, r_dest, mod_imm);
buzbee67bf8852011-08-17 17:51:35 -0700200 return res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700201 }
buzbeefa57c472012-11-21 12:06:18 -0800202 mod_imm = ModifiedImmediate(~value);
203 if (mod_imm >= 0) {
204 res = NewLIR2(cu, kThumb2MvnImm12, r_dest, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 return res;
206 }
207 /* 16-bit immediate? */
208 if ((value & 0xffff) == value) {
buzbeefa57c472012-11-21 12:06:18 -0800209 res = NewLIR2(cu, kThumb2MovImm16, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700210 return res;
211 }
buzbee4ef3e452012-12-14 13:35:28 -0800212 /* Do a low/high pair */
213 res = NewLIR2(cu, kThumb2MovImm16, r_dest, Low16Bits(value));
214 NewLIR2(cu, kThumb2MovImm16H, r_dest, High16Bits(value));
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 return res;
buzbee67bf8852011-08-17 17:51:35 -0700216}
217
buzbee02031b12012-11-23 09:41:35 -0800218LIR* ArmCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700219{
buzbee02031b12012-11-23 09:41:35 -0800220 LIR* res = NewLIR1(cu, kThumbBUncond, 0 /* offset to be patched during assembly*/);
221 res->target = target;
222 return res;
buzbee67bf8852011-08-17 17:51:35 -0700223}
224
buzbee02031b12012-11-23 09:41:35 -0800225LIR* ArmCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700226{
buzbeefa57c472012-11-21 12:06:18 -0800227 LIR* branch = NewLIR2(cu, kThumb2BCond, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -0800228 ArmConditionEncoding(cc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700229 branch->target = target;
230 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700231}
232
buzbee02031b12012-11-23 09:41:35 -0800233LIR* ArmCodegen::OpReg(CompilationUnit* cu, OpKind op, int r_dest_src)
buzbee67bf8852011-08-17 17:51:35 -0700234{
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 ArmOpcode opcode = kThumbBkpt;
236 switch (op) {
237 case kOpBlx:
238 opcode = kThumbBlxR;
239 break;
240 default:
buzbeecbd6d442012-11-17 14:11:25 -0800241 LOG(FATAL) << "Bad opcode " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700242 }
buzbeefa57c472012-11-21 12:06:18 -0800243 return NewLIR1(cu, opcode, r_dest_src);
buzbee67bf8852011-08-17 17:51:35 -0700244}
245
buzbee02031b12012-11-23 09:41:35 -0800246LIR* ArmCodegen::OpRegRegShift(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2,
247 int shift)
buzbee67bf8852011-08-17 17:51:35 -0700248{
buzbeefa57c472012-11-21 12:06:18 -0800249 bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2));
Bill Buzbeea114add2012-05-03 15:00:40 -0700250 ArmOpcode opcode = kThumbBkpt;
251 switch (op) {
252 case kOpAdc:
buzbeefa57c472012-11-21 12:06:18 -0800253 opcode = (thumb_form) ? kThumbAdcRR : kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 break;
255 case kOpAnd:
buzbeefa57c472012-11-21 12:06:18 -0800256 opcode = (thumb_form) ? kThumbAndRR : kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 break;
258 case kOpBic:
buzbeefa57c472012-11-21 12:06:18 -0800259 opcode = (thumb_form) ? kThumbBicRR : kThumb2BicRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700260 break;
261 case kOpCmn:
262 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800263 opcode = (thumb_form) ? kThumbCmnRR : kThumb2CmnRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 break;
265 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800266 if (thumb_form)
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 opcode = kThumbCmpRR;
buzbeefa57c472012-11-21 12:06:18 -0800268 else if ((shift == 0) && !ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700269 opcode = kThumbCmpHH;
buzbeefa57c472012-11-21 12:06:18 -0800270 else if ((shift == 0) && ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 opcode = kThumbCmpLH;
272 else if (shift == 0)
273 opcode = kThumbCmpHL;
274 else
275 opcode = kThumb2CmpRR;
276 break;
277 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800278 opcode = (thumb_form) ? kThumbEorRR : kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700279 break;
280 case kOpMov:
281 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800282 if (ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700283 opcode = kThumbMovRR;
buzbeefa57c472012-11-21 12:06:18 -0800284 else if (!ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700285 opcode = kThumbMovRR_H2H;
buzbeefa57c472012-11-21 12:06:18 -0800286 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700287 opcode = kThumbMovRR_H2L;
288 else
289 opcode = kThumbMovRR_L2H;
290 break;
291 case kOpMul:
292 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800293 opcode = (thumb_form) ? kThumbMul : kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700294 break;
295 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800296 opcode = (thumb_form) ? kThumbMvn : kThumb2MnvRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 break;
298 case kOpNeg:
299 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800300 opcode = (thumb_form) ? kThumbNeg : kThumb2NegRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700301 break;
302 case kOpOr:
buzbeefa57c472012-11-21 12:06:18 -0800303 opcode = (thumb_form) ? kThumbOrr : kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700304 break;
305 case kOpSbc:
buzbeefa57c472012-11-21 12:06:18 -0800306 opcode = (thumb_form) ? kThumbSbc : kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 break;
308 case kOpTst:
buzbeefa57c472012-11-21 12:06:18 -0800309 opcode = (thumb_form) ? kThumbTst : kThumb2TstRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 break;
311 case kOpLsl:
312 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800313 opcode = (thumb_form) ? kThumbLslRR : kThumb2LslRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 break;
315 case kOpLsr:
316 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800317 opcode = (thumb_form) ? kThumbLsrRR : kThumb2LsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700318 break;
319 case kOpAsr:
320 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800321 opcode = (thumb_form) ? kThumbAsrRR : kThumb2AsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 break;
323 case kOpRor:
324 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800325 opcode = (thumb_form) ? kThumbRorRR : kThumb2RorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 break;
327 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800328 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 break;
330 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800331 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700332 break;
333 case kOp2Byte:
334 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800335 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 8);
Bill Buzbeea114add2012-05-03 15:00:40 -0700336 case kOp2Short:
337 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800338 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 case kOp2Char:
340 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800341 return NewLIR4(cu, kThumb2Ubfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700342 default:
buzbeecbd6d442012-11-17 14:11:25 -0800343 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700344 break;
345 }
346 DCHECK_GE(static_cast<int>(opcode), 0);
347 if (EncodingMap[opcode].flags & IS_BINARY_OP)
buzbeefa57c472012-11-21 12:06:18 -0800348 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700349 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
buzbeefa57c472012-11-21 12:06:18 -0800350 if (EncodingMap[opcode].field_loc[2].kind == kFmtShift)
351 return NewLIR3(cu, opcode, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700352 else
buzbeefa57c472012-11-21 12:06:18 -0800353 return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700354 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800355 return NewLIR4(cu, opcode, r_dest_src1, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700356 else {
357 LOG(FATAL) << "Unexpected encoding operand count";
358 return NULL;
359 }
buzbee67bf8852011-08-17 17:51:35 -0700360}
361
buzbee02031b12012-11-23 09:41:35 -0800362LIR* ArmCodegen::OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700363{
buzbeefa57c472012-11-21 12:06:18 -0800364 return OpRegRegShift(cu, op, r_dest_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700365}
366
buzbee02031b12012-11-23 09:41:35 -0800367LIR* ArmCodegen::OpRegRegRegShift(CompilationUnit* cu, OpKind op, int r_dest, int r_src1,
368 int r_src2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700369{
Bill Buzbeea114add2012-05-03 15:00:40 -0700370 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800371 bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1) &&
372 ARM_LOWREG(r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700373 switch (op) {
374 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800375 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700376 break;
377 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800378 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700379 break;
380 case kOpRsub:
381 opcode = kThumb2RsubRRR;
382 break;
383 case kOpAdc:
384 opcode = kThumb2AdcRRR;
385 break;
386 case kOpAnd:
387 opcode = kThumb2AndRRR;
388 break;
389 case kOpBic:
390 opcode = kThumb2BicRRR;
391 break;
392 case kOpXor:
393 opcode = kThumb2EorRRR;
394 break;
395 case kOpMul:
396 DCHECK_EQ(shift, 0);
397 opcode = kThumb2MulRRR;
398 break;
399 case kOpOr:
400 opcode = kThumb2OrrRRR;
401 break;
402 case kOpSbc:
403 opcode = kThumb2SbcRRR;
404 break;
405 case kOpLsl:
406 DCHECK_EQ(shift, 0);
407 opcode = kThumb2LslRRR;
408 break;
409 case kOpLsr:
410 DCHECK_EQ(shift, 0);
411 opcode = kThumb2LsrRRR;
412 break;
413 case kOpAsr:
414 DCHECK_EQ(shift, 0);
415 opcode = kThumb2AsrRRR;
416 break;
417 case kOpRor:
418 DCHECK_EQ(shift, 0);
419 opcode = kThumb2RorRRR;
420 break;
421 default:
buzbeecbd6d442012-11-17 14:11:25 -0800422 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700423 break;
424 }
425 DCHECK_GE(static_cast<int>(opcode), 0);
426 if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800427 return NewLIR4(cu, opcode, r_dest, r_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700428 else {
429 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
buzbeefa57c472012-11-21 12:06:18 -0800430 return NewLIR3(cu, opcode, r_dest, r_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 }
buzbee67bf8852011-08-17 17:51:35 -0700432}
433
buzbee02031b12012-11-23 09:41:35 -0800434LIR* ArmCodegen::OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700435{
buzbeefa57c472012-11-21 12:06:18 -0800436 return OpRegRegRegShift(cu, op, r_dest, r_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700437}
438
buzbee02031b12012-11-23 09:41:35 -0800439LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700440{
Bill Buzbeea114add2012-05-03 15:00:40 -0700441 LIR* res;
442 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800443 int abs_value = (neg) ? -value : value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800445 ArmOpcode alt_opcode = kThumbBkpt;
446 bool all_low_regs = (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1));
447 int mod_imm = ModifiedImmediate(value);
448 int mod_imm_neg = ModifiedImmediate(-value);
buzbee67bf8852011-08-17 17:51:35 -0700449
Bill Buzbeea114add2012-05-03 15:00:40 -0700450 switch (op) {
451 case kOpLsl:
buzbeefa57c472012-11-21 12:06:18 -0800452 if (all_low_regs)
453 return NewLIR3(cu, kThumbLslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700454 else
buzbeefa57c472012-11-21 12:06:18 -0800455 return NewLIR3(cu, kThumb2LslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700456 case kOpLsr:
buzbeefa57c472012-11-21 12:06:18 -0800457 if (all_low_regs)
458 return NewLIR3(cu, kThumbLsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 else
buzbeefa57c472012-11-21 12:06:18 -0800460 return NewLIR3(cu, kThumb2LsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700461 case kOpAsr:
buzbeefa57c472012-11-21 12:06:18 -0800462 if (all_low_regs)
463 return NewLIR3(cu, kThumbAsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 else
buzbeefa57c472012-11-21 12:06:18 -0800465 return NewLIR3(cu, kThumb2AsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700466 case kOpRor:
buzbeefa57c472012-11-21 12:06:18 -0800467 return NewLIR3(cu, kThumb2RorRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800469 if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800471 return NewLIR3(cu, kThumbAddSpRel, r_dest, r_src1, value >> 2);
472 } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700473 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800474 return NewLIR3(cu, kThumbAddPcRel, r_dest, r_src1, value >> 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700475 }
476 // Note: intentional fallthrough
477 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800478 if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 if (op == kOpAdd)
480 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
buzbee67bf8852011-08-17 17:51:35 -0700481 else
Bill Buzbeea114add2012-05-03 15:00:40 -0700482 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
buzbeefa57c472012-11-21 12:06:18 -0800483 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
484 } else if ((abs_value & 0xff) == abs_value) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700485 if (op == kOpAdd)
486 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
487 else
488 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
buzbeefa57c472012-11-21 12:06:18 -0800489 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700490 }
buzbeefa57c472012-11-21 12:06:18 -0800491 if (mod_imm_neg >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 op = (op == kOpAdd) ? kOpSub : kOpAdd;
buzbeefa57c472012-11-21 12:06:18 -0800493 mod_imm = mod_imm_neg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 }
495 if (op == kOpSub) {
496 opcode = kThumb2SubRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800497 alt_opcode = kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700498 } else {
499 opcode = kThumb2AddRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800500 alt_opcode = kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700501 }
502 break;
503 case kOpAdc:
504 opcode = kThumb2AdcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800505 alt_opcode = kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700506 break;
507 case kOpSbc:
508 opcode = kThumb2SbcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800509 alt_opcode = kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 break;
511 case kOpOr:
512 opcode = kThumb2OrrRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800513 alt_opcode = kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 break;
515 case kOpAnd:
516 opcode = kThumb2AndRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800517 alt_opcode = kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 break;
519 case kOpXor:
520 opcode = kThumb2EorRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800521 alt_opcode = kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 break;
523 case kOpMul:
524 //TUNING: power of 2, shift & add
buzbeefa57c472012-11-21 12:06:18 -0800525 mod_imm = -1;
526 alt_opcode = kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700527 break;
528 case kOpCmp: {
buzbeefa57c472012-11-21 12:06:18 -0800529 int mod_imm = ModifiedImmediate(value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700530 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800531 if (mod_imm >= 0) {
buzbee4ef3e452012-12-14 13:35:28 -0800532 res = NewLIR2(cu, kThumb2CmpRI12, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 } else {
buzbeefa57c472012-11-21 12:06:18 -0800534 int r_tmp = AllocTemp(cu);
535 res = LoadConstant(cu, r_tmp, value);
536 OpRegReg(cu, kOpCmp, r_src1, r_tmp);
537 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 }
539 return res;
buzbee67bf8852011-08-17 17:51:35 -0700540 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 default:
buzbeecbd6d442012-11-17 14:11:25 -0800542 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700543 }
544
buzbeefa57c472012-11-21 12:06:18 -0800545 if (mod_imm >= 0) {
546 return NewLIR3(cu, opcode, r_dest, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 } else {
buzbeefa57c472012-11-21 12:06:18 -0800548 int r_scratch = AllocTemp(cu);
549 LoadConstant(cu, r_scratch, value);
550 if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
551 res = NewLIR4(cu, alt_opcode, r_dest, r_src1, r_scratch, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700552 else
buzbeefa57c472012-11-21 12:06:18 -0800553 res = NewLIR3(cu, alt_opcode, r_dest, r_src1, r_scratch);
554 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700555 return res;
556 }
buzbee67bf8852011-08-17 17:51:35 -0700557}
558
buzbee52a77fc2012-11-20 19:50:46 -0800559/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
buzbee02031b12012-11-23 09:41:35 -0800560LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700561{
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800563 int abs_value = (neg) ? -value : value;
564 bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 ArmOpcode opcode = kThumbBkpt;
566 switch (op) {
567 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800568 if ( !neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800570 return NewLIR1(cu, kThumbAddSpI7, value >> 2);
571 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
573 }
574 break;
575 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800576 if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800578 return NewLIR1(cu, kThumbSubSpI7, value >> 2);
579 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700580 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
581 }
582 break;
583 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800584 if (ARM_LOWREG(r_dest_src1) && short_form)
585 opcode = (short_form) ? kThumbCmpRI8 : kThumbCmpRR;
586 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700587 opcode = kThumbCmpRR;
588 else {
buzbeefa57c472012-11-21 12:06:18 -0800589 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700590 opcode = kThumbCmpHL;
591 }
592 break;
593 default:
buzbee52a77fc2012-11-20 19:50:46 -0800594 /* Punt to OpRegRegImm - if bad case catch it there */
buzbeefa57c472012-11-21 12:06:18 -0800595 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 break;
597 }
buzbeefa57c472012-11-21 12:06:18 -0800598 if (short_form)
599 return NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700600 else {
buzbeefa57c472012-11-21 12:06:18 -0800601 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700602 }
buzbee67bf8852011-08-17 17:51:35 -0700603}
604
buzbee4ef3e452012-12-14 13:35:28 -0800605LIR* ArmCodegen::LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, int64_t value)
buzbee67bf8852011-08-17 17:51:35 -0700606{
buzbee4ef3e452012-12-14 13:35:28 -0800607 LIR* res = NULL;
608 int32_t val_lo = Low32Bits(value);
609 int32_t val_hi = High32Bits(value);
buzbee7da142f2012-11-29 16:33:42 -0800610 int target_reg = S2d(r_dest_lo, r_dest_hi);
buzbeefa57c472012-11-21 12:06:18 -0800611 if (ARM_FPREG(r_dest_lo)) {
buzbee7da142f2012-11-29 16:33:42 -0800612 if ((val_lo == 0) && (val_hi == 0)) {
613 // TODO: we need better info about the target CPU. a vector exclusive or
614 // would probably be better here if we could rely on its existance.
615 // Load an immediate +2.0 (which encodes to 0)
616 NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, 0);
617 // +0.0 = +2.0 - +2.0
618 res = NewLIR3(cu, kThumb2Vsubd, target_reg, target_reg, target_reg);
buzbee67bf8852011-08-17 17:51:35 -0700619 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800620 int encoded_imm = EncodeImmDouble(value);
buzbee7da142f2012-11-29 16:33:42 -0800621 if (encoded_imm >= 0) {
622 res = NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, encoded_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700623 }
buzbee67bf8852011-08-17 17:51:35 -0700624 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800626 if ((InexpensiveConstantInt(val_lo) && (InexpensiveConstantInt(val_hi)))) {
627 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
628 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
629 }
630 }
631 if (res == NULL) {
632 // No short form - load from the literal pool.
633 LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi);
634 if (data_target == NULL) {
635 data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi);
636 }
637 if (ARM_FPREG(r_dest_lo)) {
638 res = RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd,
639 target_reg, r15pc, 0, 0, 0, data_target);
640 } else {
641 res = RawLIR(cu, cu->current_dalvik_offset, kThumb2LdrdPcRel8,
642 r_dest_lo, r_dest_hi, r15pc, 0, 0, data_target);
643 }
644 SetMemRefType(cu, res, true, kLiteral);
645 res->alias_info = reinterpret_cast<uintptr_t>(data_target);
646 AppendLIR(cu, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700647 }
648 return res;
buzbee67bf8852011-08-17 17:51:35 -0700649}
650
buzbee02031b12012-11-23 09:41:35 -0800651int ArmCodegen::EncodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700652 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700653}
654
buzbee02031b12012-11-23 09:41:35 -0800655LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest,
656 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700657{
buzbeefa57c472012-11-21 12:06:18 -0800658 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 LIR* load;
660 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800661 bool thumb_form = (all_low_regs && (scale == 0));
662 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700663
buzbeefa57c472012-11-21 12:06:18 -0800664 if (ARM_FPREG(r_dest)) {
665 if (ARM_SINGLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 DCHECK((size == kWord) || (size == kSingle));
667 opcode = kThumb2Vldrs;
668 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700669 } else {
buzbeefa57c472012-11-21 12:06:18 -0800670 DCHECK(ARM_DOUBLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700671 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800672 DCHECK_EQ((r_dest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700673 opcode = kThumb2Vldrd;
674 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700675 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700676 } else {
677 if (size == kSingle)
678 size = kWord;
679 }
buzbee67bf8852011-08-17 17:51:35 -0700680
Bill Buzbeea114add2012-05-03 15:00:40 -0700681 switch (size) {
682 case kDouble: // fall-through
683 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800684 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700685 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800686 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800687 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700688 } else {
buzbeefa57c472012-11-21 12:06:18 -0800689 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700690 }
buzbeefa57c472012-11-21 12:06:18 -0800691 load = NewLIR3(cu, opcode, r_dest, reg_ptr, 0);
692 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700693 return load;
694 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800695 opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 break;
697 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800698 opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 break;
700 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800701 opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700702 break;
703 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800704 opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700705 break;
706 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800707 opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700708 break;
709 default:
buzbeecbd6d442012-11-17 14:11:25 -0800710 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700711 }
buzbeefa57c472012-11-21 12:06:18 -0800712 if (thumb_form)
713 load = NewLIR3(cu, opcode, r_dest, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700714 else
buzbeefa57c472012-11-21 12:06:18 -0800715 load = NewLIR4(cu, opcode, r_dest, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700716
Bill Buzbeea114add2012-05-03 15:00:40 -0700717 return load;
buzbee67bf8852011-08-17 17:51:35 -0700718}
719
buzbee02031b12012-11-23 09:41:35 -0800720LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src,
721 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700722{
buzbeefa57c472012-11-21 12:06:18 -0800723 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
buzbee4ef3e452012-12-14 13:35:28 -0800724 LIR* store = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700725 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800726 bool thumb_form = (all_low_regs && (scale == 0));
727 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700728
buzbeefa57c472012-11-21 12:06:18 -0800729 if (ARM_FPREG(r_src)) {
730 if (ARM_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 DCHECK((size == kWord) || (size == kSingle));
732 opcode = kThumb2Vstrs;
733 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700734 } else {
buzbeefa57c472012-11-21 12:06:18 -0800735 DCHECK(ARM_DOUBLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700736 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800737 DCHECK_EQ((r_src & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700738 opcode = kThumb2Vstrd;
739 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700740 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700741 } else {
742 if (size == kSingle)
743 size = kWord;
744 }
buzbee67bf8852011-08-17 17:51:35 -0700745
Bill Buzbeea114add2012-05-03 15:00:40 -0700746 switch (size) {
747 case kDouble: // fall-through
748 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800749 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700750 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800751 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800752 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700753 } else {
buzbeefa57c472012-11-21 12:06:18 -0800754 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700755 }
buzbeefa57c472012-11-21 12:06:18 -0800756 store = NewLIR3(cu, opcode, r_src, reg_ptr, 0);
757 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700758 return store;
759 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800760 opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 break;
762 case kUnsignedHalf:
763 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800764 opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 break;
766 case kUnsignedByte:
767 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800768 opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700769 break;
770 default:
buzbeecbd6d442012-11-17 14:11:25 -0800771 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700772 }
buzbeefa57c472012-11-21 12:06:18 -0800773 if (thumb_form)
774 store = NewLIR3(cu, opcode, r_src, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 else
buzbeefa57c472012-11-21 12:06:18 -0800776 store = NewLIR4(cu, opcode, r_src, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700777
Bill Buzbeea114add2012-05-03 15:00:40 -0700778 return store;
buzbee67bf8852011-08-17 17:51:35 -0700779}
780
781/*
782 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800783 * on base (which must have an associated s_reg and MIR). If not
buzbee67bf8852011-08-17 17:51:35 -0700784 * performing null check, incoming MIR can be null.
785 */
buzbee02031b12012-11-23 09:41:35 -0800786LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest,
787 int r_dest_hi, OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700788{
buzbee02031b12012-11-23 09:41:35 -0800789 Codegen* cg = cu->cg.get();
buzbee4ef3e452012-12-14 13:35:28 -0800790 LIR* load = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700791 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800792 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700793 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800794 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
795 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700796 bool is64bit = false;
buzbee4ef3e452012-12-14 13:35:28 -0800797 bool already_generated = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700798 switch (size) {
799 case kDouble:
800 case kLong:
801 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800802 if (ARM_FPREG(r_dest)) {
803 if (ARM_SINGLEREG(r_dest)) {
804 DCHECK(ARM_FPREG(r_dest_hi));
buzbee02031b12012-11-23 09:41:35 -0800805 r_dest = cg->S2d(r_dest, r_dest_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700806 }
807 opcode = kThumb2Vldrd;
808 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800809 short_form = true;
810 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700811 }
812 break;
813 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800814 if (displacement <= 1020) {
815 load = NewLIR4(cu, kThumb2LdrdI8, r_dest, r_dest_hi, rBase, displacement >> 2);
816 } else {
817 load = LoadBaseDispBody(cu, rBase, displacement, r_dest,
818 -1, kWord, s_reg);
819 LoadBaseDispBody(cu, rBase, displacement + 4, r_dest_hi,
820 -1, kWord, INVALID_SREG);
821 }
822 already_generated = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700823 }
824 case kSingle:
825 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800826 if (ARM_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700827 opcode = kThumb2Vldrs;
828 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800829 short_form = true;
830 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 }
832 break;
833 }
buzbeefa57c472012-11-21 12:06:18 -0800834 if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800836 short_form = true;
837 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700838 opcode = kThumbLdrPcRel;
buzbeefa57c472012-11-21 12:06:18 -0800839 } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800841 short_form = true;
842 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700843 opcode = kThumbLdrSpRel;
buzbeefa57c472012-11-21 12:06:18 -0800844 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700845 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800846 short_form = true;
847 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 opcode = kThumbLdrRRI5;
849 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800850 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 opcode = kThumb2LdrRRI12;
852 }
853 break;
854 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800855 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700856 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800857 short_form = true;
858 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700859 opcode = kThumbLdrhRRI5;
860 } else if (displacement < 4092 && displacement >= 0) {
buzbeefa57c472012-11-21 12:06:18 -0800861 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 opcode = kThumb2LdrhRRI12;
863 }
864 break;
865 case kSignedHalf:
866 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800867 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700868 opcode = kThumb2LdrshRRI12;
869 }
870 break;
871 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800872 if (all_low_regs && displacement < 32 && displacement >= 0) {
873 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700874 opcode = kThumbLdrbRRI5;
875 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800876 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700877 opcode = kThumb2LdrbRRI12;
878 }
879 break;
880 case kSignedByte:
881 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800882 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700883 opcode = kThumb2LdrsbRRI12;
884 }
885 break;
886 default:
buzbeecbd6d442012-11-17 14:11:25 -0800887 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700888 }
buzbee67bf8852011-08-17 17:51:35 -0700889
buzbee4ef3e452012-12-14 13:35:28 -0800890 if (!already_generated) {
891 if (short_form) {
892 load = NewLIR3(cu, opcode, r_dest, rBase, encoded_disp);
893 } else {
894 int reg_offset = AllocTemp(cu);
895 cg->LoadConstant(cu, reg_offset, encoded_disp);
896 load = cg->LoadBaseIndexed(cu, rBase, reg_offset, r_dest, 0, size);
897 FreeTemp(cu, reg_offset);
898 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 }
buzbee67bf8852011-08-17 17:51:35 -0700900
Bill Buzbeea114add2012-05-03 15:00:40 -0700901 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800902 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -0800903 AnnotateDalvikRegAccess(cu, load, displacement >> 2, true /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700904 }
905 return load;
buzbee67bf8852011-08-17 17:51:35 -0700906}
907
buzbee02031b12012-11-23 09:41:35 -0800908LIR* ArmCodegen::LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest,
909 OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700910{
buzbee02031b12012-11-23 09:41:35 -0800911 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1, size, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700912}
913
buzbee02031b12012-11-23 09:41:35 -0800914LIR* ArmCodegen::LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo,
915 int r_dest_hi, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700916{
buzbee02031b12012-11-23 09:41:35 -0800917 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700918}
919
920
buzbee02031b12012-11-23 09:41:35 -0800921LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement,
922 int r_src, int r_src_hi, OpSize size) {
923 Codegen* cg = cu->cg.get();
buzbee4ef3e452012-12-14 13:35:28 -0800924 LIR* store = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700925 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800926 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700927 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800928 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
929 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 bool is64bit = false;
buzbee4ef3e452012-12-14 13:35:28 -0800931 bool already_generated = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700932 switch (size) {
933 case kLong:
934 case kDouble:
935 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800936 if (!ARM_FPREG(r_src)) {
buzbee4ef3e452012-12-14 13:35:28 -0800937 if (displacement <= 1020) {
938 store = NewLIR4(cu, kThumb2StrdI8, r_src, r_src_hi, rBase, displacement >> 2);
939 } else {
940 store = StoreBaseDispBody(cu, rBase, displacement, r_src, -1, kWord);
941 StoreBaseDispBody(cu, rBase, displacement + 4, r_src_hi, -1, kWord);
942 }
943 already_generated = true;
944 } else {
945 if (ARM_SINGLEREG(r_src)) {
946 DCHECK(ARM_FPREG(r_src_hi));
947 r_src = cg->S2d(r_src, r_src_hi);
948 }
949 opcode = kThumb2Vstrd;
950 if (displacement <= 1020) {
951 short_form = true;
952 encoded_disp >>= 2;
953 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700954 }
955 break;
956 case kSingle:
957 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800958 if (ARM_FPREG(r_src)) {
959 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700960 opcode = kThumb2Vstrs;
961 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800962 short_form = true;
963 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700964 }
965 break;
966 }
buzbeefa57c472012-11-21 12:06:18 -0800967 if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700968 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800969 short_form = true;
970 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700971 opcode = kThumbStrRRI5;
972 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800973 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700974 opcode = kThumb2StrRRI12;
975 }
976 break;
977 case kUnsignedHalf:
978 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800979 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800981 short_form = true;
982 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 opcode = kThumbStrhRRI5;
984 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800985 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700986 opcode = kThumb2StrhRRI12;
987 }
988 break;
989 case kUnsignedByte:
990 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800991 if (all_low_regs && displacement < 32 && displacement >= 0) {
992 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700993 opcode = kThumbStrbRRI5;
994 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800995 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700996 opcode = kThumb2StrbRRI12;
997 }
998 break;
999 default:
buzbeecbd6d442012-11-17 14:11:25 -08001000 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -07001001 }
buzbee4ef3e452012-12-14 13:35:28 -08001002 if (!already_generated) {
1003 if (short_form) {
1004 store = NewLIR3(cu, opcode, r_src, rBase, encoded_disp);
1005 } else {
1006 int r_scratch = AllocTemp(cu);
1007 cg->LoadConstant(cu, r_scratch, encoded_disp);
1008 store = cg->StoreBaseIndexed(cu, rBase, r_scratch, r_src, 0, size);
1009 FreeTemp(cu, r_scratch);
1010 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001011 }
buzbee67bf8852011-08-17 17:51:35 -07001012
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -08001014 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -08001015 AnnotateDalvikRegAccess(cu, store, displacement >> 2, false /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -07001016 }
buzbee4ef3e452012-12-14 13:35:28 -08001017 return store;
buzbee67bf8852011-08-17 17:51:35 -07001018}
1019
buzbee02031b12012-11-23 09:41:35 -08001020LIR* ArmCodegen::StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src,
1021 OpSize size)
buzbee67bf8852011-08-17 17:51:35 -07001022{
buzbeefa57c472012-11-21 12:06:18 -08001023 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbee67bf8852011-08-17 17:51:35 -07001024}
1025
buzbee02031b12012-11-23 09:41:35 -08001026LIR* ArmCodegen::StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement,
1027 int r_src_lo, int r_src_hi)
buzbee67bf8852011-08-17 17:51:35 -07001028{
buzbeefa57c472012-11-21 12:06:18 -08001029 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbee67bf8852011-08-17 17:51:35 -07001030}
1031
buzbee02031b12012-11-23 09:41:35 -08001032LIR* ArmCodegen::OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src)
buzbee67bf8852011-08-17 17:51:35 -07001033{
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 int opcode;
buzbeefa57c472012-11-21 12:06:18 -08001035 DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
1036 if (ARM_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001037 opcode = kThumb2Vmovd;
1038 } else {
buzbeefa57c472012-11-21 12:06:18 -08001039 if (ARM_SINGLEREG(r_dest)) {
1040 opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001041 } else {
buzbeefa57c472012-11-21 12:06:18 -08001042 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -07001043 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001044 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001045 }
buzbeefa57c472012-11-21 12:06:18 -08001046 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
1047 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
1048 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001049 }
1050 return res;
buzbee67bf8852011-08-17 17:51:35 -07001051}
1052
buzbee02031b12012-11-23 09:41:35 -08001053LIR* ArmCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -07001054{
buzbee52a77fc2012-11-20 19:50:46 -08001055 LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001056 return NULL;
1057}
buzbee67bf8852011-08-17 17:51:35 -07001058
buzbee02031b12012-11-23 09:41:35 -08001059LIR* ArmCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -07001060{
buzbee52a77fc2012-11-20 19:50:46 -08001061 LOG(FATAL) << "Unexpected use of OpMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001062 return NULL;
1063}
1064
buzbee02031b12012-11-23 09:41:35 -08001065LIR* ArmCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1066 int displacement, int r_src, int r_src_hi, OpSize size,
1067 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001068{
buzbee52a77fc2012-11-20 19:50:46 -08001069 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001070 return NULL;
1071}
1072
buzbee02031b12012-11-23 09:41:35 -08001073LIR* ArmCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, int offset)
buzbeeb046e162012-10-30 15:48:42 -07001074{
buzbee52a77fc2012-11-20 19:50:46 -08001075 LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001076 return NULL;
1077}
1078
buzbee02031b12012-11-23 09:41:35 -08001079LIR* ArmCodegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1080 int displacement, int r_dest, int r_dest_hi, OpSize size,
1081 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001082{
buzbee52a77fc2012-11-20 19:50:46 -08001083 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001084 return NULL;
1085}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001086
1087} // namespace art