blob: d1bf14ec5395b64cf6f3db7da7806f7b33c39118 [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 int encoded_imm = EncodeImmSingle(value);
51 DCHECK(ARM_SINGLEREG(r_dest));
52 if (encoded_imm >= 0) {
53 return NewLIR2(cu, kThumb2Vmovs_IMM8, r_dest, encoded_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -070054 }
buzbeefa57c472012-11-21 12:06:18 -080055 LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0);
56 if (data_target == NULL) {
57 data_target = AddWordData(cu, &cu->literal_list, value);
Bill Buzbeea114add2012-05-03 15:00:40 -070058 }
buzbeefa57c472012-11-21 12:06:18 -080059 LIR* load_pc_rel = RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrs,
60 r_dest, r15pc, 0, 0, 0, data_target);
buzbee02031b12012-11-23 09:41:35 -080061 SetMemRefType(cu, load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -080062 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
63 AppendLIR(cu, load_pc_rel);
64 return load_pc_rel;
buzbee67bf8852011-08-17 17:51:35 -070065}
66
buzbeeaad94382012-11-21 07:40:50 -080067static int LeadingZeros(uint32_t val)
buzbee67bf8852011-08-17 17:51:35 -070068{
buzbeeeaf09bc2012-11-15 14:51:41 -080069 uint32_t alt;
Bill Buzbeea114add2012-05-03 15:00:40 -070070 int n;
71 int count;
buzbee67bf8852011-08-17 17:51:35 -070072
Bill Buzbeea114add2012-05-03 15:00:40 -070073 count = 16;
74 n = 32;
75 do {
76 alt = val >> count;
77 if (alt != 0) {
78 n = n - count;
79 val = alt;
80 }
81 count >>= 1;
82 } while (count);
83 return n - val;
buzbee67bf8852011-08-17 17:51:35 -070084}
85
86/*
87 * Determine whether value can be encoded as a Thumb2 modified
88 * immediate. If not, return -1. If so, return i:imm3:a:bcdefgh form.
89 */
buzbee02031b12012-11-23 09:41:35 -080090int ArmCodegen::ModifiedImmediate(uint32_t value)
buzbee67bf8852011-08-17 17:51:35 -070091{
buzbeefa57c472012-11-21 12:06:18 -080092 int z_leading;
93 int z_trailing;
buzbeeeaf09bc2012-11-15 14:51:41 -080094 uint32_t b0 = value & 0xff;
buzbee67bf8852011-08-17 17:51:35 -070095
96 /* Note: case of value==0 must use 0:000:0:0000000 encoding */
97 if (value <= 0xFF)
Bill Buzbeea114add2012-05-03 15:00:40 -070098 return b0; // 0:000:a:bcdefgh
buzbee67bf8852011-08-17 17:51:35 -070099 if (value == ((b0 << 16) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700100 return (0x1 << 8) | b0; /* 0:001:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700101 if (value == ((b0 << 24) | (b0 << 16) | (b0 << 8) | b0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700102 return (0x3 << 8) | b0; /* 0:011:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700103 b0 = (value >> 8) & 0xff;
104 if (value == ((b0 << 24) | (b0 << 8)))
Bill Buzbeea114add2012-05-03 15:00:40 -0700105 return (0x2 << 8) | b0; /* 0:010:a:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700106 /* Can we do it with rotation? */
buzbeefa57c472012-11-21 12:06:18 -0800107 z_leading = LeadingZeros(value);
108 z_trailing = 32 - LeadingZeros(~value & (value - 1));
buzbee67bf8852011-08-17 17:51:35 -0700109 /* A run of eight or fewer active bits? */
buzbeefa57c472012-11-21 12:06:18 -0800110 if ((z_leading + z_trailing) < 24)
Bill Buzbeea114add2012-05-03 15:00:40 -0700111 return -1; /* No - bail */
buzbee67bf8852011-08-17 17:51:35 -0700112 /* left-justify the constant, discarding msb (known to be 1) */
buzbeefa57c472012-11-21 12:06:18 -0800113 value <<= z_leading + 1;
buzbee67bf8852011-08-17 17:51:35 -0700114 /* Create bcdefgh */
115 value >>= 25;
116 /* Put it all together */
buzbeefa57c472012-11-21 12:06:18 -0800117 return value | ((0x8 + z_leading) << 7); /* [01000..11111]:bcdefgh */
buzbee67bf8852011-08-17 17:51:35 -0700118}
119
120/*
121 * Load a immediate using a shortcut if possible; otherwise
122 * grab from the per-translation literal pool.
123 *
124 * No additional register clobbering operation performed. Use this version when
buzbeefa57c472012-11-21 12:06:18 -0800125 * 1) r_dest is freshly returned from AllocTemp or
buzbee67bf8852011-08-17 17:51:35 -0700126 * 2) The codegen is under fixed register usage
127 */
buzbee02031b12012-11-23 09:41:35 -0800128LIR* ArmCodegen::LoadConstantNoClobber(CompilationUnit* cu, int r_dest, int value)
buzbee67bf8852011-08-17 17:51:35 -0700129{
Bill Buzbeea114add2012-05-03 15:00:40 -0700130 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800131 int mod_imm;
buzbee67bf8852011-08-17 17:51:35 -0700132
buzbeefa57c472012-11-21 12:06:18 -0800133 if (ARM_FPREG(r_dest)) {
134 return LoadFPConstantValue(cu, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700135 }
buzbee67bf8852011-08-17 17:51:35 -0700136
Bill Buzbeea114add2012-05-03 15:00:40 -0700137 /* See if the value can be constructed cheaply */
buzbeefa57c472012-11-21 12:06:18 -0800138 if (ARM_LOWREG(r_dest) && (value >= 0) && (value <= 255)) {
139 return NewLIR2(cu, kThumbMovImm, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700140 }
141 /* Check Modified immediate special cases */
buzbeefa57c472012-11-21 12:06:18 -0800142 mod_imm = ModifiedImmediate(value);
143 if (mod_imm >= 0) {
144 res = NewLIR2(cu, kThumb2MovImmShift, r_dest, mod_imm);
buzbee67bf8852011-08-17 17:51:35 -0700145 return res;
Bill Buzbeea114add2012-05-03 15:00:40 -0700146 }
buzbeefa57c472012-11-21 12:06:18 -0800147 mod_imm = ModifiedImmediate(~value);
148 if (mod_imm >= 0) {
149 res = NewLIR2(cu, kThumb2MvnImm12, r_dest, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700150 return res;
151 }
152 /* 16-bit immediate? */
153 if ((value & 0xffff) == value) {
buzbeefa57c472012-11-21 12:06:18 -0800154 res = NewLIR2(cu, kThumb2MovImm16, r_dest, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700155 return res;
156 }
157 /* No shortcut - go ahead and use literal pool */
buzbeefa57c472012-11-21 12:06:18 -0800158 LIR* data_target = ScanLiteralPool(cu->literal_list, value, 0);
159 if (data_target == NULL) {
160 data_target = AddWordData(cu, &cu->literal_list, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700161 }
buzbeefa57c472012-11-21 12:06:18 -0800162 LIR* load_pc_rel = RawLIR(cu, cu->current_dalvik_offset,
163 kThumb2LdrPcRel12, r_dest, 0, 0, 0, 0, data_target);
buzbee02031b12012-11-23 09:41:35 -0800164 SetMemRefType(cu, load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -0800165 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
166 res = load_pc_rel;
167 AppendLIR(cu, load_pc_rel);
Bill Buzbeea114add2012-05-03 15:00:40 -0700168
169 /*
170 * To save space in the constant pool, we use the ADD_RRI8 instruction to
171 * add up to 255 to an existing constant value.
172 */
buzbeefa57c472012-11-21 12:06:18 -0800173 if (data_target->operands[0] != value) {
174 OpRegImm(cu, kOpAdd, r_dest, value - data_target->operands[0]);
Bill Buzbeea114add2012-05-03 15:00:40 -0700175 }
176 return res;
buzbee67bf8852011-08-17 17:51:35 -0700177}
178
buzbee02031b12012-11-23 09:41:35 -0800179LIR* ArmCodegen::OpUnconditionalBranch(CompilationUnit* cu, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700180{
buzbee02031b12012-11-23 09:41:35 -0800181 LIR* res = NewLIR1(cu, kThumbBUncond, 0 /* offset to be patched during assembly*/);
182 res->target = target;
183 return res;
buzbee67bf8852011-08-17 17:51:35 -0700184}
185
buzbee02031b12012-11-23 09:41:35 -0800186LIR* ArmCodegen::OpCondBranch(CompilationUnit* cu, ConditionCode cc, LIR* target)
buzbee67bf8852011-08-17 17:51:35 -0700187{
buzbeefa57c472012-11-21 12:06:18 -0800188 LIR* branch = NewLIR2(cu, kThumb2BCond, 0 /* offset to be patched */,
buzbee52a77fc2012-11-20 19:50:46 -0800189 ArmConditionEncoding(cc));
Bill Buzbeea114add2012-05-03 15:00:40 -0700190 branch->target = target;
191 return branch;
buzbee67bf8852011-08-17 17:51:35 -0700192}
193
buzbee02031b12012-11-23 09:41:35 -0800194LIR* ArmCodegen::OpReg(CompilationUnit* cu, OpKind op, int r_dest_src)
buzbee67bf8852011-08-17 17:51:35 -0700195{
Bill Buzbeea114add2012-05-03 15:00:40 -0700196 ArmOpcode opcode = kThumbBkpt;
197 switch (op) {
198 case kOpBlx:
199 opcode = kThumbBlxR;
200 break;
201 default:
buzbeecbd6d442012-11-17 14:11:25 -0800202 LOG(FATAL) << "Bad opcode " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700203 }
buzbeefa57c472012-11-21 12:06:18 -0800204 return NewLIR1(cu, opcode, r_dest_src);
buzbee67bf8852011-08-17 17:51:35 -0700205}
206
buzbee02031b12012-11-23 09:41:35 -0800207LIR* ArmCodegen::OpRegRegShift(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2,
208 int shift)
buzbee67bf8852011-08-17 17:51:35 -0700209{
buzbeefa57c472012-11-21 12:06:18 -0800210 bool thumb_form = ((shift == 0) && ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2));
Bill Buzbeea114add2012-05-03 15:00:40 -0700211 ArmOpcode opcode = kThumbBkpt;
212 switch (op) {
213 case kOpAdc:
buzbeefa57c472012-11-21 12:06:18 -0800214 opcode = (thumb_form) ? kThumbAdcRR : kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700215 break;
216 case kOpAnd:
buzbeefa57c472012-11-21 12:06:18 -0800217 opcode = (thumb_form) ? kThumbAndRR : kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700218 break;
219 case kOpBic:
buzbeefa57c472012-11-21 12:06:18 -0800220 opcode = (thumb_form) ? kThumbBicRR : kThumb2BicRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700221 break;
222 case kOpCmn:
223 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800224 opcode = (thumb_form) ? kThumbCmnRR : kThumb2CmnRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700225 break;
226 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800227 if (thumb_form)
Bill Buzbeea114add2012-05-03 15:00:40 -0700228 opcode = kThumbCmpRR;
buzbeefa57c472012-11-21 12:06:18 -0800229 else if ((shift == 0) && !ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700230 opcode = kThumbCmpHH;
buzbeefa57c472012-11-21 12:06:18 -0800231 else if ((shift == 0) && ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700232 opcode = kThumbCmpLH;
233 else if (shift == 0)
234 opcode = kThumbCmpHL;
235 else
236 opcode = kThumb2CmpRR;
237 break;
238 case kOpXor:
buzbeefa57c472012-11-21 12:06:18 -0800239 opcode = (thumb_form) ? kThumbEorRR : kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700240 break;
241 case kOpMov:
242 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800243 if (ARM_LOWREG(r_dest_src1) && ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700244 opcode = kThumbMovRR;
buzbeefa57c472012-11-21 12:06:18 -0800245 else if (!ARM_LOWREG(r_dest_src1) && !ARM_LOWREG(r_src2))
Bill Buzbeea114add2012-05-03 15:00:40 -0700246 opcode = kThumbMovRR_H2H;
buzbeefa57c472012-11-21 12:06:18 -0800247 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700248 opcode = kThumbMovRR_H2L;
249 else
250 opcode = kThumbMovRR_L2H;
251 break;
252 case kOpMul:
253 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800254 opcode = (thumb_form) ? kThumbMul : kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700255 break;
256 case kOpMvn:
buzbeefa57c472012-11-21 12:06:18 -0800257 opcode = (thumb_form) ? kThumbMvn : kThumb2MnvRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700258 break;
259 case kOpNeg:
260 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800261 opcode = (thumb_form) ? kThumbNeg : kThumb2NegRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700262 break;
263 case kOpOr:
buzbeefa57c472012-11-21 12:06:18 -0800264 opcode = (thumb_form) ? kThumbOrr : kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700265 break;
266 case kOpSbc:
buzbeefa57c472012-11-21 12:06:18 -0800267 opcode = (thumb_form) ? kThumbSbc : kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 break;
269 case kOpTst:
buzbeefa57c472012-11-21 12:06:18 -0800270 opcode = (thumb_form) ? kThumbTst : kThumb2TstRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700271 break;
272 case kOpLsl:
273 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800274 opcode = (thumb_form) ? kThumbLslRR : kThumb2LslRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700275 break;
276 case kOpLsr:
277 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800278 opcode = (thumb_form) ? kThumbLsrRR : kThumb2LsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700279 break;
280 case kOpAsr:
281 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800282 opcode = (thumb_form) ? kThumbAsrRR : kThumb2AsrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700283 break;
284 case kOpRor:
285 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800286 opcode = (thumb_form) ? kThumbRorRR : kThumb2RorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700287 break;
288 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800289 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700290 break;
291 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800292 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700293 break;
294 case kOp2Byte:
295 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800296 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 8);
Bill Buzbeea114add2012-05-03 15:00:40 -0700297 case kOp2Short:
298 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800299 return NewLIR4(cu, kThumb2Sbfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700300 case kOp2Char:
301 DCHECK_EQ(shift, 0);
buzbeefa57c472012-11-21 12:06:18 -0800302 return NewLIR4(cu, kThumb2Ubfx, r_dest_src1, r_src2, 0, 16);
Bill Buzbeea114add2012-05-03 15:00:40 -0700303 default:
buzbeecbd6d442012-11-17 14:11:25 -0800304 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700305 break;
306 }
307 DCHECK_GE(static_cast<int>(opcode), 0);
308 if (EncodingMap[opcode].flags & IS_BINARY_OP)
buzbeefa57c472012-11-21 12:06:18 -0800309 return NewLIR2(cu, opcode, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700310 else if (EncodingMap[opcode].flags & IS_TERTIARY_OP) {
buzbeefa57c472012-11-21 12:06:18 -0800311 if (EncodingMap[opcode].field_loc[2].kind == kFmtShift)
312 return NewLIR3(cu, opcode, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700313 else
buzbeefa57c472012-11-21 12:06:18 -0800314 return NewLIR3(cu, opcode, r_dest_src1, r_dest_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700315 } else if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800316 return NewLIR4(cu, opcode, r_dest_src1, r_dest_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700317 else {
318 LOG(FATAL) << "Unexpected encoding operand count";
319 return NULL;
320 }
buzbee67bf8852011-08-17 17:51:35 -0700321}
322
buzbee02031b12012-11-23 09:41:35 -0800323LIR* ArmCodegen::OpRegReg(CompilationUnit* cu, OpKind op, int r_dest_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700324{
buzbeefa57c472012-11-21 12:06:18 -0800325 return OpRegRegShift(cu, op, r_dest_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700326}
327
buzbee02031b12012-11-23 09:41:35 -0800328LIR* ArmCodegen::OpRegRegRegShift(CompilationUnit* cu, OpKind op, int r_dest, int r_src1,
329 int r_src2, int shift)
buzbee67bf8852011-08-17 17:51:35 -0700330{
Bill Buzbeea114add2012-05-03 15:00:40 -0700331 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800332 bool thumb_form = (shift == 0) && ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1) &&
333 ARM_LOWREG(r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700334 switch (op) {
335 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800336 opcode = (thumb_form) ? kThumbAddRRR : kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700337 break;
338 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800339 opcode = (thumb_form) ? kThumbSubRRR : kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700340 break;
341 case kOpRsub:
342 opcode = kThumb2RsubRRR;
343 break;
344 case kOpAdc:
345 opcode = kThumb2AdcRRR;
346 break;
347 case kOpAnd:
348 opcode = kThumb2AndRRR;
349 break;
350 case kOpBic:
351 opcode = kThumb2BicRRR;
352 break;
353 case kOpXor:
354 opcode = kThumb2EorRRR;
355 break;
356 case kOpMul:
357 DCHECK_EQ(shift, 0);
358 opcode = kThumb2MulRRR;
359 break;
360 case kOpOr:
361 opcode = kThumb2OrrRRR;
362 break;
363 case kOpSbc:
364 opcode = kThumb2SbcRRR;
365 break;
366 case kOpLsl:
367 DCHECK_EQ(shift, 0);
368 opcode = kThumb2LslRRR;
369 break;
370 case kOpLsr:
371 DCHECK_EQ(shift, 0);
372 opcode = kThumb2LsrRRR;
373 break;
374 case kOpAsr:
375 DCHECK_EQ(shift, 0);
376 opcode = kThumb2AsrRRR;
377 break;
378 case kOpRor:
379 DCHECK_EQ(shift, 0);
380 opcode = kThumb2RorRRR;
381 break;
382 default:
buzbeecbd6d442012-11-17 14:11:25 -0800383 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700384 break;
385 }
386 DCHECK_GE(static_cast<int>(opcode), 0);
387 if (EncodingMap[opcode].flags & IS_QUAD_OP)
buzbeefa57c472012-11-21 12:06:18 -0800388 return NewLIR4(cu, opcode, r_dest, r_src1, r_src2, shift);
Bill Buzbeea114add2012-05-03 15:00:40 -0700389 else {
390 DCHECK(EncodingMap[opcode].flags & IS_TERTIARY_OP);
buzbeefa57c472012-11-21 12:06:18 -0800391 return NewLIR3(cu, opcode, r_dest, r_src1, r_src2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700392 }
buzbee67bf8852011-08-17 17:51:35 -0700393}
394
buzbee02031b12012-11-23 09:41:35 -0800395LIR* ArmCodegen::OpRegRegReg(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int r_src2)
buzbee67bf8852011-08-17 17:51:35 -0700396{
buzbeefa57c472012-11-21 12:06:18 -0800397 return OpRegRegRegShift(cu, op, r_dest, r_src1, r_src2, 0);
buzbee67bf8852011-08-17 17:51:35 -0700398}
399
buzbee02031b12012-11-23 09:41:35 -0800400LIR* ArmCodegen::OpRegRegImm(CompilationUnit* cu, OpKind op, int r_dest, int r_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700401{
Bill Buzbeea114add2012-05-03 15:00:40 -0700402 LIR* res;
403 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800404 int abs_value = (neg) ? -value : value;
Bill Buzbeea114add2012-05-03 15:00:40 -0700405 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800406 ArmOpcode alt_opcode = kThumbBkpt;
407 bool all_low_regs = (ARM_LOWREG(r_dest) && ARM_LOWREG(r_src1));
408 int mod_imm = ModifiedImmediate(value);
409 int mod_imm_neg = ModifiedImmediate(-value);
buzbee67bf8852011-08-17 17:51:35 -0700410
Bill Buzbeea114add2012-05-03 15:00:40 -0700411 switch (op) {
412 case kOpLsl:
buzbeefa57c472012-11-21 12:06:18 -0800413 if (all_low_regs)
414 return NewLIR3(cu, kThumbLslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700415 else
buzbeefa57c472012-11-21 12:06:18 -0800416 return NewLIR3(cu, kThumb2LslRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700417 case kOpLsr:
buzbeefa57c472012-11-21 12:06:18 -0800418 if (all_low_regs)
419 return NewLIR3(cu, kThumbLsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700420 else
buzbeefa57c472012-11-21 12:06:18 -0800421 return NewLIR3(cu, kThumb2LsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700422 case kOpAsr:
buzbeefa57c472012-11-21 12:06:18 -0800423 if (all_low_regs)
424 return NewLIR3(cu, kThumbAsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700425 else
buzbeefa57c472012-11-21 12:06:18 -0800426 return NewLIR3(cu, kThumb2AsrRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700427 case kOpRor:
buzbeefa57c472012-11-21 12:06:18 -0800428 return NewLIR3(cu, kThumb2RorRRI5, r_dest, r_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700429 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800430 if (ARM_LOWREG(r_dest) && (r_src1 == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700431 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800432 return NewLIR3(cu, kThumbAddSpRel, r_dest, r_src1, value >> 2);
433 } else if (ARM_LOWREG(r_dest) && (r_src1 == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700434 (value <= 1020) && ((value & 0x3)==0)) {
buzbeefa57c472012-11-21 12:06:18 -0800435 return NewLIR3(cu, kThumbAddPcRel, r_dest, r_src1, value >> 2);
Bill Buzbeea114add2012-05-03 15:00:40 -0700436 }
437 // Note: intentional fallthrough
438 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800439 if (all_low_regs && ((abs_value & 0x7) == abs_value)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700440 if (op == kOpAdd)
441 opcode = (neg) ? kThumbSubRRI3 : kThumbAddRRI3;
buzbee67bf8852011-08-17 17:51:35 -0700442 else
Bill Buzbeea114add2012-05-03 15:00:40 -0700443 opcode = (neg) ? kThumbAddRRI3 : kThumbSubRRI3;
buzbeefa57c472012-11-21 12:06:18 -0800444 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
445 } else if ((abs_value & 0xff) == abs_value) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700446 if (op == kOpAdd)
447 opcode = (neg) ? kThumb2SubRRI12 : kThumb2AddRRI12;
448 else
449 opcode = (neg) ? kThumb2AddRRI12 : kThumb2SubRRI12;
buzbeefa57c472012-11-21 12:06:18 -0800450 return NewLIR3(cu, opcode, r_dest, r_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700451 }
buzbeefa57c472012-11-21 12:06:18 -0800452 if (mod_imm_neg >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700453 op = (op == kOpAdd) ? kOpSub : kOpAdd;
buzbeefa57c472012-11-21 12:06:18 -0800454 mod_imm = mod_imm_neg;
Bill Buzbeea114add2012-05-03 15:00:40 -0700455 }
456 if (op == kOpSub) {
457 opcode = kThumb2SubRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800458 alt_opcode = kThumb2SubRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700459 } else {
460 opcode = kThumb2AddRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800461 alt_opcode = kThumb2AddRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700462 }
463 break;
464 case kOpAdc:
465 opcode = kThumb2AdcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800466 alt_opcode = kThumb2AdcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700467 break;
468 case kOpSbc:
469 opcode = kThumb2SbcRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800470 alt_opcode = kThumb2SbcRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700471 break;
472 case kOpOr:
473 opcode = kThumb2OrrRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800474 alt_opcode = kThumb2OrrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700475 break;
476 case kOpAnd:
477 opcode = kThumb2AndRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800478 alt_opcode = kThumb2AndRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700479 break;
480 case kOpXor:
481 opcode = kThumb2EorRRI8;
buzbeefa57c472012-11-21 12:06:18 -0800482 alt_opcode = kThumb2EorRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700483 break;
484 case kOpMul:
485 //TUNING: power of 2, shift & add
buzbeefa57c472012-11-21 12:06:18 -0800486 mod_imm = -1;
487 alt_opcode = kThumb2MulRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700488 break;
489 case kOpCmp: {
buzbeefa57c472012-11-21 12:06:18 -0800490 int mod_imm = ModifiedImmediate(value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700491 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800492 if (mod_imm >= 0) {
493 res = NewLIR2(cu, kThumb2CmpRI8, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700494 } else {
buzbeefa57c472012-11-21 12:06:18 -0800495 int r_tmp = AllocTemp(cu);
496 res = LoadConstant(cu, r_tmp, value);
497 OpRegReg(cu, kOpCmp, r_src1, r_tmp);
498 FreeTemp(cu, r_tmp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700499 }
500 return res;
buzbee67bf8852011-08-17 17:51:35 -0700501 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700502 default:
buzbeecbd6d442012-11-17 14:11:25 -0800503 LOG(FATAL) << "Bad opcode: " << op;
Bill Buzbeea114add2012-05-03 15:00:40 -0700504 }
505
buzbeefa57c472012-11-21 12:06:18 -0800506 if (mod_imm >= 0) {
507 return NewLIR3(cu, opcode, r_dest, r_src1, mod_imm);
Bill Buzbeea114add2012-05-03 15:00:40 -0700508 } else {
buzbeefa57c472012-11-21 12:06:18 -0800509 int r_scratch = AllocTemp(cu);
510 LoadConstant(cu, r_scratch, value);
511 if (EncodingMap[alt_opcode].flags & IS_QUAD_OP)
512 res = NewLIR4(cu, alt_opcode, r_dest, r_src1, r_scratch, 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700513 else
buzbeefa57c472012-11-21 12:06:18 -0800514 res = NewLIR3(cu, alt_opcode, r_dest, r_src1, r_scratch);
515 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700516 return res;
517 }
buzbee67bf8852011-08-17 17:51:35 -0700518}
519
buzbee52a77fc2012-11-20 19:50:46 -0800520/* Handle Thumb-only variants here - otherwise punt to OpRegRegImm */
buzbee02031b12012-11-23 09:41:35 -0800521LIR* ArmCodegen::OpRegImm(CompilationUnit* cu, OpKind op, int r_dest_src1, int value)
buzbee67bf8852011-08-17 17:51:35 -0700522{
Bill Buzbeea114add2012-05-03 15:00:40 -0700523 bool neg = (value < 0);
buzbeefa57c472012-11-21 12:06:18 -0800524 int abs_value = (neg) ? -value : value;
525 bool short_form = (((abs_value & 0xff) == abs_value) && ARM_LOWREG(r_dest_src1));
Bill Buzbeea114add2012-05-03 15:00:40 -0700526 ArmOpcode opcode = kThumbBkpt;
527 switch (op) {
528 case kOpAdd:
buzbeefa57c472012-11-21 12:06:18 -0800529 if ( !neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700530 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800531 return NewLIR1(cu, kThumbAddSpI7, value >> 2);
532 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700533 opcode = (neg) ? kThumbSubRI8 : kThumbAddRI8;
534 }
535 break;
536 case kOpSub:
buzbeefa57c472012-11-21 12:06:18 -0800537 if (!neg && (r_dest_src1 == r13sp) && (value <= 508)) { /* sp */
Bill Buzbeea114add2012-05-03 15:00:40 -0700538 DCHECK_EQ((value & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800539 return NewLIR1(cu, kThumbSubSpI7, value >> 2);
540 } else if (short_form) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700541 opcode = (neg) ? kThumbAddRI8 : kThumbSubRI8;
542 }
543 break;
544 case kOpCmp:
buzbeefa57c472012-11-21 12:06:18 -0800545 if (ARM_LOWREG(r_dest_src1) && short_form)
546 opcode = (short_form) ? kThumbCmpRI8 : kThumbCmpRR;
547 else if (ARM_LOWREG(r_dest_src1))
Bill Buzbeea114add2012-05-03 15:00:40 -0700548 opcode = kThumbCmpRR;
549 else {
buzbeefa57c472012-11-21 12:06:18 -0800550 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700551 opcode = kThumbCmpHL;
552 }
553 break;
554 default:
buzbee52a77fc2012-11-20 19:50:46 -0800555 /* Punt to OpRegRegImm - if bad case catch it there */
buzbeefa57c472012-11-21 12:06:18 -0800556 short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700557 break;
558 }
buzbeefa57c472012-11-21 12:06:18 -0800559 if (short_form)
560 return NewLIR2(cu, opcode, r_dest_src1, abs_value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700561 else {
buzbeefa57c472012-11-21 12:06:18 -0800562 return OpRegRegImm(cu, op, r_dest_src1, r_dest_src1, value);
Bill Buzbeea114add2012-05-03 15:00:40 -0700563 }
buzbee67bf8852011-08-17 17:51:35 -0700564}
565
566/*
567 * Determine whether value can be encoded as a Thumb2 floating point
568 * immediate. If not, return -1. If so return encoded 8-bit value.
569 */
buzbeeaad94382012-11-21 07:40:50 -0800570static int EncodeImmDoubleHigh(int value)
buzbee67bf8852011-08-17 17:51:35 -0700571{
Bill Buzbeea114add2012-05-03 15:00:40 -0700572 int res;
buzbeefa57c472012-11-21 12:06:18 -0800573 int bit_a = (value & 0x80000000) >> 31;
574 int not_bit_b = (value & 0x40000000) >> 30;
575 int bit_b = (value & 0x20000000) >> 29;
576 int b_smear = (value & 0x3fc00000) >> 22;
Bill Buzbeea114add2012-05-03 15:00:40 -0700577 int slice = (value & 0x003f0000) >> 16;
578 int zeroes = (value & 0x0000ffff);
579 if (zeroes != 0)
580 return -1;
buzbeefa57c472012-11-21 12:06:18 -0800581 if (bit_b) {
582 if ((not_bit_b != 0) || (b_smear != 0xff))
Bill Buzbeea114add2012-05-03 15:00:40 -0700583 return -1;
584 } else {
buzbeefa57c472012-11-21 12:06:18 -0800585 if ((not_bit_b != 1) || (b_smear != 0x0))
Bill Buzbeea114add2012-05-03 15:00:40 -0700586 return -1;
587 }
buzbeefa57c472012-11-21 12:06:18 -0800588 res = (bit_a << 7) | (bit_b << 6) | slice;
Bill Buzbeea114add2012-05-03 15:00:40 -0700589 return res;
buzbee67bf8852011-08-17 17:51:35 -0700590}
591
buzbeefa57c472012-11-21 12:06:18 -0800592static int EncodeImmDouble(int val_lo, int val_hi)
buzbee67bf8852011-08-17 17:51:35 -0700593{
Bill Buzbeea114add2012-05-03 15:00:40 -0700594 int res = -1;
buzbeefa57c472012-11-21 12:06:18 -0800595 if (val_lo == 0)
596 res = EncodeImmDoubleHigh(val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700597 return res;
buzbee67bf8852011-08-17 17:51:35 -0700598}
599
buzbee02031b12012-11-23 09:41:35 -0800600LIR* ArmCodegen::LoadConstantValueWide(CompilationUnit* cu, int r_dest_lo, int r_dest_hi,
601 int val_lo, int val_hi)
buzbee67bf8852011-08-17 17:51:35 -0700602{
buzbeefa57c472012-11-21 12:06:18 -0800603 int encoded_imm = EncodeImmDouble(val_lo, val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700604 LIR* res;
buzbeefa57c472012-11-21 12:06:18 -0800605 if (ARM_FPREG(r_dest_lo)) {
606 if (encoded_imm >= 0) {
607 res = NewLIR2(cu, kThumb2Vmovd_IMM8, S2d(r_dest_lo, r_dest_hi),
608 encoded_imm);
buzbee67bf8852011-08-17 17:51:35 -0700609 } else {
buzbeefa57c472012-11-21 12:06:18 -0800610 LIR* data_target = ScanLiteralPoolWide(cu->literal_list, val_lo, val_hi);
611 if (data_target == NULL) {
612 data_target = AddWideData(cu, &cu->literal_list, val_lo, val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700613 }
buzbeefa57c472012-11-21 12:06:18 -0800614 LIR* load_pc_rel =
615 RawLIR(cu, cu->current_dalvik_offset, kThumb2Vldrd,
616 S2d(r_dest_lo, r_dest_hi), r15pc, 0, 0, 0, data_target);
buzbee02031b12012-11-23 09:41:35 -0800617 SetMemRefType(cu, load_pc_rel, true, kLiteral);
buzbeefa57c472012-11-21 12:06:18 -0800618 load_pc_rel->alias_info = reinterpret_cast<uintptr_t>(data_target);
619 AppendLIR(cu, load_pc_rel);
620 res = load_pc_rel;
buzbee67bf8852011-08-17 17:51:35 -0700621 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700622 } else {
buzbeefa57c472012-11-21 12:06:18 -0800623 res = LoadConstantNoClobber(cu, r_dest_lo, val_lo);
624 LoadConstantNoClobber(cu, r_dest_hi, val_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700625 }
626 return res;
buzbee67bf8852011-08-17 17:51:35 -0700627}
628
buzbee02031b12012-11-23 09:41:35 -0800629int ArmCodegen::EncodeShift(int code, int amount) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700630 return ((amount & 0x1f) << 2) | code;
buzbee67bf8852011-08-17 17:51:35 -0700631}
632
buzbee02031b12012-11-23 09:41:35 -0800633LIR* ArmCodegen::LoadBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_dest,
634 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700635{
buzbeefa57c472012-11-21 12:06:18 -0800636 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_dest);
Bill Buzbeea114add2012-05-03 15:00:40 -0700637 LIR* load;
638 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800639 bool thumb_form = (all_low_regs && (scale == 0));
640 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700641
buzbeefa57c472012-11-21 12:06:18 -0800642 if (ARM_FPREG(r_dest)) {
643 if (ARM_SINGLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700644 DCHECK((size == kWord) || (size == kSingle));
645 opcode = kThumb2Vldrs;
646 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700647 } else {
buzbeefa57c472012-11-21 12:06:18 -0800648 DCHECK(ARM_DOUBLEREG(r_dest));
Bill Buzbeea114add2012-05-03 15:00:40 -0700649 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800650 DCHECK_EQ((r_dest & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700651 opcode = kThumb2Vldrd;
652 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700653 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700654 } else {
655 if (size == kSingle)
656 size = kWord;
657 }
buzbee67bf8852011-08-17 17:51:35 -0700658
Bill Buzbeea114add2012-05-03 15:00:40 -0700659 switch (size) {
660 case kDouble: // fall-through
661 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800662 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700663 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800664 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800665 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700666 } else {
buzbeefa57c472012-11-21 12:06:18 -0800667 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700668 }
buzbeefa57c472012-11-21 12:06:18 -0800669 load = NewLIR3(cu, opcode, r_dest, reg_ptr, 0);
670 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700671 return load;
672 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800673 opcode = (thumb_form) ? kThumbLdrRRR : kThumb2LdrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700674 break;
675 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800676 opcode = (thumb_form) ? kThumbLdrhRRR : kThumb2LdrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700677 break;
678 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800679 opcode = (thumb_form) ? kThumbLdrshRRR : kThumb2LdrshRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700680 break;
681 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800682 opcode = (thumb_form) ? kThumbLdrbRRR : kThumb2LdrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700683 break;
684 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800685 opcode = (thumb_form) ? kThumbLdrsbRRR : kThumb2LdrsbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700686 break;
687 default:
buzbeecbd6d442012-11-17 14:11:25 -0800688 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700689 }
buzbeefa57c472012-11-21 12:06:18 -0800690 if (thumb_form)
691 load = NewLIR3(cu, opcode, r_dest, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700692 else
buzbeefa57c472012-11-21 12:06:18 -0800693 load = NewLIR4(cu, opcode, r_dest, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700694
Bill Buzbeea114add2012-05-03 15:00:40 -0700695 return load;
buzbee67bf8852011-08-17 17:51:35 -0700696}
697
buzbee02031b12012-11-23 09:41:35 -0800698LIR* ArmCodegen::StoreBaseIndexed(CompilationUnit* cu, int rBase, int r_index, int r_src,
699 int scale, OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700700{
buzbeefa57c472012-11-21 12:06:18 -0800701 bool all_low_regs = ARM_LOWREG(rBase) && ARM_LOWREG(r_index) && ARM_LOWREG(r_src);
Bill Buzbeea114add2012-05-03 15:00:40 -0700702 LIR* store;
703 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800704 bool thumb_form = (all_low_regs && (scale == 0));
705 int reg_ptr;
buzbee67bf8852011-08-17 17:51:35 -0700706
buzbeefa57c472012-11-21 12:06:18 -0800707 if (ARM_FPREG(r_src)) {
708 if (ARM_SINGLEREG(r_src)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700709 DCHECK((size == kWord) || (size == kSingle));
710 opcode = kThumb2Vstrs;
711 size = kSingle;
buzbee67bf8852011-08-17 17:51:35 -0700712 } else {
buzbeefa57c472012-11-21 12:06:18 -0800713 DCHECK(ARM_DOUBLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700714 DCHECK((size == kLong) || (size == kDouble));
buzbeefa57c472012-11-21 12:06:18 -0800715 DCHECK_EQ((r_src & 0x1), 0);
Bill Buzbeea114add2012-05-03 15:00:40 -0700716 opcode = kThumb2Vstrd;
717 size = kDouble;
buzbee67bf8852011-08-17 17:51:35 -0700718 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700719 } else {
720 if (size == kSingle)
721 size = kWord;
722 }
buzbee67bf8852011-08-17 17:51:35 -0700723
Bill Buzbeea114add2012-05-03 15:00:40 -0700724 switch (size) {
725 case kDouble: // fall-through
726 case kSingle:
buzbeefa57c472012-11-21 12:06:18 -0800727 reg_ptr = AllocTemp(cu);
Bill Buzbeea114add2012-05-03 15:00:40 -0700728 if (scale) {
buzbeefa57c472012-11-21 12:06:18 -0800729 NewLIR4(cu, kThumb2AddRRR, reg_ptr, rBase, r_index,
buzbee52a77fc2012-11-20 19:50:46 -0800730 EncodeShift(kArmLsl, scale));
Bill Buzbeea114add2012-05-03 15:00:40 -0700731 } else {
buzbeefa57c472012-11-21 12:06:18 -0800732 OpRegRegReg(cu, kOpAdd, reg_ptr, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700733 }
buzbeefa57c472012-11-21 12:06:18 -0800734 store = NewLIR3(cu, opcode, r_src, reg_ptr, 0);
735 FreeTemp(cu, reg_ptr);
Bill Buzbeea114add2012-05-03 15:00:40 -0700736 return store;
737 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800738 opcode = (thumb_form) ? kThumbStrRRR : kThumb2StrRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700739 break;
740 case kUnsignedHalf:
741 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800742 opcode = (thumb_form) ? kThumbStrhRRR : kThumb2StrhRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700743 break;
744 case kUnsignedByte:
745 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800746 opcode = (thumb_form) ? kThumbStrbRRR : kThumb2StrbRRR;
Bill Buzbeea114add2012-05-03 15:00:40 -0700747 break;
748 default:
buzbeecbd6d442012-11-17 14:11:25 -0800749 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700750 }
buzbeefa57c472012-11-21 12:06:18 -0800751 if (thumb_form)
752 store = NewLIR3(cu, opcode, r_src, rBase, r_index);
Bill Buzbeea114add2012-05-03 15:00:40 -0700753 else
buzbeefa57c472012-11-21 12:06:18 -0800754 store = NewLIR4(cu, opcode, r_src, rBase, r_index, scale);
buzbee67bf8852011-08-17 17:51:35 -0700755
Bill Buzbeea114add2012-05-03 15:00:40 -0700756 return store;
buzbee67bf8852011-08-17 17:51:35 -0700757}
758
759/*
760 * Load value from base + displacement. Optionally perform null check
buzbeefa57c472012-11-21 12:06:18 -0800761 * on base (which must have an associated s_reg and MIR). If not
buzbee67bf8852011-08-17 17:51:35 -0700762 * performing null check, incoming MIR can be null.
763 */
buzbee02031b12012-11-23 09:41:35 -0800764LIR* ArmCodegen::LoadBaseDispBody(CompilationUnit* cu, int rBase, int displacement, int r_dest,
765 int r_dest_hi, OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700766{
buzbee02031b12012-11-23 09:41:35 -0800767 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700768 LIR* res;
769 LIR* load;
770 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800771 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700772 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800773 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_dest));
774 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700775 bool is64bit = false;
776 switch (size) {
777 case kDouble:
778 case kLong:
779 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800780 if (ARM_FPREG(r_dest)) {
781 if (ARM_SINGLEREG(r_dest)) {
782 DCHECK(ARM_FPREG(r_dest_hi));
buzbee02031b12012-11-23 09:41:35 -0800783 r_dest = cg->S2d(r_dest, r_dest_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700784 }
785 opcode = kThumb2Vldrd;
786 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800787 short_form = true;
788 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700789 }
790 break;
791 } else {
buzbeefa57c472012-11-21 12:06:18 -0800792 res = LoadBaseDispBody(cu, rBase, displacement, r_dest,
793 -1, kWord, s_reg);
794 LoadBaseDispBody(cu, rBase, displacement + 4, r_dest_hi,
Bill Buzbeea114add2012-05-03 15:00:40 -0700795 -1, kWord, INVALID_SREG);
796 return res;
797 }
798 case kSingle:
799 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800800 if (ARM_FPREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700801 opcode = kThumb2Vldrs;
802 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800803 short_form = true;
804 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700805 }
806 break;
807 }
buzbeefa57c472012-11-21 12:06:18 -0800808 if (ARM_LOWREG(r_dest) && (rBase == r15pc) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700809 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800810 short_form = true;
811 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700812 opcode = kThumbLdrPcRel;
buzbeefa57c472012-11-21 12:06:18 -0800813 } else if (ARM_LOWREG(r_dest) && (rBase == r13sp) &&
Bill Buzbeea114add2012-05-03 15:00:40 -0700814 (displacement <= 1020) && (displacement >= 0)) {
buzbeefa57c472012-11-21 12:06:18 -0800815 short_form = true;
816 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700817 opcode = kThumbLdrSpRel;
buzbeefa57c472012-11-21 12:06:18 -0800818 } else if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700819 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800820 short_form = true;
821 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700822 opcode = kThumbLdrRRI5;
823 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800824 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700825 opcode = kThumb2LdrRRI12;
826 }
827 break;
828 case kUnsignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800829 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700830 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800831 short_form = true;
832 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700833 opcode = kThumbLdrhRRI5;
834 } else if (displacement < 4092 && displacement >= 0) {
buzbeefa57c472012-11-21 12:06:18 -0800835 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700836 opcode = kThumb2LdrhRRI12;
837 }
838 break;
839 case kSignedHalf:
840 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800841 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700842 opcode = kThumb2LdrshRRI12;
843 }
844 break;
845 case kUnsignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800846 if (all_low_regs && displacement < 32 && displacement >= 0) {
847 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700848 opcode = kThumbLdrbRRI5;
849 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800850 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700851 opcode = kThumb2LdrbRRI12;
852 }
853 break;
854 case kSignedByte:
855 if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800856 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700857 opcode = kThumb2LdrsbRRI12;
858 }
859 break;
860 default:
buzbeecbd6d442012-11-17 14:11:25 -0800861 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700862 }
buzbee67bf8852011-08-17 17:51:35 -0700863
buzbeefa57c472012-11-21 12:06:18 -0800864 if (short_form) {
865 load = res = NewLIR3(cu, opcode, r_dest, rBase, encoded_disp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700866 } else {
buzbeefa57c472012-11-21 12:06:18 -0800867 int reg_offset = AllocTemp(cu);
buzbee02031b12012-11-23 09:41:35 -0800868 res = cg->LoadConstant(cu, reg_offset, encoded_disp);
869 load = cg->LoadBaseIndexed(cu, rBase, reg_offset, r_dest, 0, size);
buzbeefa57c472012-11-21 12:06:18 -0800870 FreeTemp(cu, reg_offset);
Bill Buzbeea114add2012-05-03 15:00:40 -0700871 }
buzbee67bf8852011-08-17 17:51:35 -0700872
Bill Buzbeea114add2012-05-03 15:00:40 -0700873 // TODO: in future may need to differentiate Dalvik accesses w/ spills
buzbeef0504cd2012-11-13 16:31:10 -0800874 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -0800875 AnnotateDalvikRegAccess(cu, load, displacement >> 2, true /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700876 }
877 return load;
buzbee67bf8852011-08-17 17:51:35 -0700878}
879
buzbee02031b12012-11-23 09:41:35 -0800880LIR* ArmCodegen::LoadBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_dest,
881 OpSize size, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700882{
buzbee02031b12012-11-23 09:41:35 -0800883 return LoadBaseDispBody(cu, rBase, displacement, r_dest, -1, size, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700884}
885
buzbee02031b12012-11-23 09:41:35 -0800886LIR* ArmCodegen::LoadBaseDispWide(CompilationUnit* cu, int rBase, int displacement, int r_dest_lo,
887 int r_dest_hi, int s_reg)
buzbee67bf8852011-08-17 17:51:35 -0700888{
buzbee02031b12012-11-23 09:41:35 -0800889 return LoadBaseDispBody(cu, rBase, displacement, r_dest_lo, r_dest_hi, kLong, s_reg);
buzbee67bf8852011-08-17 17:51:35 -0700890}
891
892
buzbee02031b12012-11-23 09:41:35 -0800893LIR* ArmCodegen::StoreBaseDispBody(CompilationUnit* cu, int rBase, int displacement,
894 int r_src, int r_src_hi, OpSize size) {
895 Codegen* cg = cu->cg.get();
Bill Buzbeea114add2012-05-03 15:00:40 -0700896 LIR* res, *store;
897 ArmOpcode opcode = kThumbBkpt;
buzbeefa57c472012-11-21 12:06:18 -0800898 bool short_form = false;
Bill Buzbeea114add2012-05-03 15:00:40 -0700899 bool thumb2Form = (displacement < 4092 && displacement >= 0);
buzbeefa57c472012-11-21 12:06:18 -0800900 bool all_low_regs = (ARM_LOWREG(rBase) && ARM_LOWREG(r_src));
901 int encoded_disp = displacement;
Bill Buzbeea114add2012-05-03 15:00:40 -0700902 bool is64bit = false;
903 switch (size) {
904 case kLong:
905 case kDouble:
906 is64bit = true;
buzbeefa57c472012-11-21 12:06:18 -0800907 if (!ARM_FPREG(r_src)) {
908 res = StoreBaseDispBody(cu, rBase, displacement, r_src, -1, kWord);
909 StoreBaseDispBody(cu, rBase, displacement + 4, r_src_hi, -1, kWord);
Bill Buzbeea114add2012-05-03 15:00:40 -0700910 return res;
911 }
buzbeefa57c472012-11-21 12:06:18 -0800912 if (ARM_SINGLEREG(r_src)) {
913 DCHECK(ARM_FPREG(r_src_hi));
buzbee02031b12012-11-23 09:41:35 -0800914 r_src = cg->S2d(r_src, r_src_hi);
Bill Buzbeea114add2012-05-03 15:00:40 -0700915 }
916 opcode = kThumb2Vstrd;
917 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800918 short_form = true;
919 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700920 }
921 break;
922 case kSingle:
923 case kWord:
buzbeefa57c472012-11-21 12:06:18 -0800924 if (ARM_FPREG(r_src)) {
925 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -0700926 opcode = kThumb2Vstrs;
927 if (displacement <= 1020) {
buzbeefa57c472012-11-21 12:06:18 -0800928 short_form = true;
929 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700930 }
931 break;
932 }
buzbeefa57c472012-11-21 12:06:18 -0800933 if (all_low_regs && displacement < 128 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700934 DCHECK_EQ((displacement & 0x3), 0);
buzbeefa57c472012-11-21 12:06:18 -0800935 short_form = true;
936 encoded_disp >>= 2;
Bill Buzbeea114add2012-05-03 15:00:40 -0700937 opcode = kThumbStrRRI5;
938 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800939 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700940 opcode = kThumb2StrRRI12;
941 }
942 break;
943 case kUnsignedHalf:
944 case kSignedHalf:
buzbeefa57c472012-11-21 12:06:18 -0800945 if (all_low_regs && displacement < 64 && displacement >= 0) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700946 DCHECK_EQ((displacement & 0x1), 0);
buzbeefa57c472012-11-21 12:06:18 -0800947 short_form = true;
948 encoded_disp >>= 1;
Bill Buzbeea114add2012-05-03 15:00:40 -0700949 opcode = kThumbStrhRRI5;
950 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800951 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700952 opcode = kThumb2StrhRRI12;
953 }
954 break;
955 case kUnsignedByte:
956 case kSignedByte:
buzbeefa57c472012-11-21 12:06:18 -0800957 if (all_low_regs && displacement < 32 && displacement >= 0) {
958 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700959 opcode = kThumbStrbRRI5;
960 } else if (thumb2Form) {
buzbeefa57c472012-11-21 12:06:18 -0800961 short_form = true;
Bill Buzbeea114add2012-05-03 15:00:40 -0700962 opcode = kThumb2StrbRRI12;
963 }
964 break;
965 default:
buzbeecbd6d442012-11-17 14:11:25 -0800966 LOG(FATAL) << "Bad size: " << size;
Bill Buzbeea114add2012-05-03 15:00:40 -0700967 }
buzbeefa57c472012-11-21 12:06:18 -0800968 if (short_form) {
969 store = res = NewLIR3(cu, opcode, r_src, rBase, encoded_disp);
Bill Buzbeea114add2012-05-03 15:00:40 -0700970 } else {
buzbeefa57c472012-11-21 12:06:18 -0800971 int r_scratch = AllocTemp(cu);
buzbee02031b12012-11-23 09:41:35 -0800972 res = cg->LoadConstant(cu, r_scratch, encoded_disp);
973 store = cg->StoreBaseIndexed(cu, rBase, r_scratch, r_src, 0, size);
buzbeefa57c472012-11-21 12:06:18 -0800974 FreeTemp(cu, r_scratch);
Bill Buzbeea114add2012-05-03 15:00:40 -0700975 }
buzbee67bf8852011-08-17 17:51:35 -0700976
Bill Buzbeea114add2012-05-03 15:00:40 -0700977 // TODO: In future, may need to differentiate Dalvik & spill accesses
buzbeef0504cd2012-11-13 16:31:10 -0800978 if (rBase == rARM_SP) {
buzbee02031b12012-11-23 09:41:35 -0800979 AnnotateDalvikRegAccess(cu, store, displacement >> 2, false /* is_load */, is64bit);
Bill Buzbeea114add2012-05-03 15:00:40 -0700980 }
981 return res;
buzbee67bf8852011-08-17 17:51:35 -0700982}
983
buzbee02031b12012-11-23 09:41:35 -0800984LIR* ArmCodegen::StoreBaseDisp(CompilationUnit* cu, int rBase, int displacement, int r_src,
985 OpSize size)
buzbee67bf8852011-08-17 17:51:35 -0700986{
buzbeefa57c472012-11-21 12:06:18 -0800987 return StoreBaseDispBody(cu, rBase, displacement, r_src, -1, size);
buzbee67bf8852011-08-17 17:51:35 -0700988}
989
buzbee02031b12012-11-23 09:41:35 -0800990LIR* ArmCodegen::StoreBaseDispWide(CompilationUnit* cu, int rBase, int displacement,
991 int r_src_lo, int r_src_hi)
buzbee67bf8852011-08-17 17:51:35 -0700992{
buzbeefa57c472012-11-21 12:06:18 -0800993 return StoreBaseDispBody(cu, rBase, displacement, r_src_lo, r_src_hi, kLong);
buzbee67bf8852011-08-17 17:51:35 -0700994}
995
buzbee02031b12012-11-23 09:41:35 -0800996void ArmCodegen::LoadPair(CompilationUnit* cu, int base, int low_reg, int high_reg)
buzbee67bf8852011-08-17 17:51:35 -0700997{
buzbeefa57c472012-11-21 12:06:18 -0800998 LoadBaseDispWide(cu, base, 0, low_reg, high_reg, INVALID_SREG);
buzbee67bf8852011-08-17 17:51:35 -0700999}
1000
buzbee02031b12012-11-23 09:41:35 -08001001LIR* ArmCodegen::OpFpRegCopy(CompilationUnit* cu, int r_dest, int r_src)
buzbee67bf8852011-08-17 17:51:35 -07001002{
Bill Buzbeea114add2012-05-03 15:00:40 -07001003 int opcode;
buzbeefa57c472012-11-21 12:06:18 -08001004 DCHECK_EQ(ARM_DOUBLEREG(r_dest), ARM_DOUBLEREG(r_src));
1005 if (ARM_DOUBLEREG(r_dest)) {
Bill Buzbeea114add2012-05-03 15:00:40 -07001006 opcode = kThumb2Vmovd;
1007 } else {
buzbeefa57c472012-11-21 12:06:18 -08001008 if (ARM_SINGLEREG(r_dest)) {
1009 opcode = ARM_SINGLEREG(r_src) ? kThumb2Vmovs : kThumb2Fmsr;
buzbeea2ebdd72012-03-04 14:57:06 -08001010 } else {
buzbeefa57c472012-11-21 12:06:18 -08001011 DCHECK(ARM_SINGLEREG(r_src));
Bill Buzbeea114add2012-05-03 15:00:40 -07001012 opcode = kThumb2Fmrs;
buzbeea2ebdd72012-03-04 14:57:06 -08001013 }
Bill Buzbeea114add2012-05-03 15:00:40 -07001014 }
buzbeefa57c472012-11-21 12:06:18 -08001015 LIR* res = RawLIR(cu, cu->current_dalvik_offset, opcode, r_dest, r_src);
1016 if (!(cu->disable_opt & (1 << kSafeOptimizations)) && r_dest == r_src) {
1017 res->flags.is_nop = true;
Bill Buzbeea114add2012-05-03 15:00:40 -07001018 }
1019 return res;
buzbee67bf8852011-08-17 17:51:35 -07001020}
1021
buzbee02031b12012-11-23 09:41:35 -08001022LIR* ArmCodegen::OpThreadMem(CompilationUnit* cu, OpKind op, int thread_offset)
buzbeeb046e162012-10-30 15:48:42 -07001023{
buzbee52a77fc2012-11-20 19:50:46 -08001024 LOG(FATAL) << "Unexpected use of OpThreadMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001025 return NULL;
1026}
buzbee67bf8852011-08-17 17:51:35 -07001027
buzbee02031b12012-11-23 09:41:35 -08001028LIR* ArmCodegen::OpMem(CompilationUnit* cu, OpKind op, int rBase, int disp)
buzbeeb046e162012-10-30 15:48:42 -07001029{
buzbee52a77fc2012-11-20 19:50:46 -08001030 LOG(FATAL) << "Unexpected use of OpMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001031 return NULL;
1032}
1033
buzbee02031b12012-11-23 09:41:35 -08001034LIR* ArmCodegen::StoreBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1035 int displacement, int r_src, int r_src_hi, OpSize size,
1036 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001037{
buzbee52a77fc2012-11-20 19:50:46 -08001038 LOG(FATAL) << "Unexpected use of StoreBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001039 return NULL;
1040}
1041
buzbee02031b12012-11-23 09:41:35 -08001042LIR* ArmCodegen::OpRegMem(CompilationUnit *cu, OpKind op, int r_dest, int rBase, int offset)
buzbeeb046e162012-10-30 15:48:42 -07001043{
buzbee52a77fc2012-11-20 19:50:46 -08001044 LOG(FATAL) << "Unexpected use of OpRegMem for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001045 return NULL;
1046}
1047
buzbee02031b12012-11-23 09:41:35 -08001048LIR* ArmCodegen::LoadBaseIndexedDisp(CompilationUnit *cu, int rBase, int r_index, int scale,
1049 int displacement, int r_dest, int r_dest_hi, OpSize size,
1050 int s_reg)
buzbeeb046e162012-10-30 15:48:42 -07001051{
buzbee52a77fc2012-11-20 19:50:46 -08001052 LOG(FATAL) << "Unexpected use of LoadBaseIndexedDisp for Arm";
buzbeeb046e162012-10-30 15:48:42 -07001053 return NULL;
1054}
Elliott Hughes11d1b0c2012-01-23 16:57:47 -08001055
1056} // namespace art