blob: 33e821060ca2c94466a83d002477facb73750570 [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"
buzbee395116c2013-02-27 14:30:25 -080019#include "compiler/dex/quick/codegen_util.h"
20#include "compiler/dex/quick/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;
buzbeec7d1f912013-02-07 15:22:39 -0800503 case kOpRsub:
504 opcode = kThumb2RsubRRI8;
505 alt_opcode = kThumb2RsubRRR;
506 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 case kOpAdc:
508 opcode = kThumb2AdcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800509 alt_opcode = kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700510 break;
511 case kOpSbc:
512 opcode = kThumb2SbcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800513 alt_opcode = kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700514 break;
515 case kOpOr:
516 opcode = kThumb2OrrRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800517 alt_opcode = kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 break;
519 case kOpAnd:
520 opcode = kThumb2AndRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800521 alt_opcode = kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 break;
523 case kOpXor:
524 opcode = kThumb2EorRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800525 alt_opcode = kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 break;
527 case kOpMul:
528 //TUNING: power of 2, shift & add
buzbeefa57c472012-11-21 12:06:18 -0800529 mod_imm = -1;
530 alt_opcode = kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700531 break;
532 case kOpCmp: {
buzbeefa57c472012-11-21 12:06:18 -0800533 int mod_imm = ModifiedImmediate(value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700534 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800535 if (mod_imm >= 0) {
buzbee4ef3e452012-12-14 13:35:28 -0800536 res = NewLIR2(cu, kThumb2CmpRI12, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700537 } else {
buzbeefa57c472012-11-21 12:06:18 -0800538 int r_tmp = AllocTemp(cu);
539 res = LoadConstant(cu, r_tmp, value);
540 OpRegReg(cu, kOpCmp, r_src1, r_tmp);
541 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700542 }
543 return res;
buzbee67bf8852011-08-17 17:51:35 -0700544 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700545 default:
buzbeecbd6d442012-11-17 14:11:25 -0800546 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 }
548
buzbeefa57c472012-11-21 12:06:18 -0800549 if (mod_imm >= 0) {
550 return NewLIR3(cu, opcode, r_dest, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 } else {
buzbeefa57c472012-11-21 12:06:18 -0800552 int r_scratch = AllocTemp(cu);
553 LoadConstant(cu, r_scratch, value);
554 if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
555 res = NewLIR4(cu, alt_opcode, r_dest, r_src1, r_scratch, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700556 else
buzbeefa57c472012-11-21 12:06:18 -0800557 res = NewLIR3(cu, alt_opcode, r_dest, r_src1, r_scratch);
558 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700559 return res;
560 }
buzbee67bf8852011-08-17 17:51:35 -0700561}
562
buzbee52a77fc2012-11-20 19:50:46 -0800563/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
buzbee02031b12012-11-23 09:41:35 -0800564LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700565{
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800567 int abs_value = (neg) ? -value : value;
568 bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700569 ArmOpcode opcode = kThumbBkpt;
570 switch (op) {
571 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800572 if ( !neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700573 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800574 return NewLIR1(cu, kThumbAddSpI7, value >> 2);
575 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700576 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
577 }
578 break;
579 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800580 if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700581 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800582 return NewLIR1(cu, kThumbSubSpI7, value >> 2);
583 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700584 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
585 }
586 break;
587 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800588 if (ARM_LOWREG(r_dest_src1) && short_form)
589 opcode = (short_form) ? kThumbCmpRI8 : kThumbCmpRR;
590 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700591 opcode = kThumbCmpRR;
592 else {
buzbeefa57c472012-11-21 12:06:18 -0800593 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 opcode = kThumbCmpHL;
595 }
596 break;
597 default:
buzbee52a77fc2012-11-20 19:50:46 -0800598 /* Punt to OpRegRegImm - if bad case catch it there */
buzbeefa57c472012-11-21 12:06:18 -0800599 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700600 break;
601 }
buzbeefa57c472012-11-21 12:06:18 -0800602 if (short_form)
603 return NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700604 else {
buzbeefa57c472012-11-21 12:06:18 -0800605 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 }
buzbee67bf8852011-08-17 17:51:35 -0700607}
608
buzbee4ef3e452012-12-14 13:35:28 -0800609LIR* ArmCodegen::LoadConstantWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi, int64_t value)
buzbee67bf8852011-08-17 17:51:35 -0700610{
buzbee4ef3e452012-12-14 13:35:28 -0800611 LIR* res = NULL;
612 int32_t val_lo = Low32Bits(value);
613 int32_t val_hi = High32Bits(value);
buzbee7da142f2012-11-29 16:33:42 -0800614 int target_reg = S2d(r_dest_lo, r_dest_hi);
buzbeefa57c472012-11-21 12:06:18 -0800615 if (ARM_FPREG(r_dest_lo)) {
buzbee7da142f2012-11-29 16:33:42 -0800616 if ((val_lo == 0) && (val_hi == 0)) {
617 // TODO: we need better info about the target CPU. a vector exclusive or
618 // would probably be better here if we could rely on its existance.
619 // Load an immediate +2.0 (which encodes to 0)
620 NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, 0);
621 // +0.0 = +2.0 - +2.0
622 res = NewLIR3(cu, kThumb2Vsubd, target_reg, target_reg, target_reg);
buzbee67bf8852011-08-17 17:51:35 -0700623 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800624 int encoded_imm = EncodeImmDouble(value);
buzbee7da142f2012-11-29 16:33:42 -0800625 if (encoded_imm >= 0) {
626 res = NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, encoded_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 }
buzbee67bf8852011-08-17 17:51:35 -0700628 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700629 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800630 if ((InexpensiveConstantInt(val_lo) && (InexpensiveConstantInt(val_hi)))) {
631 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
632 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
633 }
634 }
635 if (res == NULL) {
636 // No short form - load from the literal pool.
637 LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi);
638 if (data_target == NULL) {
639 data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi);
640 }
641 if (ARM_FPREG(r_dest_lo)) {
642 res = RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd,
643 target_reg, r15pc, 0, 0, 0, data_target);
644 } else {
645 res = RawLIR(cu, cu->current_dalvik_offset, kThumb2LdrdPcRel8,
646 r_dest_lo, r_dest_hi, r15pc, 0, 0, data_target);
647 }
648 SetMemRefType(cu, res, true, kLiteral);
649 res->alias_info = reinterpret_cast<uintptr_t>(data_target);
650 AppendLIR(cu, res);
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 }
652 return res;
buzbee67bf8852011-08-17 17:51:35 -0700653}
654
buzbee02031b12012-11-23 09:41:35 -0800655int ArmCodegen::EncodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700656 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700657}
658
buzbee02031b12012-11-23 09:41:35 -0800659LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest,
660 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700661{
buzbeefa57c472012-11-21 12:06:18 -0800662 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 LIR* load;
664 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800665 bool thumb_form = (all_low_regs && (scale == 0));
666 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700667
buzbeefa57c472012-11-21 12:06:18 -0800668 if (ARM_FPREG(r_dest)) {
669 if (ARM_SINGLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700670 DCHECK((size == kWord) || (size == kSingle));
671 opcode = kThumb2Vldrs;
672 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700673 } else {
buzbeefa57c472012-11-21 12:06:18 -0800674 DCHECK(ARM_DOUBLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700675 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800676 DCHECK_EQ((r_dest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 opcode = kThumb2Vldrd;
678 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700679 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700680 } else {
681 if (size == kSingle)
682 size = kWord;
683 }
buzbee67bf8852011-08-17 17:51:35 -0700684
Bill Buzbeea114add2012-05-03 15:00:40 -0700685 switch (size) {
686 case kDouble: // fall-through
687 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800688 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700689 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800690 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800691 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 } else {
buzbeefa57c472012-11-21 12:06:18 -0800693 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700694 }
buzbeefa57c472012-11-21 12:06:18 -0800695 load = NewLIR3(cu, opcode, r_dest, reg_ptr, 0);
696 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700697 return load;
698 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800699 opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700700 break;
701 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800702 opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700703 break;
704 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800705 opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700706 break;
707 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800708 opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700709 break;
710 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800711 opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700712 break;
713 default:
buzbeecbd6d442012-11-17 14:11:25 -0800714 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700715 }
buzbeefa57c472012-11-21 12:06:18 -0800716 if (thumb_form)
717 load = NewLIR3(cu, opcode, r_dest, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700718 else
buzbeefa57c472012-11-21 12:06:18 -0800719 load = NewLIR4(cu, opcode, r_dest, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700720
Bill Buzbeea114add2012-05-03 15:00:40 -0700721 return load;
buzbee67bf8852011-08-17 17:51:35 -0700722}
723
buzbee02031b12012-11-23 09:41:35 -0800724LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src,
725 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700726{
buzbeefa57c472012-11-21 12:06:18 -0800727 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
buzbee4ef3e452012-12-14 13:35:28 -0800728 LIR* store = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700729 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800730 bool thumb_form = (all_low_regs && (scale == 0));
731 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700732
buzbeefa57c472012-11-21 12:06:18 -0800733 if (ARM_FPREG(r_src)) {
734 if (ARM_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700735 DCHECK((size == kWord) || (size == kSingle));
736 opcode = kThumb2Vstrs;
737 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700738 } else {
buzbeefa57c472012-11-21 12:06:18 -0800739 DCHECK(ARM_DOUBLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700740 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800741 DCHECK_EQ((r_src & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700742 opcode = kThumb2Vstrd;
743 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700744 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700745 } else {
746 if (size == kSingle)
747 size = kWord;
748 }
buzbee67bf8852011-08-17 17:51:35 -0700749
Bill Buzbeea114add2012-05-03 15:00:40 -0700750 switch (size) {
751 case kDouble: // fall-through
752 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800753 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800755 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800756 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700757 } else {
buzbeefa57c472012-11-21 12:06:18 -0800758 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700759 }
buzbeefa57c472012-11-21 12:06:18 -0800760 store = NewLIR3(cu, opcode, r_src, reg_ptr, 0);
761 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700762 return store;
763 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800764 opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 break;
766 case kUnsignedHalf:
767 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800768 opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700769 break;
770 case kUnsignedByte:
771 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800772 opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700773 break;
774 default:
buzbeecbd6d442012-11-17 14:11:25 -0800775 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700776 }
buzbeefa57c472012-11-21 12:06:18 -0800777 if (thumb_form)
778 store = NewLIR3(cu, opcode, r_src, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700779 else
buzbeefa57c472012-11-21 12:06:18 -0800780 store = NewLIR4(cu, opcode, r_src, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700781
Bill Buzbeea114add2012-05-03 15:00:40 -0700782 return store;
buzbee67bf8852011-08-17 17:51:35 -0700783}
784
785/*
786 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800787 * on base (which must have an associated s_reg and MIR). If not
buzbee67bf8852011-08-17 17:51:35 -0700788 * performing null check, incoming MIR can be null.
789 */
buzbee02031b12012-11-23 09:41:35 -0800790LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest,
791 int r_dest_hi, OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700792{
buzbee02031b12012-11-23 09:41:35 -0800793 Codegen* cg = cu->cg.get();
buzbee4ef3e452012-12-14 13:35:28 -0800794 LIR* load = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700795 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800796 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700797 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800798 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
799 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700800 bool is64bit = false;
buzbee4ef3e452012-12-14 13:35:28 -0800801 bool already_generated = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700802 switch (size) {
803 case kDouble:
804 case kLong:
805 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800806 if (ARM_FPREG(r_dest)) {
807 if (ARM_SINGLEREG(r_dest)) {
808 DCHECK(ARM_FPREG(r_dest_hi));
buzbee02031b12012-11-23 09:41:35 -0800809 r_dest = cg->S2d(r_dest, r_dest_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700810 }
811 opcode = kThumb2Vldrd;
812 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800813 short_form = true;
814 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700815 }
816 break;
817 } else {
buzbee4ef3e452012-12-14 13:35:28 -0800818 if (displacement <= 1020) {
819 load = NewLIR4(cu, kThumb2LdrdI8, r_dest, r_dest_hi, rBase, displacement >> 2);
820 } else {
821 load = LoadBaseDispBody(cu, rBase, displacement, r_dest,
822 -1, kWord, s_reg);
823 LoadBaseDispBody(cu, rBase, displacement + 4, r_dest_hi,
824 -1, kWord, INVALID_SREG);
825 }
826 already_generated = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700827 }
828 case kSingle:
829 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800830 if (ARM_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700831 opcode = kThumb2Vldrs;
832 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800833 short_form = true;
834 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 }
836 break;
837 }
buzbeefa57c472012-11-21 12:06:18 -0800838 if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700839 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800840 short_form = true;
841 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 opcode = kThumbLdrPcRel;
buzbeefa57c472012-11-21 12:06:18 -0800843 } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700844 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800845 short_form = true;
846 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700847 opcode = kThumbLdrSpRel;
buzbeefa57c472012-11-21 12:06:18 -0800848 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700849 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800850 short_form = true;
851 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 opcode = kThumbLdrRRI5;
853 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800854 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700855 opcode = kThumb2LdrRRI12;
856 }
857 break;
858 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800859 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700860 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800861 short_form = true;
862 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 opcode = kThumbLdrhRRI5;
864 } else if (displacement < 4092 && displacement >= 0) {
buzbeefa57c472012-11-21 12:06:18 -0800865 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 opcode = kThumb2LdrhRRI12;
867 }
868 break;
869 case kSignedHalf:
870 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800871 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700872 opcode = kThumb2LdrshRRI12;
873 }
874 break;
875 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800876 if (all_low_regs && displacement < 32 && displacement >= 0) {
877 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700878 opcode = kThumbLdrbRRI5;
879 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800880 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 opcode = kThumb2LdrbRRI12;
882 }
883 break;
884 case kSignedByte:
885 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800886 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700887 opcode = kThumb2LdrsbRRI12;
888 }
889 break;
890 default:
buzbeecbd6d442012-11-17 14:11:25 -0800891 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700892 }
buzbee67bf8852011-08-17 17:51:35 -0700893
buzbee4ef3e452012-12-14 13:35:28 -0800894 if (!already_generated) {
895 if (short_form) {
896 load = NewLIR3(cu, opcode, r_dest, rBase, encoded_disp);
897 } else {
898 int reg_offset = AllocTemp(cu);
899 cg->LoadConstant(cu, reg_offset, encoded_disp);
900 load = cg->LoadBaseIndexed(cu, rBase, reg_offset, r_dest, 0, size);
901 FreeTemp(cu, reg_offset);
902 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700903 }
buzbee67bf8852011-08-17 17:51:35 -0700904
Bill Buzbeea114add2012-05-03 15:00:40 -0700905 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800906 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -0800907 AnnotateDalvikRegAccess(cu, load, displacement >> 2, true /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700908 }
909 return load;
buzbee67bf8852011-08-17 17:51:35 -0700910}
911
buzbee02031b12012-11-23 09:41:35 -0800912LIR* ArmCodegen::LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest,
913 OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700914{
buzbee02031b12012-11-23 09:41:35 -0800915 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1, size, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700916}
917
buzbee02031b12012-11-23 09:41:35 -0800918LIR* ArmCodegen::LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo,
919 int r_dest_hi, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700920{
buzbee02031b12012-11-23 09:41:35 -0800921 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700922}
923
924
buzbee02031b12012-11-23 09:41:35 -0800925LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement,
926 int r_src, int r_src_hi, OpSize size) {
927 Codegen* cg = cu->cg.get();
buzbee4ef3e452012-12-14 13:35:28 -0800928 LIR* store = NULL;
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800930 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700931 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800932 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
933 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 bool is64bit = false;
buzbee4ef3e452012-12-14 13:35:28 -0800935 bool already_generated = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700936 switch (size) {
937 case kLong:
938 case kDouble:
939 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800940 if (!ARM_FPREG(r_src)) {
buzbee4ef3e452012-12-14 13:35:28 -0800941 if (displacement <= 1020) {
942 store = NewLIR4(cu, kThumb2StrdI8, r_src, r_src_hi, rBase, displacement >> 2);
943 } else {
944 store = StoreBaseDispBody(cu, rBase, displacement, r_src, -1, kWord);
945 StoreBaseDispBody(cu, rBase, displacement + 4, r_src_hi, -1, kWord);
946 }
947 already_generated = true;
948 } else {
949 if (ARM_SINGLEREG(r_src)) {
950 DCHECK(ARM_FPREG(r_src_hi));
951 r_src = cg->S2d(r_src, r_src_hi);
952 }
953 opcode = kThumb2Vstrd;
954 if (displacement <= 1020) {
955 short_form = true;
956 encoded_disp >>= 2;
957 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700958 }
959 break;
960 case kSingle:
961 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800962 if (ARM_FPREG(r_src)) {
963 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700964 opcode = kThumb2Vstrs;
965 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800966 short_form = true;
967 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700968 }
Sebastien Hertza188cd42013-03-28 17:23:23 +0100969 break;
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 }
Sebastien Hertza188cd42013-03-28 17:23:23 +0100971 if (ARM_LOWREG(r_src) && (rBase == r13sp) &&
972 (displacement <= 1020) && (displacement >= 0)) {
973 short_form = true;
974 encoded_disp >>= 2;
975 opcode = kThumbStrSpRel;
976 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800978 short_form = true;
979 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 opcode = kThumbStrRRI5;
981 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800982 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700983 opcode = kThumb2StrRRI12;
984 }
985 break;
986 case kUnsignedHalf:
987 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800988 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700989 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800990 short_form = true;
991 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 opcode = kThumbStrhRRI5;
993 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800994 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 opcode = kThumb2StrhRRI12;
996 }
997 break;
998 case kUnsignedByte:
999 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -08001000 if (all_low_regs && displacement < 32 && displacement >= 0) {
1001 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001002 opcode = kThumbStrbRRI5;
1003 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -08001004 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001005 opcode = kThumb2StrbRRI12;
1006 }
1007 break;
1008 default:
buzbeecbd6d442012-11-17 14:11:25 -08001009 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 }
buzbee4ef3e452012-12-14 13:35:28 -08001011 if (!already_generated) {
1012 if (short_form) {
1013 store = NewLIR3(cu, opcode, r_src, rBase, encoded_disp);
1014 } else {
1015 int r_scratch = AllocTemp(cu);
1016 cg->LoadConstant(cu, r_scratch, encoded_disp);
1017 store = cg->StoreBaseIndexed(cu, rBase, r_scratch, r_src, 0, size);
1018 FreeTemp(cu, r_scratch);
1019 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001020 }
buzbee67bf8852011-08-17 17:51:35 -07001021
Bill Buzbeea114add2012-05-03 15:00:40 -07001022 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -08001023 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -08001024 AnnotateDalvikRegAccess(cu, store, displacement >> 2, false /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -07001025 }
buzbee4ef3e452012-12-14 13:35:28 -08001026 return store;
buzbee67bf8852011-08-17 17:51:35 -07001027}
1028
buzbee02031b12012-11-23 09:41:35 -08001029LIR* ArmCodegen::StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src,
1030 OpSize size)
buzbee67bf8852011-08-17 17:51:35 -07001031{
buzbeefa57c472012-11-21 12:06:18 -08001032 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbee67bf8852011-08-17 17:51:35 -07001033}
1034
buzbee02031b12012-11-23 09:41:35 -08001035LIR* ArmCodegen::StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement,
1036 int r_src_lo, int r_src_hi)
buzbee67bf8852011-08-17 17:51:35 -07001037{
buzbeefa57c472012-11-21 12:06:18 -08001038 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbee67bf8852011-08-17 17:51:35 -07001039}
1040
buzbee02031b12012-11-23 09:41:35 -08001041LIR* ArmCodegen::OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src)
buzbee67bf8852011-08-17 17:51:35 -07001042{
Bill Buzbeea114add2012-05-03 15:00:40 -07001043 int opcode;
buzbeefa57c472012-11-21 12:06:18 -08001044 DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
1045 if (ARM_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001046 opcode = kThumb2Vmovd;
1047 } else {
buzbeefa57c472012-11-21 12:06:18 -08001048 if (ARM_SINGLEREG(r_dest)) {
1049 opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001050 } else {
buzbeefa57c472012-11-21 12:06:18 -08001051 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -07001052 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001053 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001054 }
buzbeefa57c472012-11-21 12:06:18 -08001055 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
1056 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
1057 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001058 }
1059 return res;
buzbee67bf8852011-08-17 17:51:35 -07001060}
1061
buzbee02031b12012-11-23 09:41:35 -08001062LIR* ArmCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -07001063{
buzbee52a77fc2012-11-20 19:50:46 -08001064 LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001065 return NULL;
1066}
buzbee67bf8852011-08-17 17:51:35 -07001067
buzbee02031b12012-11-23 09:41:35 -08001068LIR* ArmCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -07001069{
buzbee52a77fc2012-11-20 19:50:46 -08001070 LOG(FATAL) << "Unexpected use of OpMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001071 return NULL;
1072}
1073
buzbee02031b12012-11-23 09:41:35 -08001074LIR* ArmCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1075 int displacement, int r_src, int r_src_hi, OpSize size,
1076 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001077{
buzbee52a77fc2012-11-20 19:50:46 -08001078 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001079 return NULL;
1080}
1081
buzbee02031b12012-11-23 09:41:35 -08001082LIR* ArmCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, int offset)
buzbeeb046e162012-10-30 15:48:42 -07001083{
buzbee52a77fc2012-11-20 19:50:46 -08001084 LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001085 return NULL;
1086}
1087
buzbee02031b12012-11-23 09:41:35 -08001088LIR* ArmCodegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1089 int displacement, int r_dest, int r_dest_hi, OpSize size,
1090 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001091{
buzbee52a77fc2012-11-20 19:50:46 -08001092 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001093 return NULL;
1094}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001095
1096} // namespace art