blob: de407552d3bfaf0496bb9f40e00f8ab3044ffc94 [file] [log] [blame]
Raghu Gandhama8b91c52012-05-02 14:27:16 -07001/*
2 * Copyright (C) 2009 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
17#ifndef DALVIK_VM_COMPILER_CODEGEN_MIPS_MIPSLIR_H_
18#define DALVIK_VM_COMPILER_CODEGEN_MIPS_MIPSLIR_H_
19
20#include "Dalvik.h"
21#include "compiler/CompilerInternals.h"
22
23/*
24 * zero is always the value 0
25 * at is scratch for Jit (normally used as temp reg by assembler)
26 * v0, v1 are scratch for Jit (normally hold subroutine return values)
27 * a0-a3 are scratch for Jit (normally hold subroutine arguments)
28 * t0-t7 are scratch for Jit
29 * t8 is scratch for Jit
30 * t9 is scratch for Jit (normally used for function calls)
31 * s0 (rFP) is reserved [holds Dalvik frame pointer]
32 * s1 (rSELF) is reserved [holds current &Thread]
33 * s2 (rINST) is scratch for Jit
34 * s3 (rIBASE) is scratch for Jit
35 * s4-s7 are scratch for Jit
36 * k0, k1 are reserved for use by interrupt handlers
37 * gp is reserved for global pointer
38 * sp is reserved
39 * s8 is scratch for Jit
40 * ra is scratch for Jit (normally holds the return addr)
41 *
42 * Preserved across C calls: s0-s8
43 * Trashed across C calls: at, v0-v1, a0-a3, t0-t9, gp, ra
44 *
45 * Floating pointer registers
46 * NOTE: there are 32 fp registers (16 df pairs), but current Jit code
47 * only support 16 fp registers (8 df pairs).
48 * f0-f15
49 * df0-df7, where df0={f0,f1}, df1={f2,f3}, ... , df7={f14,f15}
50 *
51 * f0-f15 (df0-df7) trashed across C calls
52 *
53 * For mips32 code use:
54 * a0-a3 to hold operands
55 * v0-v1 to hold results
56 * t0-t9 for temps
57 *
58 * All jump/branch instructions have a delay slot after it.
59 *
60 */
61
62/* Offset to distingish FP regs */
63#define FP_REG_OFFSET 32
64/* Offset to distinguish DP FP regs */
65#define FP_DOUBLE 64
66/* Offset to distingish the extra regs */
67#define EXTRA_REG_OFFSET 128
68/* Reg types */
69#define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
70#define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
71#define EXTRAREG(x) ((x & EXTRA_REG_OFFSET) == EXTRA_REG_OFFSET)
72#define LOWREG(x) ((x & 0x1f) == x)
73#define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
74#define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
75/*
76 * Note: the low register of a floating point pair is sufficient to
77 * create the name of a double, but require both names to be passed to
78 * allow for asserts to verify that the pair is consecutive if significant
79 * rework is done in this area. Also, it is a good reminder in the calling
80 * code that reg locations always describe doubles as a pair of singles.
81 */
82#define S2D(x,y) ((x) | FP_DOUBLE)
83/* Mask to strip off fp flags */
84#define FP_REG_MASK (FP_REG_OFFSET-1)
85/* non-existent Dalvik register */
86#define vNone (-1)
87/* non-existant physical register */
88#define rNone (-1)
89
90#ifdef HAVE_LITTLE_ENDIAN
91#define LOWORD_OFFSET 0
92#define HIWORD_OFFSET 4
93#define r_ARG0 r_A0
94#define r_ARG1 r_A1
95#define r_ARG2 r_A2
96#define r_ARG3 r_A3
97#define r_RESULT0 r_V0
98#define r_RESULT1 r_V1
99#else
100#define LOWORD_OFFSET 4
101#define HIWORD_OFFSET 0
102#define r_ARG0 r_A1
103#define r_ARG1 r_A0
104#define r_ARG2 r_A3
105#define r_ARG3 r_A2
106#define r_RESULT0 r_V1
107#define r_RESULT1 r_V0
108#endif
109
110/* These are the same for both big and little endian. */
111#define r_FARG0 r_F12
112#define r_FARG1 r_F13
113#define r_FRESULT0 r_F0
114#define r_FRESULT1 r_F1
115
116/* RegisterLocation templates return values (r_V0, or r_V0/r_V1) */
117#define LOC_C_RETURN {kLocPhysReg, 0, 0, r_V0, 0, -1}
118#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, r_RESULT0, r_RESULT1, -1}
119#define LOC_C_RETURN_ALT {kLocPhysReg, 0, 1, r_F0, 0, -1}
120#define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 1, r_FRESULT0, r_FRESULT1, -1}
121/* RegisterLocation templates for interpState->retVal; */
122#define LOC_DALVIK_RETURN_VAL {kLocRetval, 0, 0, 0, 0, -1}
123#define LOC_DALVIK_RETURN_VAL_WIDE {kLocRetval, 1, 0, 0, 0, -1}
124
125 /*
126 * Data structure tracking the mapping between a Dalvik register (pair) and a
127 * native register (pair). The idea is to reuse the previously loaded value
128 * if possible, otherwise to keep the value in a native register as long as
129 * possible.
130 */
131typedef struct RegisterInfo {
132 int reg; // Reg number
133 bool inUse; // Has it been allocated?
134 bool pair; // Part of a register pair?
135 int partner; // If pair, other reg of pair
136 bool live; // Is there an associated SSA name?
137 bool dirty; // If live, is it dirty?
138 int sReg; // Name of live value
139 struct LIR *defStart; // Starting inst in last def sequence
140 struct LIR *defEnd; // Ending inst in last def sequence
141} RegisterInfo;
142
143typedef struct RegisterPool {
144 BitVector *nullCheckedRegs; // Track which registers have been null-checked
145 int numCoreTemps;
146 RegisterInfo *coreTemps;
147 int nextCoreTemp;
148 int numFPTemps;
149 RegisterInfo *FPTemps;
150 int nextFPTemp;
151} RegisterPool;
152
153typedef enum ResourceEncodingPos {
154 kGPReg0 = 0,
155 kRegSP = 29,
156 kRegLR = 31,
157 kFPReg0 = 32, /* only 16 fp regs supported currently */
158 kFPRegEnd = 48,
159 kRegHI = kFPRegEnd,
160 kRegLO,
161 kRegPC,
162 kRegEnd = 51,
163 kCCode = kRegEnd,
164 kFPStatus, // FP status word
165 // The following four bits are for memory disambiguation
166 kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
167 kLiteral, // 2 Literal pool (can be fully disambiguated)
168 kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
169 kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
170} ResourceEncodingPos;
171
172#define ENCODE_REG_LIST(N) ((u8) N)
173#define ENCODE_REG_SP (1ULL << kRegSP)
174#define ENCODE_REG_LR (1ULL << kRegLR)
175#define ENCODE_REG_PC (1ULL << kRegPC)
176#define ENCODE_CCODE (1ULL << kCCode)
177#define ENCODE_FP_STATUS (1ULL << kFPStatus)
178
179/* Abstract memory locations */
180#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
181#define ENCODE_LITERAL (1ULL << kLiteral)
182#define ENCODE_HEAP_REF (1ULL << kHeapRef)
183#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias)
184
185#define ENCODE_ALL (~0ULL)
186#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
187 ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
188
189#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
190#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
191
192typedef enum OpSize {
193 kWord,
194 kLong,
195 kSingle,
196 kDouble,
197 kUnsignedHalf,
198 kSignedHalf,
199 kUnsignedByte,
200 kSignedByte,
201} OpSize;
202
203typedef enum OpKind {
204 kOpMov,
205 kOpMvn,
206 kOpCmp,
207 kOpLsl,
208 kOpLsr,
209 kOpAsr,
210 kOpRor,
211 kOpNot,
212 kOpAnd,
213 kOpOr,
214 kOpXor,
215 kOpNeg,
216 kOpAdd,
217 kOpAdc,
218 kOpSub,
219 kOpSbc,
220 kOpRsub,
221 kOpMul,
222 kOpDiv,
223 kOpRem,
224 kOpBic,
225 kOpCmn,
226 kOpTst,
227 kOpBkpt,
228 kOpBlx,
229 kOpPush,
230 kOpPop,
231 kOp2Char,
232 kOp2Short,
233 kOp2Byte,
234 kOpCondBr,
235 kOpUncondBr,
236} OpKind;
237
238/*
239 * Annotate special-purpose core registers:
240 *
241 * rPC, rFP, and rSELF are for architecture-independent code to use.
242 */
243typedef enum NativeRegisterPool {
244 r_ZERO = 0,
245 r_AT = 1,
246 r_V0 = 2,
247 r_V1 = 3,
248 r_A0 = 4,
249 r_A1 = 5,
250 r_A2 = 6,
251 r_A3 = 7,
252 r_T0 = 8,
253 r_T1 = 9,
254 r_T2 = 10,
255 r_T3 = 11,
256 r_T4 = 12,
257 r_T5 = 13,
258 r_T6 = 14,
259 r_T7 = 15,
260 r_S0 = 16,
261 r_S1 = 17,
262 r_S2 = 18,
263 r_S3 = 19,
264 r_S4 = 20,
265 r_S5 = 21,
266 r_S6 = 22,
267 r_S7 = 23,
268 r_T8 = 24,
269 r_T9 = 25,
270 r_K0 = 26,
271 r_K1 = 27,
272 r_GP = 28,
273 r_SP = 29,
274 r_FP = 30,
275 r_RA = 31,
276
277 r_F0 = 0 + FP_REG_OFFSET,
278 r_F1,
279 r_F2,
280 r_F3,
281 r_F4,
282 r_F5,
283 r_F6,
284 r_F7,
285 r_F8,
286 r_F9,
287 r_F10,
288 r_F11,
289 r_F12,
290 r_F13,
291 r_F14,
292 r_F15,
293#if 0 /* only 16 fp regs supported currently */
294 r_F16,
295 r_F17,
296 r_F18,
297 r_F19,
298 r_F20,
299 r_F21,
300 r_F22,
301 r_F23,
302 r_F24,
303 r_F25,
304 r_F26,
305 r_F27,
306 r_F28,
307 r_F29,
308 r_F30,
309 r_F31,
310#endif
311 r_DF0 = r_F0 + FP_DOUBLE,
312 r_DF1 = r_F2 + FP_DOUBLE,
313 r_DF2 = r_F4 + FP_DOUBLE,
314 r_DF3 = r_F6 + FP_DOUBLE,
315 r_DF4 = r_F8 + FP_DOUBLE,
316 r_DF5 = r_F10 + FP_DOUBLE,
317 r_DF6 = r_F12 + FP_DOUBLE,
318 r_DF7 = r_F14 + FP_DOUBLE,
319#if 0 /* only 16 fp regs supported currently */
320 r_DF8 = r_F16 + FP_DOUBLE,
321 r_DF9 = r_F18 + FP_DOUBLE,
322 r_DF10 = r_F20 + FP_DOUBLE,
323 r_DF11 = r_F22 + FP_DOUBLE,
324 r_DF12 = r_F24 + FP_DOUBLE,
325 r_DF13 = r_F26 + FP_DOUBLE,
326 r_DF14 = r_F28 + FP_DOUBLE,
327 r_DF15 = r_F30 + FP_DOUBLE,
328#endif
329 r_HI = EXTRA_REG_OFFSET,
330 r_LO,
331 r_PC,
332} NativeRegisterPool;
333
334
335/* must match gp offset used mterp/mips files */
336#define STACK_OFFSET_GP 84
337
338/* MIPSTODO: properly remap arm regs (dPC, dFP, dGLUE) and remove these mappings */
339#define r4PC r_S0
340#define rFP r_S1
341#define rSELF r_S2
342#define rINST r_S4
343
344/* Shift encodings */
345typedef enum MipsShiftEncodings {
346 kMipsLsl = 0x0,
347 kMipsLsr = 0x1,
348 kMipsAsr = 0x2,
349 kMipsRor = 0x3
350} MipsShiftEncodings;
351
352/* condition encodings */
353typedef enum MipsConditionCode {
354 kMipsCondEq = 0x0, /* 0000 */
355 kMipsCondNe = 0x1, /* 0001 */
356 kMipsCondCs = 0x2, /* 0010 */
357 kMipsCondCc = 0x3, /* 0011 */
358 kMipsCondMi = 0x4, /* 0100 */
359 kMipsCondPl = 0x5, /* 0101 */
360 kMipsCondVs = 0x6, /* 0110 */
361 kMipsCondVc = 0x7, /* 0111 */
362 kMipsCondHi = 0x8, /* 1000 */
363 kMipsCondLs = 0x9, /* 1001 */
364 kMipsCondGe = 0xa, /* 1010 */
365 kMipsCondLt = 0xb, /* 1011 */
366 kMipsCondGt = 0xc, /* 1100 */
367 kMipsCondLe = 0xd, /* 1101 */
368 kMipsCondAl = 0xe, /* 1110 */
369 kMipsCondNv = 0xf, /* 1111 */
370} MipsConditionCode;
371
372#define isPseudoOpCode(opCode) ((int)(opCode) < 0)
373
374/*
375 * The following enum defines the list of supported Thumb instructions by the
376 * assembler. Their corresponding snippet positions will be defined in
377 * Assemble.c.
378 */
379typedef enum MipsOpCode {
380 kMipsChainingCellBottom = -18,
381 kMipsPseudoBarrier = -17,
382 kMipsPseudoExtended = -16,
383 kMipsPseudoSSARep = -15,
384 kMipsPseudoEntryBlock = -14,
385 kMipsPseudoExitBlock = -13,
386 kMipsPseudoTargetLabel = -12,
387 kMipsPseudoChainingCellBackwardBranch = -11,
388 kMipsPseudoChainingCellHot = -10,
389 kMipsPseudoChainingCellInvokePredicted = -9,
390 kMipsPseudoChainingCellInvokeSingleton = -8,
391 kMipsPseudoChainingCellNormal = -7,
392 kMipsPseudoDalvikByteCodeBoundary = -6,
393 kMipsPseudoPseudoAlign4 = -5,
394 kMipsPseudoPCReconstructionCell = -4,
395 kMipsPseudoPCReconstructionBlockLabel = -3,
396 kMipsPseudoEHBlockLabel = -2,
397 kMipsPseudoNormalBlockLabel = -1,
398
399 kMipsFirst,
400 kMips32BitData = kMipsFirst, /* data [31..0] */
401 kMipsAddiu, /* addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] */
402 kMipsAddu, /* add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001] */
403 kMipsAnd, /* and d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100100] */
404 kMipsAndi, /* andi t,s,imm16 [001100] s[25..21] t[20..16] imm16[15..0] */
405 kMipsB, /* b o [0001000000000000] o[15..0] */
406 kMipsBal, /* bal o [0000010000010001] o[15..0] */
407 /* NOTE: the code tests the range kMipsBeq thru kMipsBne, so
408 adding an instruction in this range may require updates */
409 kMipsBeq, /* beq s,t,o [000100] s[25..21] t[20..16] o[15..0] */
410 kMipsBeqz, /* beqz s,o [000100] s[25..21] [00000] o[15..0] */
411 kMipsBgez, /* bgez s,o [000001] s[25..21] [00001] o[15..0] */
412 kMipsBgtz, /* bgtz s,o [000111] s[25..21] [00000] o[15..0] */
413 kMipsBlez, /* blez s,o [000110] s[25..21] [00000] o[15..0] */
414 kMipsBltz, /* bltz s,o [000001] s[25..21] [00000] o[15..0] */
415 kMipsBnez, /* bnez s,o [000101] s[25..21] [00000] o[15..0] */
416 kMipsBne, /* bne s,t,o [000101] s[25..21] t[20..16] o[15..0] */
417 kMipsDiv, /* div s,t [000000] s[25..21] t[20..16] [0000000000011010] */
418#if __mips_isa_rev>=2
419 kMipsExt, /* ext t,s,p,z [011111] s[25..21] t[20..16] z[15..11] p[10..6] [000000] */
420#endif
421 kMipsJal, /* jal t [000011] t[25..0] */
422 kMipsJalr, /* jalr d,s [000000] s[25..21] [00000] d[15..11]
423 hint[10..6] [001001] */
424 kMipsJr, /* jr s [000000] s[25..21] [0000000000] hint[10..6] [001000] */
425 kMipsLahi, /* lui t,imm16 [00111100000] t[20..16] imm16[15..0] load addr hi */
426 kMipsLalo, /* ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] load addr lo */
427 kMipsLui, /* lui t,imm16 [00111100000] t[20..16] imm16[15..0] */
428 kMipsLb, /* lb t,o(b) [100000] b[25..21] t[20..16] o[15..0] */
429 kMipsLbu, /* lbu t,o(b) [100100] b[25..21] t[20..16] o[15..0] */
430 kMipsLh, /* lh t,o(b) [100001] b[25..21] t[20..16] o[15..0] */
431 kMipsLhu, /* lhu t,o(b) [100101] b[25..21] t[20..16] o[15..0] */
432 kMipsLw, /* lw t,o(b) [100011] b[25..21] t[20..16] o[15..0] */
433 kMipsMfhi, /* mfhi d [0000000000000000] d[15..11] [00000010000] */
434 kMipsMflo, /* mflo d [0000000000000000] d[15..11] [00000010010] */
435 kMipsMove, /* move d,s [000000] s[25..21] [00000] d[15..11] [00000100101] */
436 kMipsMovz, /* movz d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000001010] */
437 kMipsMul, /* mul d,s,t [011100] s[25..21] t[20..16] d[15..11] [00000000010] */
438 kMipsNop, /* nop [00000000000000000000000000000000] */
439 kMipsNor, /* nor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100111] */
440 kMipsOr, /* or d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100101] */
441 kMipsOri, /* ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] */
442 kMipsPref, /* pref h,o(b) [101011] b[25..21] h[20..16] o[15..0] */
443 kMipsSb, /* sb t,o(b) [101000] b[25..21] t[20..16] o[15..0] */
444#if __mips_isa_rev>=2
445 kMipsSeb, /* seb d,t [01111100000] t[20..16] d[15..11] [10000100000] */
446 kMipsSeh, /* seh d,t [01111100000] t[20..16] d[15..11] [11000100000] */
447#endif
448 kMipsSh, /* sh t,o(b) [101001] b[25..21] t[20..16] o[15..0] */
449 kMipsSll, /* sll d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [000000] */
450 kMipsSllv, /* sllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000100] */
451 kMipsSlt, /* slt d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101010] */
452 kMipsSlti, /* slti t,s,imm16 [001010] s[25..21] t[20..16] imm16[15..0] */
453 kMipsSltu, /* sltu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101011] */
454 kMipsSra, /* sra d,s,imm5 [00000000000] t[20..16] d[15..11] imm5[10..6] [000011] */
455 kMipsSrav, /* srav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000111] */
456 kMipsSrl, /* srl d,t,a [00000000000] t[20..16] d[20..16] a[10..6] [000010] */
457 kMipsSrlv, /* srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110] */
458 kMipsSubu, /* subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011] */
459 kMipsSw, /* sw t,o(b) [101011] b[25..21] t[20..16] o[15..0] */
Chris Dearman5e22c9a2013-10-25 11:40:53 -0700460 kMipsSync, /* sync hint [000000000000000000000] hint[10..6] [001111] */
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700461 kMipsXor, /* xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110] */
462 kMipsXori, /* xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0] */
463#ifdef __mips_hard_float
464 kMipsFadds, /* add.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000000] */
465 kMipsFsubs, /* sub.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000001] */
466 kMipsFmuls, /* mul.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000010] */
467 kMipsFdivs, /* div.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000011] */
468 kMipsFaddd, /* add.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000000] */
469 kMipsFsubd, /* sub.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000001] */
470 kMipsFmuld, /* mul.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000010] */
471 kMipsFdivd, /* div.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000011] */
472 kMipsFcvtsd, /* cvt.s.d d,s [01000110001] [00000] s[15..11] d[10..6] [100000] */
473 kMipsFcvtsw, /* cvt.s.w d,s [01000110100] [00000] s[15..11] d[10..6] [100000] */
474 kMipsFcvtds, /* cvt.d.s d,s [01000110000] [00000] s[15..11] d[10..6] [100001] */
475 kMipsFcvtdw, /* cvt.d.w d,s [01000110100] [00000] s[15..11] d[10..6] [100001] */
476 kMipsFcvtws, /* cvt.w.d d,s [01000110000] [00000] s[15..11] d[10..6] [100100] */
477 kMipsFcvtwd, /* cvt.w.d d,s [01000110001] [00000] s[15..11] d[10..6] [100100] */
478 kMipsFmovs, /* mov.s d,s [01000110000] [00000] s[15..11] d[10..6] [000110] */
479 kMipsFmovd, /* mov.d d,s [01000110001] [00000] s[15..11] d[10..6] [000110] */
480 kMipsFlwc1, /* lwc1 t,o(b) [110001] b[25..21] t[20..16] o[15..0] */
481 kMipsFldc1, /* ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0] */
482 kMipsFswc1, /* swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0] */
483 kMipsFsdc1, /* sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0] */
484 kMipsMfc1, /* mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000] */
485 kMipsMtc1, /* mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000] */
486#endif
487 kMipsUndefined, /* undefined [011001xxxxxxxxxxxxxxxx] */
488 kMipsLast
489} MipsOpCode;
490
Chris Dearman5e22c9a2013-10-25 11:40:53 -0700491/* Sync option encodings */
492typedef enum MipsSyncOptions {
493 /*
494 * sync guarantees ordering of Load/Store operations wrt itself
495 *
496 * Older: instruction classes that must be ordered before the sync instruction completes
497 * Younger: instruction classes that must be ordered after the sync instruction completes
498 * Global: instruction classes that must be performed globally when the sync completes
499 */
500 /* Older Younger Global */
501 kSY = 0x00, /* Load,Store Load,Store Load,Store */
502 kWMB = 0x04, /* Store Store */
503 kMB = 0x10, /* Load,Store Load,Store */
504 kACQUIRE = 0x11, /* Load Load,Store */
505 kRELEASE = 0x12, /* Load,Store Store */
506 kRMB = 0x13 /* Load Load */
507} MipsSyncOptions;
508
Raghu Gandhama8b91c52012-05-02 14:27:16 -0700509/* Bit flags describing the behavior of each native opcode */
510typedef enum MipsOpFeatureFlags {
511 kIsBranch = 0,
512 kRegDef0,
513 kRegDef1,
514 kRegDefSP,
515 kRegDefLR,
516 kRegDefList0,
517 kRegDefList1,
518 kRegUse0,
519 kRegUse1,
520 kRegUse2,
521 kRegUse3,
522 kRegUseSP,
523 kRegUsePC,
524 kRegUseList0,
525 kRegUseList1,
526 kNoOperand,
527 kIsUnaryOp,
528 kIsBinaryOp,
529 kIsTertiaryOp,
530 kIsQuadOp,
531 kIsIT,
532 kSetsCCodes,
533 kUsesCCodes,
534 kMemLoad,
535 kMemStore,
536} MipsOpFeatureFlags;
537
538#define IS_LOAD (1 << kMemLoad)
539#define IS_STORE (1 << kMemStore)
540#define IS_BRANCH (1 << kIsBranch)
541#define REG_DEF0 (1 << kRegDef0)
542#define REG_DEF1 (1 << kRegDef1)
543#define REG_DEF_SP (1 << kRegDefSP)
544#define REG_DEF_LR (1 << kRegDefLR)
545#define REG_DEF_LIST0 (1 << kRegDefList0)
546#define REG_DEF_LIST1 (1 << kRegDefList1)
547#define REG_USE0 (1 << kRegUse0)
548#define REG_USE1 (1 << kRegUse1)
549#define REG_USE2 (1 << kRegUse2)
550#define REG_USE3 (1 << kRegUse3)
551#define REG_USE_SP (1 << kRegUseSP)
552#define REG_USE_PC (1 << kRegUsePC)
553#define REG_USE_LIST0 (1 << kRegUseList0)
554#define REG_USE_LIST1 (1 << kRegUseList1)
555#define NO_OPERAND (1 << kNoOperand)
556#define IS_UNARY_OP (1 << kIsUnaryOp)
557#define IS_BINARY_OP (1 << kIsBinaryOp)
558#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
559#define IS_QUAD_OP (1 << kIsQuadOp)
560#define IS_IT (1 << kIsIT)
561#define SETS_CCODES (1 << kSetsCCodes)
562#define USES_CCODES (1 << kUsesCCodes)
563
564/* Common combo register usage patterns */
565#define REG_USE01 (REG_USE0 | REG_USE1)
566#define REG_USE02 (REG_USE0 | REG_USE2)
567#define REG_USE012 (REG_USE01 | REG_USE2)
568#define REG_USE12 (REG_USE1 | REG_USE2)
569#define REG_USE23 (REG_USE2 | REG_USE3)
570#define REG_DEF01 (REG_DEF0 | REG_DEF1)
571#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
572#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
573#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2)
574#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01)
575#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12)
576#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2)
577
578/* Instruction assembly fieldLoc kind */
579typedef enum MipsEncodingKind {
580 kFmtUnused,
581 kFmtBitBlt, /* Bit string using end/start */
582 kFmtDfp, /* Double FP reg */
583 kFmtSfp, /* Single FP reg */
584} MipsEncodingKind;
585
586/* Struct used to define the snippet positions for each Thumb opcode */
587typedef struct MipsEncodingMap {
588 u4 skeleton;
589 struct {
590 MipsEncodingKind kind;
591 int end; /* end for kFmtBitBlt, 1-bit slice end for FP regs */
592 int start; /* start for kFmtBitBlt, 4-bit slice end for FP regs */
593 } fieldLoc[4];
594 MipsOpCode opcode;
595 int flags;
596 const char *name;
597 const char* fmt;
598 int size;
599} MipsEncodingMap;
600
601/* Keys for target-specific scheduling and other optimization hints */
602typedef enum MipsTargetOptHints {
603 kMaxHoistDistance,
604} MipsTargetOptHints;
605
606extern MipsEncodingMap EncodingMap[kMipsLast];
607
608/*
609 * Each instance of this struct holds a pseudo or real LIR instruction:
610 * - pseudo ones (eg labels and marks) and will be discarded by the assembler.
611 * - real ones will be assembled into Thumb instructions.
612 *
613 * Machine resources are encoded into a 64-bit vector, where the encodings are
614 * as following:
615 * - [ 0..15]: general purpose registers including PC, SP, and LR
616 * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
617 * starts at bit 16
618 * - [48]: IT block
619 * - [49]: integer condition code
620 * - [50]: floatint-point status word
621 */
622typedef struct MipsLIR {
623 LIR generic;
624 MipsOpCode opcode;
625 int operands[4]; // [0..3] = [dest, src1, src2, extra]
626 struct {
627 bool isNop:1; // LIR is optimized away
628 bool insertWrapper:1; // insert branch to emulate memory accesses
629 unsigned int age:4; // default is 0, set lazily by the optimizer
630 unsigned int size:3; // bytes (2 for thumb, 2/4 for thumb2)
631 unsigned int unused:23;
632 } flags;
633 int aliasInfo; // For Dalvik register access & litpool disambiguation
634 u8 useMask; // Resource mask for use
635 u8 defMask; // Resource mask for def
636} MipsLIR;
637
638/* Init values when a predicted chain is initially assembled */
639/* E7FE is branch to self */
640#define PREDICTED_CHAIN_BX_PAIR_INIT 0xe7fe
641#define PREDICTED_CHAIN_DELAY_SLOT_INIT 0
642#define PREDICTED_CHAIN_CLAZZ_INIT 0
643#define PREDICTED_CHAIN_METHOD_INIT 0
644#define PREDICTED_CHAIN_COUNTER_INIT 0
645
646/* Utility macros to traverse the LIR/MipsLIR list */
647#define NEXT_LIR(lir) ((MipsLIR *) lir->generic.next)
648#define PREV_LIR(lir) ((MipsLIR *) lir->generic.prev)
649
650#define NEXT_LIR_LVALUE(lir) (lir)->generic.next
651#define PREV_LIR_LVALUE(lir) (lir)->generic.prev
652
653#define CHAIN_CELL_OFFSET_TAG 0xcdabcdabL
654
655#define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535))
656#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766))
657#define IS_SIMM16_2WORD(v) ((-32764 <= (v)) && ((v) <= 32763)) /* 2 offsets must fit */
658
659#define CHAIN_CELL_NORMAL_SIZE 16
660#define CHAIN_CELL_PREDICTED_SIZE 20
661
662
663#endif // DALVIK_VM_COMPILER_CODEGEN_MIPS_MIPSLIR_H_