blob: 5c25eee87a116b56a1a31245100ca39872771081 [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"
buzbee1bc37c62012-11-20 13:35:41 -080019#include "../codegen_util.h"
20#include "../ralloc_util.h"
21
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
buzbeefa57c472012-11-21 12:06:18 -080048static LIR* LoadFPConstantValue(CompilationUnit* cu, int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -070049{
buzbeefa57c472012-11-21 12:06:18 -080050 DCHECK(ARM_SINGLEREG(r_dest));
buzbee7da142f2012-11-29 16:33:42 -080051 if (value == 0) {
52 // TODO: we need better info about the target CPU. a vector exclusive or
53 // would probably be better here if we could rely on its existance.
54 // Load an immediate +2.0 (which encodes to 0)
55 NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, 0);
56 // +0.0 = +2.0 - +2.0
57 return NewLIR3(cu, kThumb2Vsubs, r_dest, r_dest, r_dest);
58 } else {
59 int encoded_imm = EncodeImmSingle(value);
60 if (encoded_imm >= 0) {
61 return NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, encoded_imm);
62 }
Bill Buzbeea114add2012-05-03 15:00:40 -070063 }
buzbeefa57c472012-11-21 12:06:18 -080064 LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0);
65 if (data_target == NULL) {
66 data_target = AddWordData(cu, &cu->literal_list, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070067 }
buzbeefa57c472012-11-21 12:06:18 -080068 LIR* load_pc_rel = RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrs,
69 r_dest, r15pc, 0, 0, 0, data_target);
buzbee02031b12012-11-23 09:41:35 -080070 SetMemRefType(cu, load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -080071 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
72 AppendLIR(cu, load_pc_rel);
73 return load_pc_rel;
buzbee67bf8852011-08-17 17:51:35 -070074}
75
buzbeeaad94382012-11-21 07:40:50 -080076static int LeadingZeros(uint32_t val)
buzbee67bf8852011-08-17 17:51:35 -070077{
buzbeeeaf09bc2012-11-15 14:51:41 -080078 uint32_t alt;
Bill Buzbeea114add2012-05-03 15:00:40 -070079 int n;
80 int count;
buzbee67bf8852011-08-17 17:51:35 -070081
Bill Buzbeea114add2012-05-03 15:00:40 -070082 count = 16;
83 n = 32;
84 do {
85 alt = val >> count;
86 if (alt != 0) {
87 n = n - count;
88 val = alt;
89 }
90 count >>= 1;
91 } while (count);
92 return n - val;
buzbee67bf8852011-08-17 17:51:35 -070093}
94
95/*
96 * Determine whether value can be encoded as a Thumb2 modified
97 * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
98 */
buzbee02031b12012-11-23 09:41:35 -080099int ArmCodegen::ModifiedImmediate(uint32_t value)
buzbee67bf8852011-08-17 17:51:35 -0700100{
buzbeefa57c472012-11-21 12:06:18 -0800101 int z_leading;
102 int z_trailing;
buzbeeeaf09bc2012-11-15 14:51:41 -0800103 uint32_t b0 = value & 0xff;
buzbee67bf8852011-08-17 17:51:35 -0700104
105 /* Note: case of value==0 must use 0:000:0:0000000 encoding */
106 if (value <= 0xFF)
Bill Buzbeea114add2012-05-03 15:00:40 -0700107 return b0; // 0:000:a:bcdefgh
buzbee67bf8852011-08-17 17:51:35 -0700108 if (value == ((b0 << 16) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700109 return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700110 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700112 b0 = (value >> 8) & 0xff;
113 if (value == ((b0 << 24) | (b0 << 8)))
Bill Buzbeea114add2012-05-03 15:00:40 -0700114 return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700115 /* Can we do it with rotation? */
buzbeefa57c472012-11-21 12:06:18 -0800116 z_leading = LeadingZeros(value);
117 z_trailing = 32 - LeadingZeros(~value & (value - 1));
buzbee67bf8852011-08-17 17:51:35 -0700118 /* A run of eight or fewer active bits? */
buzbeefa57c472012-11-21 12:06:18 -0800119 if ((z_leading + z_trailing) < 24)
Bill Buzbeea114add2012-05-03 15:00:40 -0700120 return -1; /* No - bail */
buzbee67bf8852011-08-17 17:51:35 -0700121 /* left-justify the constant, discarding msb (known to be 1) */
buzbeefa57c472012-11-21 12:06:18 -0800122 value <<= z_leading + 1;
buzbee67bf8852011-08-17 17:51:35 -0700123 /* Create bcdefgh */
124 value >>= 25;
125 /* Put it all together */
buzbeefa57c472012-11-21 12:06:18 -0800126 return value | ((0x8 + z_leading) << 7); /* [01000..11111]:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700127}
128
buzbeee6285f92012-12-06 15:57:46 -0800129bool ArmCodegen::InexpensiveConstant(int reg, int value)
130{
131 bool res = false;
132 if (ARM_FPREG(reg)) {
133 res = (EncodeImmSingle(value) >= 0);
134 } else {
135 if (ARM_LOWREG(reg) && (value >= 0) && (IsUint(8, value))) {
136 res = true;
137 } else {
138 res = (ModifiedImmediate(value) >= 0) || (ModifiedImmediate(~value) >= 0);
139 }
140 }
141 return res;
142}
143
buzbee67bf8852011-08-17 17:51:35 -0700144/*
145 * Load a immediate using a shortcut if possible; otherwise
146 * grab from the per-translation literal pool.
147 *
148 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -0800149 * 1) r_dest is freshly returned from AllocTemp or
buzbee67bf8852011-08-17 17:51:35 -0700150 * 2) The codegen is under fixed register usage
151 */
buzbee02031b12012-11-23 09:41:35 -0800152LIR* ArmCodegen::LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700153{
Bill Buzbeea114add2012-05-03 15:00:40 -0700154 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800155 int mod_imm;
buzbee67bf8852011-08-17 17:51:35 -0700156
buzbeefa57c472012-11-21 12:06:18 -0800157 if (ARM_FPREG(r_dest)) {
158 return LoadFPConstantValue(cu, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 }
buzbee67bf8852011-08-17 17:51:35 -0700160
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 /* See if the value can be constructed cheaply */
buzbeefa57c472012-11-21 12:06:18 -0800162 if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) {
163 return NewLIR2(cu, kThumbMovImm, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 }
165 /* Check Modified immediate special cases */
buzbeefa57c472012-11-21 12:06:18 -0800166 mod_imm = ModifiedImmediate(value);
167 if (mod_imm >= 0) {
168 res = NewLIR2(cu, kThumb2MovImmShift, r_dest, mod_imm);
buzbee67bf8852011-08-17 17:51:35 -0700169 return res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 }
buzbeefa57c472012-11-21 12:06:18 -0800171 mod_imm = ModifiedImmediate(~value);
172 if (mod_imm >= 0) {
173 res = NewLIR2(cu, kThumb2MvnImm12, r_dest, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700174 return res;
175 }
176 /* 16-bit immediate? */
177 if ((value & 0xffff) == value) {
buzbeefa57c472012-11-21 12:06:18 -0800178 res = NewLIR2(cu, kThumb2MovImm16, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700179 return res;
180 }
181 /* No shortcut - go ahead and use literal pool */
buzbeefa57c472012-11-21 12:06:18 -0800182 LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0);
183 if (data_target == NULL) {
184 data_target = AddWordData(cu, &cu->literal_list, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700185 }
buzbeefa57c472012-11-21 12:06:18 -0800186 LIR* load_pc_rel = RawLIR(cu, cu->current_dalvik_offset,
187 kThumb2LdrPcRel12, r_dest, 0, 0, 0, 0, data_target);
buzbee02031b12012-11-23 09:41:35 -0800188 SetMemRefType(cu, load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -0800189 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
190 res = load_pc_rel;
191 AppendLIR(cu, load_pc_rel);
Bill Buzbeea114add2012-05-03 15:00:40 -0700192
193 /*
194 * To save space in the constant pool, we use the ADD_RRI8 instruction to
195 * add up to 255 to an existing constant value.
196 */
buzbeefa57c472012-11-21 12:06:18 -0800197 if (data_target->operands[0] != value) {
198 OpRegImm(cu, kOpAdd, r_dest, value - data_target->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700199 }
200 return res;
buzbee67bf8852011-08-17 17:51:35 -0700201}
202
buzbee02031b12012-11-23 09:41:35 -0800203LIR* ArmCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700204{
buzbee02031b12012-11-23 09:41:35 -0800205 LIR* res = NewLIR1(cu, kThumbBUncond, 0 /* offset to be patched during assembly*/);
206 res->target = target;
207 return res;
buzbee67bf8852011-08-17 17:51:35 -0700208}
209
buzbee02031b12012-11-23 09:41:35 -0800210LIR* ArmCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700211{
buzbeefa57c472012-11-21 12:06:18 -0800212 LIR* branch = NewLIR2(cu, kThumb2BCond, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -0800213 ArmConditionEncoding(cc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700214 branch->target = target;
215 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700216}
217
buzbee02031b12012-11-23 09:41:35 -0800218LIR* ArmCodegen::OpReg(CompilationUnit* cu, OpKind op, int r_dest_src)
buzbee67bf8852011-08-17 17:51:35 -0700219{
Bill Buzbeea114add2012-05-03 15:00:40 -0700220 ArmOpcode opcode = kThumbBkpt;
221 switch (op) {
222 case kOpBlx:
223 opcode = kThumbBlxR;
224 break;
225 default:
buzbeecbd6d442012-11-17 14:11:25 -0800226 LOG(FATAL) << "Bad opcode " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 }
buzbeefa57c472012-11-21 12:06:18 -0800228 return NewLIR1(cu, opcode, r_dest_src);
buzbee67bf8852011-08-17 17:51:35 -0700229}
230
buzbee02031b12012-11-23 09:41:35 -0800231LIR* ArmCodegen::OpRegRegShift(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2,
232 int shift)
buzbee67bf8852011-08-17 17:51:35 -0700233{
buzbeefa57c472012-11-21 12:06:18 -0800234 bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2));
Bill Buzbeea114add2012-05-03 15:00:40 -0700235 ArmOpcode opcode = kThumbBkpt;
236 switch (op) {
237 case kOpAdc:
buzbeefa57c472012-11-21 12:06:18 -0800238 opcode = (thumb_form) ? kThumbAdcRR : kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 break;
240 case kOpAnd:
buzbeefa57c472012-11-21 12:06:18 -0800241 opcode = (thumb_form) ? kThumbAndRR : kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700242 break;
243 case kOpBic:
buzbeefa57c472012-11-21 12:06:18 -0800244 opcode = (thumb_form) ? kThumbBicRR : kThumb2BicRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700245 break;
246 case kOpCmn:
247 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800248 opcode = (thumb_form) ? kThumbCmnRR : kThumb2CmnRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 break;
250 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800251 if (thumb_form)
Bill Buzbeea114add2012-05-03 15:00:40 -0700252 opcode = kThumbCmpRR;
buzbeefa57c472012-11-21 12:06:18 -0800253 else if ((shift == 0) && !ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700254 opcode = kThumbCmpHH;
buzbeefa57c472012-11-21 12:06:18 -0800255 else if ((shift == 0) && ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700256 opcode = kThumbCmpLH;
257 else if (shift == 0)
258 opcode = kThumbCmpHL;
259 else
260 opcode = kThumb2CmpRR;
261 break;
262 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800263 opcode = (thumb_form) ? kThumbEorRR : kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 break;
265 case kOpMov:
266 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800267 if (ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 opcode = kThumbMovRR;
buzbeefa57c472012-11-21 12:06:18 -0800269 else if (!ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700270 opcode = kThumbMovRR_H2H;
buzbeefa57c472012-11-21 12:06:18 -0800271 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700272 opcode = kThumbMovRR_H2L;
273 else
274 opcode = kThumbMovRR_L2H;
275 break;
276 case kOpMul:
277 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800278 opcode = (thumb_form) ? kThumbMul : kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700279 break;
280 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800281 opcode = (thumb_form) ? kThumbMvn : kThumb2MnvRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700282 break;
283 case kOpNeg:
284 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800285 opcode = (thumb_form) ? kThumbNeg : kThumb2NegRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700286 break;
287 case kOpOr:
buzbeefa57c472012-11-21 12:06:18 -0800288 opcode = (thumb_form) ? kThumbOrr : kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700289 break;
290 case kOpSbc:
buzbeefa57c472012-11-21 12:06:18 -0800291 opcode = (thumb_form) ? kThumbSbc : kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 break;
293 case kOpTst:
buzbeefa57c472012-11-21 12:06:18 -0800294 opcode = (thumb_form) ? kThumbTst : kThumb2TstRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700295 break;
296 case kOpLsl:
297 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800298 opcode = (thumb_form) ? kThumbLslRR : kThumb2LslRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 break;
300 case kOpLsr:
301 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800302 opcode = (thumb_form) ? kThumbLsrRR : kThumb2LsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 break;
304 case kOpAsr:
305 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800306 opcode = (thumb_form) ? kThumbAsrRR : kThumb2AsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700307 break;
308 case kOpRor:
309 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800310 opcode = (thumb_form) ? kThumbRorRR : kThumb2RorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700311 break;
312 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800313 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 break;
315 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800316 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 break;
318 case kOp2Byte:
319 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800320 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 8);
Bill Buzbeea114add2012-05-03 15:00:40 -0700321 case kOp2Short:
322 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800323 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700324 case kOp2Char:
325 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800326 return NewLIR4(cu, kThumb2Ubfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700327 default:
buzbeecbd6d442012-11-17 14:11:25 -0800328 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700329 break;
330 }
331 DCHECK_GE(static_cast<int>(opcode), 0);
332 if (EncodingMap[opcode].flags & IS_BINARY_OP)
buzbeefa57c472012-11-21 12:06:18 -0800333 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
buzbeefa57c472012-11-21 12:06:18 -0800335 if (EncodingMap[opcode].field_loc[2].kind == kFmtShift)
336 return NewLIR3(cu, opcode, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 else
buzbeefa57c472012-11-21 12:06:18 -0800338 return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700339 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800340 return NewLIR4(cu, opcode, r_dest_src1, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700341 else {
342 LOG(FATAL) << "Unexpected encoding operand count";
343 return NULL;
344 }
buzbee67bf8852011-08-17 17:51:35 -0700345}
346
buzbee02031b12012-11-23 09:41:35 -0800347LIR* ArmCodegen::OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700348{
buzbeefa57c472012-11-21 12:06:18 -0800349 return OpRegRegShift(cu, op, r_dest_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700350}
351
buzbee02031b12012-11-23 09:41:35 -0800352LIR* ArmCodegen::OpRegRegRegShift(CompilationUnit* cu, OpKind op, int r_dest, int r_src1,
353 int r_src2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700354{
Bill Buzbeea114add2012-05-03 15:00:40 -0700355 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800356 bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1) &&
357 ARM_LOWREG(r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700358 switch (op) {
359 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800360 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700361 break;
362 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800363 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700364 break;
365 case kOpRsub:
366 opcode = kThumb2RsubRRR;
367 break;
368 case kOpAdc:
369 opcode = kThumb2AdcRRR;
370 break;
371 case kOpAnd:
372 opcode = kThumb2AndRRR;
373 break;
374 case kOpBic:
375 opcode = kThumb2BicRRR;
376 break;
377 case kOpXor:
378 opcode = kThumb2EorRRR;
379 break;
380 case kOpMul:
381 DCHECK_EQ(shift, 0);
382 opcode = kThumb2MulRRR;
383 break;
384 case kOpOr:
385 opcode = kThumb2OrrRRR;
386 break;
387 case kOpSbc:
388 opcode = kThumb2SbcRRR;
389 break;
390 case kOpLsl:
391 DCHECK_EQ(shift, 0);
392 opcode = kThumb2LslRRR;
393 break;
394 case kOpLsr:
395 DCHECK_EQ(shift, 0);
396 opcode = kThumb2LsrRRR;
397 break;
398 case kOpAsr:
399 DCHECK_EQ(shift, 0);
400 opcode = kThumb2AsrRRR;
401 break;
402 case kOpRor:
403 DCHECK_EQ(shift, 0);
404 opcode = kThumb2RorRRR;
405 break;
406 default:
buzbeecbd6d442012-11-17 14:11:25 -0800407 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700408 break;
409 }
410 DCHECK_GE(static_cast<int>(opcode), 0);
411 if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800412 return NewLIR4(cu, opcode, r_dest, r_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700413 else {
414 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
buzbeefa57c472012-11-21 12:06:18 -0800415 return NewLIR3(cu, opcode, r_dest, r_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700416 }
buzbee67bf8852011-08-17 17:51:35 -0700417}
418
buzbee02031b12012-11-23 09:41:35 -0800419LIR* ArmCodegen::OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700420{
buzbeefa57c472012-11-21 12:06:18 -0800421 return OpRegRegRegShift(cu, op, r_dest, r_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700422}
423
buzbee02031b12012-11-23 09:41:35 -0800424LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700425{
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 LIR* res;
427 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800428 int abs_value = (neg) ? -value : value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800430 ArmOpcode alt_opcode = kThumbBkpt;
431 bool all_low_regs = (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1));
432 int mod_imm = ModifiedImmediate(value);
433 int mod_imm_neg = ModifiedImmediate(-value);
buzbee67bf8852011-08-17 17:51:35 -0700434
Bill Buzbeea114add2012-05-03 15:00:40 -0700435 switch (op) {
436 case kOpLsl:
buzbeefa57c472012-11-21 12:06:18 -0800437 if (all_low_regs)
438 return NewLIR3(cu, kThumbLslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700439 else
buzbeefa57c472012-11-21 12:06:18 -0800440 return NewLIR3(cu, kThumb2LslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700441 case kOpLsr:
buzbeefa57c472012-11-21 12:06:18 -0800442 if (all_low_regs)
443 return NewLIR3(cu, kThumbLsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700444 else
buzbeefa57c472012-11-21 12:06:18 -0800445 return NewLIR3(cu, kThumb2LsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 case kOpAsr:
buzbeefa57c472012-11-21 12:06:18 -0800447 if (all_low_regs)
448 return NewLIR3(cu, kThumbAsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 else
buzbeefa57c472012-11-21 12:06:18 -0800450 return NewLIR3(cu, kThumb2AsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 case kOpRor:
buzbeefa57c472012-11-21 12:06:18 -0800452 return NewLIR3(cu, kThumb2RorRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800454 if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800456 return NewLIR3(cu, kThumbAddSpRel, r_dest, r_src1, value >> 2);
457 } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700458 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800459 return NewLIR3(cu, kThumbAddPcRel, r_dest, r_src1, value >> 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 }
461 // Note: intentional fallthrough
462 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800463 if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 if (op == kOpAdd)
465 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
buzbee67bf8852011-08-17 17:51:35 -0700466 else
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
buzbeefa57c472012-11-21 12:06:18 -0800468 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
469 } else if ((abs_value & 0xff) == abs_value) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700470 if (op == kOpAdd)
471 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
472 else
473 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
buzbeefa57c472012-11-21 12:06:18 -0800474 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700475 }
buzbeefa57c472012-11-21 12:06:18 -0800476 if (mod_imm_neg >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700477 op = (op == kOpAdd) ? kOpSub : kOpAdd;
buzbeefa57c472012-11-21 12:06:18 -0800478 mod_imm = mod_imm_neg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 }
480 if (op == kOpSub) {
481 opcode = kThumb2SubRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800482 alt_opcode = kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 } else {
484 opcode = kThumb2AddRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800485 alt_opcode = kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700486 }
487 break;
488 case kOpAdc:
489 opcode = kThumb2AdcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800490 alt_opcode = kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 break;
492 case kOpSbc:
493 opcode = kThumb2SbcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800494 alt_opcode = kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700495 break;
496 case kOpOr:
497 opcode = kThumb2OrrRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800498 alt_opcode = kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 break;
500 case kOpAnd:
501 opcode = kThumb2AndRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800502 alt_opcode = kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 break;
504 case kOpXor:
505 opcode = kThumb2EorRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800506 alt_opcode = kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700507 break;
508 case kOpMul:
509 //TUNING: power of 2, shift & add
buzbeefa57c472012-11-21 12:06:18 -0800510 mod_imm = -1;
511 alt_opcode = kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700512 break;
513 case kOpCmp: {
buzbeefa57c472012-11-21 12:06:18 -0800514 int mod_imm = ModifiedImmediate(value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700515 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800516 if (mod_imm >= 0) {
517 res = NewLIR2(cu, kThumb2CmpRI8, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700518 } else {
buzbeefa57c472012-11-21 12:06:18 -0800519 int r_tmp = AllocTemp(cu);
520 res = LoadConstant(cu, r_tmp, value);
521 OpRegReg(cu, kOpCmp, r_src1, r_tmp);
522 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 }
524 return res;
buzbee67bf8852011-08-17 17:51:35 -0700525 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 default:
buzbeecbd6d442012-11-17 14:11:25 -0800527 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700528 }
529
buzbeefa57c472012-11-21 12:06:18 -0800530 if (mod_imm >= 0) {
531 return NewLIR3(cu, opcode, r_dest, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700532 } else {
buzbeefa57c472012-11-21 12:06:18 -0800533 int r_scratch = AllocTemp(cu);
534 LoadConstant(cu, r_scratch, value);
535 if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
536 res = NewLIR4(cu, alt_opcode, r_dest, r_src1, r_scratch, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700537 else
buzbeefa57c472012-11-21 12:06:18 -0800538 res = NewLIR3(cu, alt_opcode, r_dest, r_src1, r_scratch);
539 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700540 return res;
541 }
buzbee67bf8852011-08-17 17:51:35 -0700542}
543
buzbee52a77fc2012-11-20 19:50:46 -0800544/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
buzbee02031b12012-11-23 09:41:35 -0800545LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700546{
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800548 int abs_value = (neg) ? -value : value;
549 bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 ArmOpcode opcode = kThumbBkpt;
551 switch (op) {
552 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800553 if ( !neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700554 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800555 return NewLIR1(cu, kThumbAddSpI7, value >> 2);
556 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
558 }
559 break;
560 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800561 if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700562 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800563 return NewLIR1(cu, kThumbSubSpI7, value >> 2);
564 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700565 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
566 }
567 break;
568 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800569 if (ARM_LOWREG(r_dest_src1) && short_form)
570 opcode = (short_form) ? kThumbCmpRI8 : kThumbCmpRR;
571 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 opcode = kThumbCmpRR;
573 else {
buzbeefa57c472012-11-21 12:06:18 -0800574 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700575 opcode = kThumbCmpHL;
576 }
577 break;
578 default:
buzbee52a77fc2012-11-20 19:50:46 -0800579 /* Punt to OpRegRegImm - if bad case catch it there */
buzbeefa57c472012-11-21 12:06:18 -0800580 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700581 break;
582 }
buzbeefa57c472012-11-21 12:06:18 -0800583 if (short_form)
584 return NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700585 else {
buzbeefa57c472012-11-21 12:06:18 -0800586 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700587 }
buzbee67bf8852011-08-17 17:51:35 -0700588}
589
590/*
591 * Determine whether value can be encoded as a Thumb2 floating point
592 * immediate. If not, return -1. If so return encoded 8-bit value.
593 */
buzbeeaad94382012-11-21 07:40:50 -0800594static int EncodeImmDoubleHigh(int value)
buzbee67bf8852011-08-17 17:51:35 -0700595{
Bill Buzbeea114add2012-05-03 15:00:40 -0700596 int res;
buzbeefa57c472012-11-21 12:06:18 -0800597 int bit_a = (value & 0x80000000) >> 31;
598 int not_bit_b = (value & 0x40000000) >> 30;
599 int bit_b = (value & 0x20000000) >> 29;
600 int b_smear = (value & 0x3fc00000) >> 22;
Bill Buzbeea114add2012-05-03 15:00:40 -0700601 int slice = (value & 0x003f0000) >> 16;
602 int zeroes = (value & 0x0000ffff);
603 if (zeroes != 0)
604 return -1;
buzbeefa57c472012-11-21 12:06:18 -0800605 if (bit_b) {
606 if ((not_bit_b != 0) || (b_smear != 0xff))
Bill Buzbeea114add2012-05-03 15:00:40 -0700607 return -1;
608 } else {
buzbeefa57c472012-11-21 12:06:18 -0800609 if ((not_bit_b != 1) || (b_smear != 0x0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700610 return -1;
611 }
buzbeefa57c472012-11-21 12:06:18 -0800612 res = (bit_a << 7) | (bit_b << 6) | slice;
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 return res;
buzbee67bf8852011-08-17 17:51:35 -0700614}
615
buzbeefa57c472012-11-21 12:06:18 -0800616static int EncodeImmDouble(int val_lo, int val_hi)
buzbee67bf8852011-08-17 17:51:35 -0700617{
Bill Buzbeea114add2012-05-03 15:00:40 -0700618 int res = -1;
buzbeefa57c472012-11-21 12:06:18 -0800619 if (val_lo == 0)
620 res = EncodeImmDoubleHigh(val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700621 return res;
buzbee67bf8852011-08-17 17:51:35 -0700622}
623
buzbee02031b12012-11-23 09:41:35 -0800624LIR* ArmCodegen::LoadConstantValueWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi,
625 int val_lo, int val_hi)
buzbee67bf8852011-08-17 17:51:35 -0700626{
Bill Buzbeea114add2012-05-03 15:00:40 -0700627 LIR* res;
buzbee7da142f2012-11-29 16:33:42 -0800628 int target_reg = S2d(r_dest_lo, r_dest_hi);
buzbeefa57c472012-11-21 12:06:18 -0800629 if (ARM_FPREG(r_dest_lo)) {
buzbee7da142f2012-11-29 16:33:42 -0800630 if ((val_lo == 0) && (val_hi == 0)) {
631 // TODO: we need better info about the target CPU. a vector exclusive or
632 // would probably be better here if we could rely on its existance.
633 // Load an immediate +2.0 (which encodes to 0)
634 NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, 0);
635 // +0.0 = +2.0 - +2.0
636 res = NewLIR3(cu, kThumb2Vsubd, target_reg, target_reg, target_reg);
buzbee67bf8852011-08-17 17:51:35 -0700637 } else {
buzbee7da142f2012-11-29 16:33:42 -0800638 int encoded_imm = EncodeImmDouble(val_lo, val_hi);
639 if (encoded_imm >= 0) {
640 res = NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, encoded_imm);
641 } else {
642 LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi);
643 if (data_target == NULL) {
644 data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi);
645 }
646 LIR* load_pc_rel =
647 RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd,
648 target_reg, r15pc, 0, 0, 0, data_target);
649 SetMemRefType(cu, load_pc_rel, true, kLiteral);
650 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
651 AppendLIR(cu, load_pc_rel);
652 res = load_pc_rel;
Bill Buzbeea114add2012-05-03 15:00:40 -0700653 }
buzbee67bf8852011-08-17 17:51:35 -0700654 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 } else {
buzbeefa57c472012-11-21 12:06:18 -0800656 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
657 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700658 }
659 return res;
buzbee67bf8852011-08-17 17:51:35 -0700660}
661
buzbee02031b12012-11-23 09:41:35 -0800662int ArmCodegen::EncodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700664}
665
buzbee02031b12012-11-23 09:41:35 -0800666LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest,
667 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700668{
buzbeefa57c472012-11-21 12:06:18 -0800669 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700670 LIR* load;
671 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800672 bool thumb_form = (all_low_regs && (scale == 0));
673 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700674
buzbeefa57c472012-11-21 12:06:18 -0800675 if (ARM_FPREG(r_dest)) {
676 if (ARM_SINGLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 DCHECK((size == kWord) || (size == kSingle));
678 opcode = kThumb2Vldrs;
679 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700680 } else {
buzbeefa57c472012-11-21 12:06:18 -0800681 DCHECK(ARM_DOUBLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700682 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800683 DCHECK_EQ((r_dest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 opcode = kThumb2Vldrd;
685 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700686 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700687 } else {
688 if (size == kSingle)
689 size = kWord;
690 }
buzbee67bf8852011-08-17 17:51:35 -0700691
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 switch (size) {
693 case kDouble: // fall-through
694 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800695 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700696 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800697 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800698 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700699 } else {
buzbeefa57c472012-11-21 12:06:18 -0800700 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700701 }
buzbeefa57c472012-11-21 12:06:18 -0800702 load = NewLIR3(cu, opcode, r_dest, reg_ptr, 0);
703 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 return load;
705 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800706 opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700707 break;
708 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800709 opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 break;
711 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800712 opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700713 break;
714 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800715 opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700716 break;
717 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800718 opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700719 break;
720 default:
buzbeecbd6d442012-11-17 14:11:25 -0800721 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700722 }
buzbeefa57c472012-11-21 12:06:18 -0800723 if (thumb_form)
724 load = NewLIR3(cu, opcode, r_dest, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700725 else
buzbeefa57c472012-11-21 12:06:18 -0800726 load = NewLIR4(cu, opcode, r_dest, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700727
Bill Buzbeea114add2012-05-03 15:00:40 -0700728 return load;
buzbee67bf8852011-08-17 17:51:35 -0700729}
730
buzbee02031b12012-11-23 09:41:35 -0800731LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src,
732 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700733{
buzbeefa57c472012-11-21 12:06:18 -0800734 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700735 LIR* store;
736 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800737 bool thumb_form = (all_low_regs && (scale == 0));
738 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700739
buzbeefa57c472012-11-21 12:06:18 -0800740 if (ARM_FPREG(r_src)) {
741 if (ARM_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700742 DCHECK((size == kWord) || (size == kSingle));
743 opcode = kThumb2Vstrs;
744 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700745 } else {
buzbeefa57c472012-11-21 12:06:18 -0800746 DCHECK(ARM_DOUBLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700747 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800748 DCHECK_EQ((r_src & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 opcode = kThumb2Vstrd;
750 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700751 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700752 } else {
753 if (size == kSingle)
754 size = kWord;
755 }
buzbee67bf8852011-08-17 17:51:35 -0700756
Bill Buzbeea114add2012-05-03 15:00:40 -0700757 switch (size) {
758 case kDouble: // fall-through
759 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800760 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800762 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800763 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700764 } else {
buzbeefa57c472012-11-21 12:06:18 -0800765 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700766 }
buzbeefa57c472012-11-21 12:06:18 -0800767 store = NewLIR3(cu, opcode, r_src, reg_ptr, 0);
768 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700769 return store;
770 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800771 opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700772 break;
773 case kUnsignedHalf:
774 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800775 opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700776 break;
777 case kUnsignedByte:
778 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800779 opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700780 break;
781 default:
buzbeecbd6d442012-11-17 14:11:25 -0800782 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700783 }
buzbeefa57c472012-11-21 12:06:18 -0800784 if (thumb_form)
785 store = NewLIR3(cu, opcode, r_src, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700786 else
buzbeefa57c472012-11-21 12:06:18 -0800787 store = NewLIR4(cu, opcode, r_src, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700788
Bill Buzbeea114add2012-05-03 15:00:40 -0700789 return store;
buzbee67bf8852011-08-17 17:51:35 -0700790}
791
792/*
793 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800794 * on base (which must have an associated s_reg and MIR). If not
buzbee67bf8852011-08-17 17:51:35 -0700795 * performing null check, incoming MIR can be null.
796 */
buzbee02031b12012-11-23 09:41:35 -0800797LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest,
798 int r_dest_hi, OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700799{
buzbee02031b12012-11-23 09:41:35 -0800800 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700801 LIR* res;
802 LIR* load;
803 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800804 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700805 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800806 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
807 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700808 bool is64bit = false;
809 switch (size) {
810 case kDouble:
811 case kLong:
812 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800813 if (ARM_FPREG(r_dest)) {
814 if (ARM_SINGLEREG(r_dest)) {
815 DCHECK(ARM_FPREG(r_dest_hi));
buzbee02031b12012-11-23 09:41:35 -0800816 r_dest = cg->S2d(r_dest, r_dest_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700817 }
818 opcode = kThumb2Vldrd;
819 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800820 short_form = true;
821 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700822 }
823 break;
824 } else {
buzbeefa57c472012-11-21 12:06:18 -0800825 res = LoadBaseDispBody(cu, rBase, displacement, r_dest,
826 -1, kWord, s_reg);
827 LoadBaseDispBody(cu, rBase, displacement + 4, r_dest_hi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700828 -1, kWord, INVALID_SREG);
829 return res;
830 }
831 case kSingle:
832 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800833 if (ARM_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700834 opcode = kThumb2Vldrs;
835 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800836 short_form = true;
837 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700838 }
839 break;
840 }
buzbeefa57c472012-11-21 12:06:18 -0800841 if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800843 short_form = true;
844 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700845 opcode = kThumbLdrPcRel;
buzbeefa57c472012-11-21 12:06:18 -0800846 } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700847 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800848 short_form = true;
849 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700850 opcode = kThumbLdrSpRel;
buzbeefa57c472012-11-21 12:06:18 -0800851 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700852 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800853 short_form = true;
854 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700855 opcode = kThumbLdrRRI5;
856 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800857 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700858 opcode = kThumb2LdrRRI12;
859 }
860 break;
861 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800862 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700863 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800864 short_form = true;
865 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 opcode = kThumbLdrhRRI5;
867 } else if (displacement < 4092 && displacement >= 0) {
buzbeefa57c472012-11-21 12:06:18 -0800868 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 opcode = kThumb2LdrhRRI12;
870 }
871 break;
872 case kSignedHalf:
873 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800874 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 opcode = kThumb2LdrshRRI12;
876 }
877 break;
878 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800879 if (all_low_regs && displacement < 32 && displacement >= 0) {
880 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700881 opcode = kThumbLdrbRRI5;
882 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800883 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700884 opcode = kThumb2LdrbRRI12;
885 }
886 break;
887 case kSignedByte:
888 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800889 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700890 opcode = kThumb2LdrsbRRI12;
891 }
892 break;
893 default:
buzbeecbd6d442012-11-17 14:11:25 -0800894 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700895 }
buzbee67bf8852011-08-17 17:51:35 -0700896
buzbeefa57c472012-11-21 12:06:18 -0800897 if (short_form) {
898 load = res = NewLIR3(cu, opcode, r_dest, rBase, encoded_disp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 } else {
buzbeefa57c472012-11-21 12:06:18 -0800900 int reg_offset = AllocTemp(cu);
buzbee02031b12012-11-23 09:41:35 -0800901 res = cg->LoadConstant(cu, reg_offset, encoded_disp);
902 load = cg->LoadBaseIndexed(cu, rBase, reg_offset, r_dest, 0, size);
buzbeefa57c472012-11-21 12:06:18 -0800903 FreeTemp(cu, reg_offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700904 }
buzbee67bf8852011-08-17 17:51:35 -0700905
Bill Buzbeea114add2012-05-03 15:00:40 -0700906 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800907 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -0800908 AnnotateDalvikRegAccess(cu, load, displacement >> 2, true /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700909 }
910 return load;
buzbee67bf8852011-08-17 17:51:35 -0700911}
912
buzbee02031b12012-11-23 09:41:35 -0800913LIR* ArmCodegen::LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest,
914 OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700915{
buzbee02031b12012-11-23 09:41:35 -0800916 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1, size, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700917}
918
buzbee02031b12012-11-23 09:41:35 -0800919LIR* ArmCodegen::LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo,
920 int r_dest_hi, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700921{
buzbee02031b12012-11-23 09:41:35 -0800922 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700923}
924
925
buzbee02031b12012-11-23 09:41:35 -0800926LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement,
927 int r_src, int r_src_hi, OpSize size) {
928 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700929 LIR* res, *store;
930 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800931 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700932 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800933 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
934 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700935 bool is64bit = false;
936 switch (size) {
937 case kLong:
938 case kDouble:
939 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800940 if (!ARM_FPREG(r_src)) {
941 res = StoreBaseDispBody(cu, rBase, displacement, r_src, -1, kWord);
942 StoreBaseDispBody(cu, rBase, displacement + 4, r_src_hi, -1, kWord);
Bill Buzbeea114add2012-05-03 15:00:40 -0700943 return res;
944 }
buzbeefa57c472012-11-21 12:06:18 -0800945 if (ARM_SINGLEREG(r_src)) {
946 DCHECK(ARM_FPREG(r_src_hi));
buzbee02031b12012-11-23 09:41:35 -0800947 r_src = cg->S2d(r_src, r_src_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700948 }
949 opcode = kThumb2Vstrd;
950 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800951 short_form = true;
952 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700953 }
954 break;
955 case kSingle:
956 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800957 if (ARM_FPREG(r_src)) {
958 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700959 opcode = kThumb2Vstrs;
960 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800961 short_form = true;
962 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700963 }
964 break;
965 }
buzbeefa57c472012-11-21 12:06:18 -0800966 if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700967 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800968 short_form = true;
969 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 opcode = kThumbStrRRI5;
971 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800972 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700973 opcode = kThumb2StrRRI12;
974 }
975 break;
976 case kUnsignedHalf:
977 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800978 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700979 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800980 short_form = true;
981 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700982 opcode = kThumbStrhRRI5;
983 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800984 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 opcode = kThumb2StrhRRI12;
986 }
987 break;
988 case kUnsignedByte:
989 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800990 if (all_low_regs && displacement < 32 && displacement >= 0) {
991 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700992 opcode = kThumbStrbRRI5;
993 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800994 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 opcode = kThumb2StrbRRI12;
996 }
997 break;
998 default:
buzbeecbd6d442012-11-17 14:11:25 -0800999 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -07001000 }
buzbeefa57c472012-11-21 12:06:18 -08001001 if (short_form) {
1002 store = res = NewLIR3(cu, opcode, r_src, rBase, encoded_disp);
Bill Buzbeea114add2012-05-03 15:00:40 -07001003 } else {
buzbeefa57c472012-11-21 12:06:18 -08001004 int r_scratch = AllocTemp(cu);
buzbee02031b12012-11-23 09:41:35 -08001005 res = cg->LoadConstant(cu, r_scratch, encoded_disp);
1006 store = cg->StoreBaseIndexed(cu, rBase, r_scratch, r_src, 0, size);
buzbeefa57c472012-11-21 12:06:18 -08001007 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -07001008 }
buzbee67bf8852011-08-17 17:51:35 -07001009
Bill Buzbeea114add2012-05-03 15:00:40 -07001010 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -08001011 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -08001012 AnnotateDalvikRegAccess(cu, store, displacement >> 2, false /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -07001013 }
1014 return res;
buzbee67bf8852011-08-17 17:51:35 -07001015}
1016
buzbee02031b12012-11-23 09:41:35 -08001017LIR* ArmCodegen::StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src,
1018 OpSize size)
buzbee67bf8852011-08-17 17:51:35 -07001019{
buzbeefa57c472012-11-21 12:06:18 -08001020 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbee67bf8852011-08-17 17:51:35 -07001021}
1022
buzbee02031b12012-11-23 09:41:35 -08001023LIR* ArmCodegen::StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement,
1024 int r_src_lo, int r_src_hi)
buzbee67bf8852011-08-17 17:51:35 -07001025{
buzbeefa57c472012-11-21 12:06:18 -08001026 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbee67bf8852011-08-17 17:51:35 -07001027}
1028
buzbee02031b12012-11-23 09:41:35 -08001029LIR* ArmCodegen::OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src)
buzbee67bf8852011-08-17 17:51:35 -07001030{
Bill Buzbeea114add2012-05-03 15:00:40 -07001031 int opcode;
buzbeefa57c472012-11-21 12:06:18 -08001032 DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
1033 if (ARM_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001034 opcode = kThumb2Vmovd;
1035 } else {
buzbeefa57c472012-11-21 12:06:18 -08001036 if (ARM_SINGLEREG(r_dest)) {
1037 opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001038 } else {
buzbeefa57c472012-11-21 12:06:18 -08001039 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -07001040 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001041 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001042 }
buzbeefa57c472012-11-21 12:06:18 -08001043 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
1044 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
1045 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001046 }
1047 return res;
buzbee67bf8852011-08-17 17:51:35 -07001048}
1049
buzbee02031b12012-11-23 09:41:35 -08001050LIR* ArmCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -07001051{
buzbee52a77fc2012-11-20 19:50:46 -08001052 LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001053 return NULL;
1054}
buzbee67bf8852011-08-17 17:51:35 -07001055
buzbee02031b12012-11-23 09:41:35 -08001056LIR* ArmCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -07001057{
buzbee52a77fc2012-11-20 19:50:46 -08001058 LOG(FATAL) << "Unexpected use of OpMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001059 return NULL;
1060}
1061
buzbee02031b12012-11-23 09:41:35 -08001062LIR* ArmCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1063 int displacement, int r_src, int r_src_hi, OpSize size,
1064 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001065{
buzbee52a77fc2012-11-20 19:50:46 -08001066 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001067 return NULL;
1068}
1069
buzbee02031b12012-11-23 09:41:35 -08001070LIR* ArmCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, int offset)
buzbeeb046e162012-10-30 15:48:42 -07001071{
buzbee52a77fc2012-11-20 19:50:46 -08001072 LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001073 return NULL;
1074}
1075
buzbee02031b12012-11-23 09:41:35 -08001076LIR* ArmCodegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1077 int displacement, int r_dest, int r_dest_hi, OpSize size,
1078 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001079{
buzbee52a77fc2012-11-20 19:50:46 -08001080 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001081 return NULL;
1082}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001083
1084} // namespace art