blob: 7f37bea1afaccf280ee70df19c484ba50522bffa [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
129/*
130 * Load a immediate using a shortcut if possible; otherwise
131 * grab from the per-translation literal pool.
132 *
133 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -0800134 * 1) r_dest is freshly returned from AllocTemp or
buzbee67bf8852011-08-17 17:51:35 -0700135 * 2) The codegen is under fixed register usage
136 */
buzbee02031b12012-11-23 09:41:35 -0800137LIR* ArmCodegen::LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700138{
Bill Buzbeea114add2012-05-03 15:00:40 -0700139 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800140 int mod_imm;
buzbee67bf8852011-08-17 17:51:35 -0700141
buzbeefa57c472012-11-21 12:06:18 -0800142 if (ARM_FPREG(r_dest)) {
143 return LoadFPConstantValue(cu, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700144 }
buzbee67bf8852011-08-17 17:51:35 -0700145
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 /* See if the value can be constructed cheaply */
buzbeefa57c472012-11-21 12:06:18 -0800147 if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) {
148 return NewLIR2(cu, kThumbMovImm, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700149 }
150 /* Check Modified immediate special cases */
buzbeefa57c472012-11-21 12:06:18 -0800151 mod_imm = ModifiedImmediate(value);
152 if (mod_imm >= 0) {
153 res = NewLIR2(cu, kThumb2MovImmShift, r_dest, mod_imm);
buzbee67bf8852011-08-17 17:51:35 -0700154 return res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 }
buzbeefa57c472012-11-21 12:06:18 -0800156 mod_imm = ModifiedImmediate(~value);
157 if (mod_imm >= 0) {
158 res = NewLIR2(cu, kThumb2MvnImm12, r_dest, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 return res;
160 }
161 /* 16-bit immediate? */
162 if ((value & 0xffff) == value) {
buzbeefa57c472012-11-21 12:06:18 -0800163 res = NewLIR2(cu, kThumb2MovImm16, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700164 return res;
165 }
166 /* No shortcut - go ahead and use literal pool */
buzbeefa57c472012-11-21 12:06:18 -0800167 LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0);
168 if (data_target == NULL) {
169 data_target = AddWordData(cu, &cu->literal_list, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700170 }
buzbeefa57c472012-11-21 12:06:18 -0800171 LIR* load_pc_rel = RawLIR(cu, cu->current_dalvik_offset,
172 kThumb2LdrPcRel12, r_dest, 0, 0, 0, 0, data_target);
buzbee02031b12012-11-23 09:41:35 -0800173 SetMemRefType(cu, load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -0800174 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
175 res = load_pc_rel;
176 AppendLIR(cu, load_pc_rel);
Bill Buzbeea114add2012-05-03 15:00:40 -0700177
178 /*
179 * To save space in the constant pool, we use the ADD_RRI8 instruction to
180 * add up to 255 to an existing constant value.
181 */
buzbeefa57c472012-11-21 12:06:18 -0800182 if (data_target->operands[0] != value) {
183 OpRegImm(cu, kOpAdd, r_dest, value - data_target->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700184 }
185 return res;
buzbee67bf8852011-08-17 17:51:35 -0700186}
187
buzbee02031b12012-11-23 09:41:35 -0800188LIR* ArmCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700189{
buzbee02031b12012-11-23 09:41:35 -0800190 LIR* res = NewLIR1(cu, kThumbBUncond, 0 /* offset to be patched during assembly*/);
191 res->target = target;
192 return res;
buzbee67bf8852011-08-17 17:51:35 -0700193}
194
buzbee02031b12012-11-23 09:41:35 -0800195LIR* ArmCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700196{
buzbeefa57c472012-11-21 12:06:18 -0800197 LIR* branch = NewLIR2(cu, kThumb2BCond, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -0800198 ArmConditionEncoding(cc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700199 branch->target = target;
200 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700201}
202
buzbee02031b12012-11-23 09:41:35 -0800203LIR* ArmCodegen::OpReg(CompilationUnit* cu, OpKind op, int r_dest_src)
buzbee67bf8852011-08-17 17:51:35 -0700204{
Bill Buzbeea114add2012-05-03 15:00:40 -0700205 ArmOpcode opcode = kThumbBkpt;
206 switch (op) {
207 case kOpBlx:
208 opcode = kThumbBlxR;
209 break;
210 default:
buzbeecbd6d442012-11-17 14:11:25 -0800211 LOG(FATAL) << "Bad opcode " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700212 }
buzbeefa57c472012-11-21 12:06:18 -0800213 return NewLIR1(cu, opcode, r_dest_src);
buzbee67bf8852011-08-17 17:51:35 -0700214}
215
buzbee02031b12012-11-23 09:41:35 -0800216LIR* ArmCodegen::OpRegRegShift(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2,
217 int shift)
buzbee67bf8852011-08-17 17:51:35 -0700218{
buzbeefa57c472012-11-21 12:06:18 -0800219 bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2));
Bill Buzbeea114add2012-05-03 15:00:40 -0700220 ArmOpcode opcode = kThumbBkpt;
221 switch (op) {
222 case kOpAdc:
buzbeefa57c472012-11-21 12:06:18 -0800223 opcode = (thumb_form) ? kThumbAdcRR : kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700224 break;
225 case kOpAnd:
buzbeefa57c472012-11-21 12:06:18 -0800226 opcode = (thumb_form) ? kThumbAndRR : kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700227 break;
228 case kOpBic:
buzbeefa57c472012-11-21 12:06:18 -0800229 opcode = (thumb_form) ? kThumbBicRR : kThumb2BicRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700230 break;
231 case kOpCmn:
232 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800233 opcode = (thumb_form) ? kThumbCmnRR : kThumb2CmnRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700234 break;
235 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800236 if (thumb_form)
Bill Buzbeea114add2012-05-03 15:00:40 -0700237 opcode = kThumbCmpRR;
buzbeefa57c472012-11-21 12:06:18 -0800238 else if ((shift == 0) && !ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700239 opcode = kThumbCmpHH;
buzbeefa57c472012-11-21 12:06:18 -0800240 else if ((shift == 0) && ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700241 opcode = kThumbCmpLH;
242 else if (shift == 0)
243 opcode = kThumbCmpHL;
244 else
245 opcode = kThumb2CmpRR;
246 break;
247 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800248 opcode = (thumb_form) ? kThumbEorRR : kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700249 break;
250 case kOpMov:
251 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800252 if (ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700253 opcode = kThumbMovRR;
buzbeefa57c472012-11-21 12:06:18 -0800254 else if (!ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 opcode = kThumbMovRR_H2H;
buzbeefa57c472012-11-21 12:06:18 -0800256 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 opcode = kThumbMovRR_H2L;
258 else
259 opcode = kThumbMovRR_L2H;
260 break;
261 case kOpMul:
262 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800263 opcode = (thumb_form) ? kThumbMul : kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 break;
265 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800266 opcode = (thumb_form) ? kThumbMvn : kThumb2MnvRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700267 break;
268 case kOpNeg:
269 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800270 opcode = (thumb_form) ? kThumbNeg : kThumb2NegRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 break;
272 case kOpOr:
buzbeefa57c472012-11-21 12:06:18 -0800273 opcode = (thumb_form) ? kThumbOrr : kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700274 break;
275 case kOpSbc:
buzbeefa57c472012-11-21 12:06:18 -0800276 opcode = (thumb_form) ? kThumbSbc : kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700277 break;
278 case kOpTst:
buzbeefa57c472012-11-21 12:06:18 -0800279 opcode = (thumb_form) ? kThumbTst : kThumb2TstRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700280 break;
281 case kOpLsl:
282 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800283 opcode = (thumb_form) ? kThumbLslRR : kThumb2LslRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 break;
285 case kOpLsr:
286 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800287 opcode = (thumb_form) ? kThumbLsrRR : kThumb2LsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700288 break;
289 case kOpAsr:
290 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800291 opcode = (thumb_form) ? kThumbAsrRR : kThumb2AsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700292 break;
293 case kOpRor:
294 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800295 opcode = (thumb_form) ? kThumbRorRR : kThumb2RorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700296 break;
297 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800298 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700299 break;
300 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800301 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700302 break;
303 case kOp2Byte:
304 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800305 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 8);
Bill Buzbeea114add2012-05-03 15:00:40 -0700306 case kOp2Short:
307 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800308 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700309 case kOp2Char:
310 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800311 return NewLIR4(cu, kThumb2Ubfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700312 default:
buzbeecbd6d442012-11-17 14:11:25 -0800313 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700314 break;
315 }
316 DCHECK_GE(static_cast<int>(opcode), 0);
317 if (EncodingMap[opcode].flags & IS_BINARY_OP)
buzbeefa57c472012-11-21 12:06:18 -0800318 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700319 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
buzbeefa57c472012-11-21 12:06:18 -0800320 if (EncodingMap[opcode].field_loc[2].kind == kFmtShift)
321 return NewLIR3(cu, opcode, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700322 else
buzbeefa57c472012-11-21 12:06:18 -0800323 return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700324 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800325 return NewLIR4(cu, opcode, r_dest_src1, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700326 else {
327 LOG(FATAL) << "Unexpected encoding operand count";
328 return NULL;
329 }
buzbee67bf8852011-08-17 17:51:35 -0700330}
331
buzbee02031b12012-11-23 09:41:35 -0800332LIR* ArmCodegen::OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700333{
buzbeefa57c472012-11-21 12:06:18 -0800334 return OpRegRegShift(cu, op, r_dest_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700335}
336
buzbee02031b12012-11-23 09:41:35 -0800337LIR* ArmCodegen::OpRegRegRegShift(CompilationUnit* cu, OpKind op, int r_dest, int r_src1,
338 int r_src2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700339{
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800341 bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1) &&
342 ARM_LOWREG(r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700343 switch (op) {
344 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800345 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700346 break;
347 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800348 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700349 break;
350 case kOpRsub:
351 opcode = kThumb2RsubRRR;
352 break;
353 case kOpAdc:
354 opcode = kThumb2AdcRRR;
355 break;
356 case kOpAnd:
357 opcode = kThumb2AndRRR;
358 break;
359 case kOpBic:
360 opcode = kThumb2BicRRR;
361 break;
362 case kOpXor:
363 opcode = kThumb2EorRRR;
364 break;
365 case kOpMul:
366 DCHECK_EQ(shift, 0);
367 opcode = kThumb2MulRRR;
368 break;
369 case kOpOr:
370 opcode = kThumb2OrrRRR;
371 break;
372 case kOpSbc:
373 opcode = kThumb2SbcRRR;
374 break;
375 case kOpLsl:
376 DCHECK_EQ(shift, 0);
377 opcode = kThumb2LslRRR;
378 break;
379 case kOpLsr:
380 DCHECK_EQ(shift, 0);
381 opcode = kThumb2LsrRRR;
382 break;
383 case kOpAsr:
384 DCHECK_EQ(shift, 0);
385 opcode = kThumb2AsrRRR;
386 break;
387 case kOpRor:
388 DCHECK_EQ(shift, 0);
389 opcode = kThumb2RorRRR;
390 break;
391 default:
buzbeecbd6d442012-11-17 14:11:25 -0800392 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700393 break;
394 }
395 DCHECK_GE(static_cast<int>(opcode), 0);
396 if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800397 return NewLIR4(cu, opcode, r_dest, r_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700398 else {
399 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
buzbeefa57c472012-11-21 12:06:18 -0800400 return NewLIR3(cu, opcode, r_dest, r_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700401 }
buzbee67bf8852011-08-17 17:51:35 -0700402}
403
buzbee02031b12012-11-23 09:41:35 -0800404LIR* ArmCodegen::OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700405{
buzbeefa57c472012-11-21 12:06:18 -0800406 return OpRegRegRegShift(cu, op, r_dest, r_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700407}
408
buzbee02031b12012-11-23 09:41:35 -0800409LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700410{
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 LIR* res;
412 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800413 int abs_value = (neg) ? -value : value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700414 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800415 ArmOpcode alt_opcode = kThumbBkpt;
416 bool all_low_regs = (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1));
417 int mod_imm = ModifiedImmediate(value);
418 int mod_imm_neg = ModifiedImmediate(-value);
buzbee67bf8852011-08-17 17:51:35 -0700419
Bill Buzbeea114add2012-05-03 15:00:40 -0700420 switch (op) {
421 case kOpLsl:
buzbeefa57c472012-11-21 12:06:18 -0800422 if (all_low_regs)
423 return NewLIR3(cu, kThumbLslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700424 else
buzbeefa57c472012-11-21 12:06:18 -0800425 return NewLIR3(cu, kThumb2LslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700426 case kOpLsr:
buzbeefa57c472012-11-21 12:06:18 -0800427 if (all_low_regs)
428 return NewLIR3(cu, kThumbLsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 else
buzbeefa57c472012-11-21 12:06:18 -0800430 return NewLIR3(cu, kThumb2LsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 case kOpAsr:
buzbeefa57c472012-11-21 12:06:18 -0800432 if (all_low_regs)
433 return NewLIR3(cu, kThumbAsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 else
buzbeefa57c472012-11-21 12:06:18 -0800435 return NewLIR3(cu, kThumb2AsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700436 case kOpRor:
buzbeefa57c472012-11-21 12:06:18 -0800437 return NewLIR3(cu, kThumb2RorRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700438 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800439 if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800441 return NewLIR3(cu, kThumbAddSpRel, r_dest, r_src1, value >> 2);
442 } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700443 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800444 return NewLIR3(cu, kThumbAddPcRel, r_dest, r_src1, value >> 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700445 }
446 // Note: intentional fallthrough
447 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800448 if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700449 if (op == kOpAdd)
450 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
buzbee67bf8852011-08-17 17:51:35 -0700451 else
Bill Buzbeea114add2012-05-03 15:00:40 -0700452 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
buzbeefa57c472012-11-21 12:06:18 -0800453 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
454 } else if ((abs_value & 0xff) == abs_value) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 if (op == kOpAdd)
456 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
457 else
458 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
buzbeefa57c472012-11-21 12:06:18 -0800459 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700460 }
buzbeefa57c472012-11-21 12:06:18 -0800461 if (mod_imm_neg >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 op = (op == kOpAdd) ? kOpSub : kOpAdd;
buzbeefa57c472012-11-21 12:06:18 -0800463 mod_imm = mod_imm_neg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700464 }
465 if (op == kOpSub) {
466 opcode = kThumb2SubRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800467 alt_opcode = kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700468 } else {
469 opcode = kThumb2AddRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800470 alt_opcode = kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 }
472 break;
473 case kOpAdc:
474 opcode = kThumb2AdcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800475 alt_opcode = kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700476 break;
477 case kOpSbc:
478 opcode = kThumb2SbcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800479 alt_opcode = kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700480 break;
481 case kOpOr:
482 opcode = kThumb2OrrRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800483 alt_opcode = kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700484 break;
485 case kOpAnd:
486 opcode = kThumb2AndRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800487 alt_opcode = kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 break;
489 case kOpXor:
490 opcode = kThumb2EorRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800491 alt_opcode = kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700492 break;
493 case kOpMul:
494 //TUNING: power of 2, shift & add
buzbeefa57c472012-11-21 12:06:18 -0800495 mod_imm = -1;
496 alt_opcode = kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700497 break;
498 case kOpCmp: {
buzbeefa57c472012-11-21 12:06:18 -0800499 int mod_imm = ModifiedImmediate(value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700500 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800501 if (mod_imm >= 0) {
502 res = NewLIR2(cu, kThumb2CmpRI8, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700503 } else {
buzbeefa57c472012-11-21 12:06:18 -0800504 int r_tmp = AllocTemp(cu);
505 res = LoadConstant(cu, r_tmp, value);
506 OpRegReg(cu, kOpCmp, r_src1, r_tmp);
507 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 }
509 return res;
buzbee67bf8852011-08-17 17:51:35 -0700510 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700511 default:
buzbeecbd6d442012-11-17 14:11:25 -0800512 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 }
514
buzbeefa57c472012-11-21 12:06:18 -0800515 if (mod_imm >= 0) {
516 return NewLIR3(cu, opcode, r_dest, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700517 } else {
buzbeefa57c472012-11-21 12:06:18 -0800518 int r_scratch = AllocTemp(cu);
519 LoadConstant(cu, r_scratch, value);
520 if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
521 res = NewLIR4(cu, alt_opcode, r_dest, r_src1, r_scratch, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700522 else
buzbeefa57c472012-11-21 12:06:18 -0800523 res = NewLIR3(cu, alt_opcode, r_dest, r_src1, r_scratch);
524 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700525 return res;
526 }
buzbee67bf8852011-08-17 17:51:35 -0700527}
528
buzbee52a77fc2012-11-20 19:50:46 -0800529/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
buzbee02031b12012-11-23 09:41:35 -0800530LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700531{
Bill Buzbeea114add2012-05-03 15:00:40 -0700532 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800533 int abs_value = (neg) ? -value : value;
534 bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700535 ArmOpcode opcode = kThumbBkpt;
536 switch (op) {
537 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800538 if ( !neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700539 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800540 return NewLIR1(cu, kThumbAddSpI7, value >> 2);
541 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700542 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
543 }
544 break;
545 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800546 if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700547 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800548 return NewLIR1(cu, kThumbSubSpI7, value >> 2);
549 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700550 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
551 }
552 break;
553 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800554 if (ARM_LOWREG(r_dest_src1) && short_form)
555 opcode = (short_form) ? kThumbCmpRI8 : kThumbCmpRR;
556 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 opcode = kThumbCmpRR;
558 else {
buzbeefa57c472012-11-21 12:06:18 -0800559 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700560 opcode = kThumbCmpHL;
561 }
562 break;
563 default:
buzbee52a77fc2012-11-20 19:50:46 -0800564 /* Punt to OpRegRegImm - if bad case catch it there */
buzbeefa57c472012-11-21 12:06:18 -0800565 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700566 break;
567 }
buzbeefa57c472012-11-21 12:06:18 -0800568 if (short_form)
569 return NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700570 else {
buzbeefa57c472012-11-21 12:06:18 -0800571 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 }
buzbee67bf8852011-08-17 17:51:35 -0700573}
574
575/*
576 * Determine whether value can be encoded as a Thumb2 floating point
577 * immediate. If not, return -1. If so return encoded 8-bit value.
578 */
buzbeeaad94382012-11-21 07:40:50 -0800579static int EncodeImmDoubleHigh(int value)
buzbee67bf8852011-08-17 17:51:35 -0700580{
Bill Buzbeea114add2012-05-03 15:00:40 -0700581 int res;
buzbeefa57c472012-11-21 12:06:18 -0800582 int bit_a = (value & 0x80000000) >> 31;
583 int not_bit_b = (value & 0x40000000) >> 30;
584 int bit_b = (value & 0x20000000) >> 29;
585 int b_smear = (value & 0x3fc00000) >> 22;
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 int slice = (value & 0x003f0000) >> 16;
587 int zeroes = (value & 0x0000ffff);
588 if (zeroes != 0)
589 return -1;
buzbeefa57c472012-11-21 12:06:18 -0800590 if (bit_b) {
591 if ((not_bit_b != 0) || (b_smear != 0xff))
Bill Buzbeea114add2012-05-03 15:00:40 -0700592 return -1;
593 } else {
buzbeefa57c472012-11-21 12:06:18 -0800594 if ((not_bit_b != 1) || (b_smear != 0x0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700595 return -1;
596 }
buzbeefa57c472012-11-21 12:06:18 -0800597 res = (bit_a << 7) | (bit_b << 6) | slice;
Bill Buzbeea114add2012-05-03 15:00:40 -0700598 return res;
buzbee67bf8852011-08-17 17:51:35 -0700599}
600
buzbeefa57c472012-11-21 12:06:18 -0800601static int EncodeImmDouble(int val_lo, int val_hi)
buzbee67bf8852011-08-17 17:51:35 -0700602{
Bill Buzbeea114add2012-05-03 15:00:40 -0700603 int res = -1;
buzbeefa57c472012-11-21 12:06:18 -0800604 if (val_lo == 0)
605 res = EncodeImmDoubleHigh(val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700606 return res;
buzbee67bf8852011-08-17 17:51:35 -0700607}
608
buzbee02031b12012-11-23 09:41:35 -0800609LIR* ArmCodegen::LoadConstantValueWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi,
610 int val_lo, int val_hi)
buzbee67bf8852011-08-17 17:51:35 -0700611{
Bill Buzbeea114add2012-05-03 15:00:40 -0700612 LIR* res;
buzbee7da142f2012-11-29 16:33:42 -0800613 int target_reg = S2d(r_dest_lo, r_dest_hi);
buzbeefa57c472012-11-21 12:06:18 -0800614 if (ARM_FPREG(r_dest_lo)) {
buzbee7da142f2012-11-29 16:33:42 -0800615 if ((val_lo == 0) && (val_hi == 0)) {
616 // TODO: we need better info about the target CPU. a vector exclusive or
617 // would probably be better here if we could rely on its existance.
618 // Load an immediate +2.0 (which encodes to 0)
619 NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, 0);
620 // +0.0 = +2.0 - +2.0
621 res = NewLIR3(cu, kThumb2Vsubd, target_reg, target_reg, target_reg);
buzbee67bf8852011-08-17 17:51:35 -0700622 } else {
buzbee7da142f2012-11-29 16:33:42 -0800623 int encoded_imm = EncodeImmDouble(val_lo, val_hi);
624 if (encoded_imm >= 0) {
625 res = NewLIR2(cu, kThumb2Vmovd_IMM8, target_reg, encoded_imm);
626 } else {
627 LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi);
628 if (data_target == NULL) {
629 data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi);
630 }
631 LIR* load_pc_rel =
632 RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd,
633 target_reg, r15pc, 0, 0, 0, data_target);
634 SetMemRefType(cu, load_pc_rel, true, kLiteral);
635 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
636 AppendLIR(cu, load_pc_rel);
637 res = load_pc_rel;
Bill Buzbeea114add2012-05-03 15:00:40 -0700638 }
buzbee67bf8852011-08-17 17:51:35 -0700639 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700640 } else {
buzbeefa57c472012-11-21 12:06:18 -0800641 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
642 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700643 }
644 return res;
buzbee67bf8852011-08-17 17:51:35 -0700645}
646
buzbee02031b12012-11-23 09:41:35 -0800647int ArmCodegen::EncodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700648 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700649}
650
buzbee02031b12012-11-23 09:41:35 -0800651LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest,
652 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700653{
buzbeefa57c472012-11-21 12:06:18 -0800654 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700655 LIR* load;
656 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800657 bool thumb_form = (all_low_regs && (scale == 0));
658 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700659
buzbeefa57c472012-11-21 12:06:18 -0800660 if (ARM_FPREG(r_dest)) {
661 if (ARM_SINGLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700662 DCHECK((size == kWord) || (size == kSingle));
663 opcode = kThumb2Vldrs;
664 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700665 } else {
buzbeefa57c472012-11-21 12:06:18 -0800666 DCHECK(ARM_DOUBLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700667 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800668 DCHECK_EQ((r_dest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700669 opcode = kThumb2Vldrd;
670 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700671 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700672 } else {
673 if (size == kSingle)
674 size = kWord;
675 }
buzbee67bf8852011-08-17 17:51:35 -0700676
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 switch (size) {
678 case kDouble: // fall-through
679 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800680 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700681 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800682 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800683 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700684 } else {
buzbeefa57c472012-11-21 12:06:18 -0800685 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700686 }
buzbeefa57c472012-11-21 12:06:18 -0800687 load = NewLIR3(cu, opcode, r_dest, reg_ptr, 0);
688 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700689 return load;
690 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800691 opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 break;
693 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800694 opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700695 break;
696 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800697 opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700698 break;
699 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800700 opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700701 break;
702 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800703 opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700704 break;
705 default:
buzbeecbd6d442012-11-17 14:11:25 -0800706 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700707 }
buzbeefa57c472012-11-21 12:06:18 -0800708 if (thumb_form)
709 load = NewLIR3(cu, opcode, r_dest, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700710 else
buzbeefa57c472012-11-21 12:06:18 -0800711 load = NewLIR4(cu, opcode, r_dest, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700712
Bill Buzbeea114add2012-05-03 15:00:40 -0700713 return load;
buzbee67bf8852011-08-17 17:51:35 -0700714}
715
buzbee02031b12012-11-23 09:41:35 -0800716LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src,
717 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700718{
buzbeefa57c472012-11-21 12:06:18 -0800719 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700720 LIR* store;
721 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800722 bool thumb_form = (all_low_regs && (scale == 0));
723 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700724
buzbeefa57c472012-11-21 12:06:18 -0800725 if (ARM_FPREG(r_src)) {
726 if (ARM_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700727 DCHECK((size == kWord) || (size == kSingle));
728 opcode = kThumb2Vstrs;
729 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700730 } else {
buzbeefa57c472012-11-21 12:06:18 -0800731 DCHECK(ARM_DOUBLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700732 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800733 DCHECK_EQ((r_src & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700734 opcode = kThumb2Vstrd;
735 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700736 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700737 } else {
738 if (size == kSingle)
739 size = kWord;
740 }
buzbee67bf8852011-08-17 17:51:35 -0700741
Bill Buzbeea114add2012-05-03 15:00:40 -0700742 switch (size) {
743 case kDouble: // fall-through
744 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800745 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700746 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800747 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800748 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700749 } else {
buzbeefa57c472012-11-21 12:06:18 -0800750 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700751 }
buzbeefa57c472012-11-21 12:06:18 -0800752 store = NewLIR3(cu, opcode, r_src, reg_ptr, 0);
753 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700754 return store;
755 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800756 opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700757 break;
758 case kUnsignedHalf:
759 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800760 opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700761 break;
762 case kUnsignedByte:
763 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800764 opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700765 break;
766 default:
buzbeecbd6d442012-11-17 14:11:25 -0800767 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700768 }
buzbeefa57c472012-11-21 12:06:18 -0800769 if (thumb_form)
770 store = NewLIR3(cu, opcode, r_src, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700771 else
buzbeefa57c472012-11-21 12:06:18 -0800772 store = NewLIR4(cu, opcode, r_src, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700773
Bill Buzbeea114add2012-05-03 15:00:40 -0700774 return store;
buzbee67bf8852011-08-17 17:51:35 -0700775}
776
777/*
778 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800779 * on base (which must have an associated s_reg and MIR). If not
buzbee67bf8852011-08-17 17:51:35 -0700780 * performing null check, incoming MIR can be null.
781 */
buzbee02031b12012-11-23 09:41:35 -0800782LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest,
783 int r_dest_hi, OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700784{
buzbee02031b12012-11-23 09:41:35 -0800785 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700786 LIR* res;
787 LIR* load;
788 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800789 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700790 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800791 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
792 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700793 bool is64bit = false;
794 switch (size) {
795 case kDouble:
796 case kLong:
797 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800798 if (ARM_FPREG(r_dest)) {
799 if (ARM_SINGLEREG(r_dest)) {
800 DCHECK(ARM_FPREG(r_dest_hi));
buzbee02031b12012-11-23 09:41:35 -0800801 r_dest = cg->S2d(r_dest, r_dest_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700802 }
803 opcode = kThumb2Vldrd;
804 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800805 short_form = true;
806 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700807 }
808 break;
809 } else {
buzbeefa57c472012-11-21 12:06:18 -0800810 res = LoadBaseDispBody(cu, rBase, displacement, r_dest,
811 -1, kWord, s_reg);
812 LoadBaseDispBody(cu, rBase, displacement + 4, r_dest_hi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700813 -1, kWord, INVALID_SREG);
814 return res;
815 }
816 case kSingle:
817 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800818 if (ARM_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 opcode = kThumb2Vldrs;
820 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800821 short_form = true;
822 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700823 }
824 break;
825 }
buzbeefa57c472012-11-21 12:06:18 -0800826 if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700827 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800828 short_form = true;
829 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700830 opcode = kThumbLdrPcRel;
buzbeefa57c472012-11-21 12:06:18 -0800831 } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700832 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800833 short_form = true;
834 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700835 opcode = kThumbLdrSpRel;
buzbeefa57c472012-11-21 12:06:18 -0800836 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700837 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800838 short_form = true;
839 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700840 opcode = kThumbLdrRRI5;
841 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800842 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700843 opcode = kThumb2LdrRRI12;
844 }
845 break;
846 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800847 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800849 short_form = true;
850 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 opcode = kThumbLdrhRRI5;
852 } else if (displacement < 4092 && displacement >= 0) {
buzbeefa57c472012-11-21 12:06:18 -0800853 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700854 opcode = kThumb2LdrhRRI12;
855 }
856 break;
857 case kSignedHalf:
858 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800859 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700860 opcode = kThumb2LdrshRRI12;
861 }
862 break;
863 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800864 if (all_low_regs && displacement < 32 && displacement >= 0) {
865 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 opcode = kThumbLdrbRRI5;
867 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800868 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700869 opcode = kThumb2LdrbRRI12;
870 }
871 break;
872 case kSignedByte:
873 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800874 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700875 opcode = kThumb2LdrsbRRI12;
876 }
877 break;
878 default:
buzbeecbd6d442012-11-17 14:11:25 -0800879 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700880 }
buzbee67bf8852011-08-17 17:51:35 -0700881
buzbeefa57c472012-11-21 12:06:18 -0800882 if (short_form) {
883 load = res = NewLIR3(cu, opcode, r_dest, rBase, encoded_disp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700884 } else {
buzbeefa57c472012-11-21 12:06:18 -0800885 int reg_offset = AllocTemp(cu);
buzbee02031b12012-11-23 09:41:35 -0800886 res = cg->LoadConstant(cu, reg_offset, encoded_disp);
887 load = cg->LoadBaseIndexed(cu, rBase, reg_offset, r_dest, 0, size);
buzbeefa57c472012-11-21 12:06:18 -0800888 FreeTemp(cu, reg_offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700889 }
buzbee67bf8852011-08-17 17:51:35 -0700890
Bill Buzbeea114add2012-05-03 15:00:40 -0700891 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800892 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -0800893 AnnotateDalvikRegAccess(cu, load, displacement >> 2, true /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700894 }
895 return load;
buzbee67bf8852011-08-17 17:51:35 -0700896}
897
buzbee02031b12012-11-23 09:41:35 -0800898LIR* ArmCodegen::LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest,
899 OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700900{
buzbee02031b12012-11-23 09:41:35 -0800901 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1, size, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700902}
903
buzbee02031b12012-11-23 09:41:35 -0800904LIR* ArmCodegen::LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo,
905 int r_dest_hi, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700906{
buzbee02031b12012-11-23 09:41:35 -0800907 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700908}
909
910
buzbee02031b12012-11-23 09:41:35 -0800911LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement,
912 int r_src, int r_src_hi, OpSize size) {
913 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700914 LIR* res, *store;
915 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800916 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700917 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800918 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
919 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700920 bool is64bit = false;
921 switch (size) {
922 case kLong:
923 case kDouble:
924 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800925 if (!ARM_FPREG(r_src)) {
926 res = StoreBaseDispBody(cu, rBase, displacement, r_src, -1, kWord);
927 StoreBaseDispBody(cu, rBase, displacement + 4, r_src_hi, -1, kWord);
Bill Buzbeea114add2012-05-03 15:00:40 -0700928 return res;
929 }
buzbeefa57c472012-11-21 12:06:18 -0800930 if (ARM_SINGLEREG(r_src)) {
931 DCHECK(ARM_FPREG(r_src_hi));
buzbee02031b12012-11-23 09:41:35 -0800932 r_src = cg->S2d(r_src, r_src_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700933 }
934 opcode = kThumb2Vstrd;
935 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800936 short_form = true;
937 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700938 }
939 break;
940 case kSingle:
941 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800942 if (ARM_FPREG(r_src)) {
943 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700944 opcode = kThumb2Vstrs;
945 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800946 short_form = true;
947 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700948 }
949 break;
950 }
buzbeefa57c472012-11-21 12:06:18 -0800951 if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700952 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800953 short_form = true;
954 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700955 opcode = kThumbStrRRI5;
956 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800957 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700958 opcode = kThumb2StrRRI12;
959 }
960 break;
961 case kUnsignedHalf:
962 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800963 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700964 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800965 short_form = true;
966 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700967 opcode = kThumbStrhRRI5;
968 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800969 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 opcode = kThumb2StrhRRI12;
971 }
972 break;
973 case kUnsignedByte:
974 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800975 if (all_low_regs && displacement < 32 && displacement >= 0) {
976 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 opcode = kThumbStrbRRI5;
978 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800979 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 opcode = kThumb2StrbRRI12;
981 }
982 break;
983 default:
buzbeecbd6d442012-11-17 14:11:25 -0800984 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700985 }
buzbeefa57c472012-11-21 12:06:18 -0800986 if (short_form) {
987 store = res = NewLIR3(cu, opcode, r_src, rBase, encoded_disp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700988 } else {
buzbeefa57c472012-11-21 12:06:18 -0800989 int r_scratch = AllocTemp(cu);
buzbee02031b12012-11-23 09:41:35 -0800990 res = cg->LoadConstant(cu, r_scratch, encoded_disp);
991 store = cg->StoreBaseIndexed(cu, rBase, r_scratch, r_src, 0, size);
buzbeefa57c472012-11-21 12:06:18 -0800992 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700993 }
buzbee67bf8852011-08-17 17:51:35 -0700994
Bill Buzbeea114add2012-05-03 15:00:40 -0700995 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -0800996 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -0800997 AnnotateDalvikRegAccess(cu, store, displacement >> 2, false /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700998 }
999 return res;
buzbee67bf8852011-08-17 17:51:35 -07001000}
1001
buzbee02031b12012-11-23 09:41:35 -08001002LIR* ArmCodegen::StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src,
1003 OpSize size)
buzbee67bf8852011-08-17 17:51:35 -07001004{
buzbeefa57c472012-11-21 12:06:18 -08001005 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbee67bf8852011-08-17 17:51:35 -07001006}
1007
buzbee02031b12012-11-23 09:41:35 -08001008LIR* ArmCodegen::StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement,
1009 int r_src_lo, int r_src_hi)
buzbee67bf8852011-08-17 17:51:35 -07001010{
buzbeefa57c472012-11-21 12:06:18 -08001011 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbee67bf8852011-08-17 17:51:35 -07001012}
1013
buzbee02031b12012-11-23 09:41:35 -08001014void ArmCodegen::LoadPair(CompilationUnit* cu, int base, int low_reg, int high_reg)
buzbee67bf8852011-08-17 17:51:35 -07001015{
buzbeefa57c472012-11-21 12:06:18 -08001016 LoadBaseDispWide(cu, base, 0, low_reg, high_reg, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -07001017}
1018
buzbee02031b12012-11-23 09:41:35 -08001019LIR* ArmCodegen::OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src)
buzbee67bf8852011-08-17 17:51:35 -07001020{
Bill Buzbeea114add2012-05-03 15:00:40 -07001021 int opcode;
buzbeefa57c472012-11-21 12:06:18 -08001022 DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
1023 if (ARM_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001024 opcode = kThumb2Vmovd;
1025 } else {
buzbeefa57c472012-11-21 12:06:18 -08001026 if (ARM_SINGLEREG(r_dest)) {
1027 opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001028 } else {
buzbeefa57c472012-11-21 12:06:18 -08001029 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -07001030 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001031 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001032 }
buzbeefa57c472012-11-21 12:06:18 -08001033 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
1034 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
1035 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001036 }
1037 return res;
buzbee67bf8852011-08-17 17:51:35 -07001038}
1039
buzbee02031b12012-11-23 09:41:35 -08001040LIR* ArmCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -07001041{
buzbee52a77fc2012-11-20 19:50:46 -08001042 LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001043 return NULL;
1044}
buzbee67bf8852011-08-17 17:51:35 -07001045
buzbee02031b12012-11-23 09:41:35 -08001046LIR* ArmCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -07001047{
buzbee52a77fc2012-11-20 19:50:46 -08001048 LOG(FATAL) << "Unexpected use of OpMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001049 return NULL;
1050}
1051
buzbee02031b12012-11-23 09:41:35 -08001052LIR* ArmCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1053 int displacement, int r_src, int r_src_hi, OpSize size,
1054 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001055{
buzbee52a77fc2012-11-20 19:50:46 -08001056 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001057 return NULL;
1058}
1059
buzbee02031b12012-11-23 09:41:35 -08001060LIR* ArmCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, int offset)
buzbeeb046e162012-10-30 15:48:42 -07001061{
buzbee52a77fc2012-11-20 19:50:46 -08001062 LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001063 return NULL;
1064}
1065
buzbee02031b12012-11-23 09:41:35 -08001066LIR* ArmCodegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1067 int displacement, int r_dest, int r_dest_hi, OpSize size,
1068 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001069{
buzbee52a77fc2012-11-20 19:50:46 -08001070 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001071 return NULL;
1072}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001073
1074} // namespace art