blob: 44f0c5a2b982757072dbac5681c3daf6af6ef63a [file] [log] [blame]
buzbeee3acd072012-02-25 17:03:10 -08001/*
2 * Copyright (C) 2012 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 ART_COMPILER_COMPILER_CODEGEN_MIPS_MIPSLIR_H_
18#define ART_COMPILER_COMPILER_CODEGEN_MIPS_MIPSLIR_H_
19
20#include "../../Dalvik.h"
21#include "../../CompilerInternals.h"
22
23namespace art {
24
25// Set to 1 to measure cost of suspend check
26#define NO_SUSPEND 0
27
28/*
29 * Runtime register conventions.
30 *
31 * zero is always the value 0
32 * at is scratch (normally used as temp reg by assembler)
33 * v0, v1 are scratch (normally hold subroutine return values)
34 * a0-a3 are scratch (normally hold subroutine arguments)
35 * t0-t8 are scratch
36 * t9 is scratch (normally used for function calls)
37 * s0 (rSUSPEND) is reserved [holds suspend-check counter]
38 * s1 (rSELF) is reserved [holds current &Thread]
39 * s2-s7 are callee save (promotion target)
40 * k0, k1 are reserved for use by interrupt handlers
41 * gp is reserved for global pointer
42 * sp is reserved
43 * s8 is callee save (promotion target)
44 * ra is scratch (normally holds the return addr)
45 *
46 * Preserved across C calls: s0-s8
47 * Trashed across C calls: at, v0-v1, a0-a3, t0-t9, gp, ra
48 *
49 * Floating pointer registers
50 * NOTE: there are 32 fp registers (16 df pairs), but currently
51 * only support 16 fp registers (8 df pairs).
52 * f0-f15
53 * df0-df7, where df0={f0,f1}, df1={f2,f3}, ... , df7={f14,f15}
54 *
55 * f0-f15 (df0-df7) trashed across C calls
56 *
57 * For mips32 code use:
58 * a0-a3 to hold operands
59 * v0-v1 to hold results
60 * t0-t9 for temps
61 *
62 * All jump/branch instructions have a delay slot after it.
63 *
64 * Stack frame diagram (stack grows down, higher addresses at top):
65 *
66 * +------------------------+
67 * | IN[ins-1] | {Note: resides in caller's frame}
68 * | . |
69 * | IN[0] |
70 * | caller's Method* |
71 * +========================+ {Note: start of callee's frame}
72 * | spill region | {variable sized - will include lr if non-leaf.}
73 * +------------------------+
74 * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long]
75 * +------------------------+
76 * | V[locals-1] |
77 * | V[locals-2] |
78 * | . |
79 * | . |
80 * | V[1] |
81 * | V[0] |
82 * +------------------------+
83 * | 0 to 3 words padding |
84 * +------------------------+
85 * | OUT[outs-1] |
86 * | OUT[outs-2] |
87 * | . |
88 * | OUT[0] |
89 * | curMethod* | <<== sp w/ 16-byte alignment
90 * +========================+
91 */
92
93/* Offset to distingish FP regs */
94#define FP_REG_OFFSET 32
95/* Offset to distinguish DP FP regs */
96#define FP_DOUBLE 64
97/* Offset to distingish the extra regs */
98#define EXTRA_REG_OFFSET 128
99/* Reg types */
100#define REGTYPE(x) (x & (FP_REG_OFFSET | FP_DOUBLE))
101#define FPREG(x) ((x & FP_REG_OFFSET) == FP_REG_OFFSET)
102#define EXTRAREG(x) ((x & EXTRA_REG_OFFSET) == EXTRA_REG_OFFSET)
103#define LOWREG(x) ((x & 0x1f) == x)
104#define DOUBLEREG(x) ((x & FP_DOUBLE) == FP_DOUBLE)
105#define SINGLEREG(x) (FPREG(x) && !DOUBLEREG(x))
106/*
107 * Note: the low register of a floating point pair is sufficient to
108 * create the name of a double, but require both names to be passed to
109 * allow for asserts to verify that the pair is consecutive if significant
110 * rework is done in this area. Also, it is a good reminder in the calling
111 * code that reg locations always describe doubles as a pair of singles.
112 */
113#define S2D(x,y) ((x) | FP_DOUBLE)
114/* Mask to strip off fp flags */
115#define FP_REG_MASK (FP_REG_OFFSET-1)
116/* non-existent Dalvik register */
117#define vNone (-1)
118/* non-existant physical register */
119#define rNone (-1)
120
121#ifdef HAVE_LITTLE_ENDIAN
122#define LOWORD_OFFSET 0
123#define HIWORD_OFFSET 4
124#define r_ARG0 r_A0
125#define r_ARG1 r_A1
126#define r_ARG2 r_A2
127#define r_ARG3 r_A3
128#define r_RESULT0 r_V0
129#define r_RESULT1 r_V1
130#else
131#define LOWORD_OFFSET 4
132#define HIWORD_OFFSET 0
133#define r_ARG0 r_A1
134#define r_ARG1 r_A0
135#define r_ARG2 r_A3
136#define r_ARG3 r_A2
137#define r_RESULT0 r_V1
138#define r_RESULT1 r_V0
139#endif
140
141/* These are the same for both big and little endian. */
142#define r_FARG0 r_F12
143#define r_FARG1 r_F13
144#define r_FRESULT0 r_F0
145#define r_FRESULT1 r_F1
146
147/* RegisterLocation templates return values (r_V0, or r_V0/r_V1) */
148#define LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 1, r_V0, INVALID_REG, \
149 INVALID_SREG}
150#define LOC_C_RETURN_ALT {kLocPhysReg, 0, 0, 0, 0, 0, 1, r_F0, INVALID_REG, \
151 INVALID_SREG}
152#define LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_V0, r_V1,\
153 INVALID_SREG}
154#define LOC_C_RETURN_WIDE_ALT {kLocPhysReg, 1, 0, 0, 0, 0, 1, r_F0, r_F1,\
155 INVALID_SREG}
156
157typedef enum ResourceEncodingPos {
158 kGPReg0 = 0,
159 kRegSP = 29,
160 kRegLR = 31,
161 kFPReg0 = 32, /* only 16 fp regs supported currently */
162 kFPRegEnd = 48,
163 kRegHI = kFPRegEnd,
164 kRegLO,
165 kRegPC,
166 kRegEnd = 51,
167 kCCode = kRegEnd,
168 kFPStatus, // FP status word
169 // The following four bits are for memory disambiguation
170 kDalvikReg, // 1 Dalvik Frame (can be fully disambiguated)
171 kLiteral, // 2 Literal pool (can be fully disambiguated)
172 kHeapRef, // 3 Somewhere on the heap (alias with any other heap)
173 kMustNotAlias, // 4 Guaranteed to be non-alias (eg *(r6+x))
174} ResourceEncodingPos;
175
176#define ENCODE_REG_LIST(N) ((u8) N)
177#define ENCODE_REG_SP (1ULL << kRegSP)
178#define ENCODE_REG_LR (1ULL << kRegLR)
179#define ENCODE_REG_PC (1ULL << kRegPC)
180#define ENCODE_CCODE (1ULL << kCCode)
181#define ENCODE_FP_STATUS (1ULL << kFPStatus)
182
183/* Abstract memory locations */
184#define ENCODE_DALVIK_REG (1ULL << kDalvikReg)
185#define ENCODE_LITERAL (1ULL << kLiteral)
186#define ENCODE_HEAP_REF (1ULL << kHeapRef)
187#define ENCODE_MUST_NOT_ALIAS (1ULL << kMustNotAlias)
188
189#define ENCODE_ALL (~0ULL)
190#define ENCODE_MEM (ENCODE_DALVIK_REG | ENCODE_LITERAL | \
191 ENCODE_HEAP_REF | ENCODE_MUST_NOT_ALIAS)
192
193#define DECODE_ALIAS_INFO_REG(X) (X & 0xffff)
194#define DECODE_ALIAS_INFO_WIDE(X) ((X & 0x80000000) ? 1 : 0)
195
buzbeee3acd072012-02-25 17:03:10 -0800196/*
197 * FIXME:
198 * Originally had r4PC as r_S0, rFP as r_S1, rSELF as r_S2, rINST as r_S4
199 * Remap - don't need r4PC, rFP or rINST. Might make sense to keep
200 * Method* in one of these since we have so many registers to play with.
201 */
202
203#define rSUSPEND r_S0
204#define rSELF r_S1
205#define rSP r_SP
206
buzbee31a4a6f2012-02-28 15:36:15 -0800207#define rARG0 r_ARG0
208#define rARG1 r_ARG1
209#define rARG2 r_ARG2
210#define rARG3 r_ARG3
211
212#define rRET0 r_V0
213#define rRET1 r_V1
buzbeee3acd072012-02-25 17:03:10 -0800214
215/*
216 * Annotate special-purpose core registers:
217 */
218
219typedef enum NativeRegisterPool {
220 r_ZERO = 0,
221 r_AT = 1,
222 r_V0 = 2,
223 r_V1 = 3,
224 r_A0 = 4,
225 r_A1 = 5,
226 r_A2 = 6,
227 r_A3 = 7,
228 r_T0 = 8,
229 r_T1 = 9,
230 r_T2 = 10,
231 r_T3 = 11,
232 r_T4 = 12,
233 r_T5 = 13,
234 r_T6 = 14,
235 r_T7 = 15,
236 r_S0 = 16,
237 r_S1 = 17,
238 r_S2 = 18,
239 r_S3 = 19,
240 r_S4 = 20,
241 r_S5 = 21,
242 r_S6 = 22,
243 r_S7 = 23,
244 r_T8 = 24,
245 r_T9 = 25,
246 r_K0 = 26,
247 r_K1 = 27,
248 r_GP = 28,
249 r_SP = 29,
250 r_FP = 30,
251 r_RA = 31,
252
253 r_F0 = 0 + FP_REG_OFFSET,
254 r_F1,
255 r_F2,
256 r_F3,
257 r_F4,
258 r_F5,
259 r_F6,
260 r_F7,
261 r_F8,
262 r_F9,
263 r_F10,
264 r_F11,
265 r_F12,
266 r_F13,
267 r_F14,
268 r_F15,
269#if 0 /* only 16 fp regs supported currently */
270 r_F16,
271 r_F17,
272 r_F18,
273 r_F19,
274 r_F20,
275 r_F21,
276 r_F22,
277 r_F23,
278 r_F24,
279 r_F25,
280 r_F26,
281 r_F27,
282 r_F28,
283 r_F29,
284 r_F30,
285 r_F31,
286#endif
287 r_DF0 = r_F0 + FP_DOUBLE,
288 r_DF1 = r_F2 + FP_DOUBLE,
289 r_DF2 = r_F4 + FP_DOUBLE,
290 r_DF3 = r_F6 + FP_DOUBLE,
291 r_DF4 = r_F8 + FP_DOUBLE,
292 r_DF5 = r_F10 + FP_DOUBLE,
293 r_DF6 = r_F12 + FP_DOUBLE,
294 r_DF7 = r_F14 + FP_DOUBLE,
295#if 0 /* only 16 fp regs supported currently */
296 r_DF8 = r_F16 + FP_DOUBLE,
297 r_DF9 = r_F18 + FP_DOUBLE,
298 r_DF10 = r_F20 + FP_DOUBLE,
299 r_DF11 = r_F22 + FP_DOUBLE,
300 r_DF12 = r_F24 + FP_DOUBLE,
301 r_DF13 = r_F26 + FP_DOUBLE,
302 r_DF14 = r_F28 + FP_DOUBLE,
303 r_DF15 = r_F30 + FP_DOUBLE,
304#endif
305 r_HI = EXTRA_REG_OFFSET,
306 r_LO,
307 r_PC,
308} NativeRegisterPool;
309
310/* Shift encodings */
311typedef enum MipsShiftEncodings {
312 kMipsLsl = 0x0,
313 kMipsLsr = 0x1,
314 kMipsAsr = 0x2,
315 kMipsRor = 0x3
316} MipsShiftEncodings;
317
318/* condition encodings */
319typedef enum MipsConditionCode {
320 kMipsCondEq = 0x0, /* 0000 */
321 kMipsCondNe = 0x1, /* 0001 */
322 kMipsCondCs = 0x2, /* 0010 */
323 kMipsCondCc = 0x3, /* 0011 */
324 kMipsCondMi = 0x4, /* 0100 */
325 kMipsCondPl = 0x5, /* 0101 */
326 kMipsCondVs = 0x6, /* 0110 */
327 kMipsCondVc = 0x7, /* 0111 */
328 kMipsCondHi = 0x8, /* 1000 */
329 kMipsCondLs = 0x9, /* 1001 */
330 kMipsCondGe = 0xa, /* 1010 */
331 kMipsCondLt = 0xb, /* 1011 */
332 kMipsCondGt = 0xc, /* 1100 */
333 kMipsCondLe = 0xd, /* 1101 */
334 kMipsCondAl = 0xe, /* 1110 */
335 kMipsCondNv = 0xf, /* 1111 */
336} MipsConditionCode;
337
338typedef enum MipsThrowKind {
339 kMipsThrowNullPointer,
340 kMipsThrowDivZero,
341 kMipsThrowArrayBounds,
342 kMipsThrowVerificationError,
343 kMipsThrowNegArraySize,
344 kMipsThrowNoSuchMethod,
345 kMipsThrowStackOverflow,
346} MipsThrowKind;
347
buzbee31a4a6f2012-02-28 15:36:15 -0800348#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
buzbeee3acd072012-02-25 17:03:10 -0800349
350/*
351 * The following enum defines the list of supported Thumb instructions by the
352 * assembler. Their corresponding snippet positions will be defined in
353 * Assemble.c.
354 */
355typedef enum MipsOpCode {
buzbee31a4a6f2012-02-28 15:36:15 -0800356 kPseudoSuspendTarget = -15,
357 kPseudoThrowTarget = -14,
358 kPseudoCaseLabel = -13,
359 kPseudoMethodEntry = -12,
360 kPseudoMethodExit = -11,
361 kPseudoBarrier = -10,
362 kPseudoExtended = -9,
363 kPseudoSSARep = -8,
364 kPseudoEntryBlock = -7,
365 kPseudoExitBlock = -6,
366 kPseudoTargetLabel = -5,
367 kPseudoDalvikByteCodeBoundary = -4,
368 kPseudoPseudoAlign4 = -3,
369 kPseudoEHBlockLabel = -2,
370 kPseudoNormalBlockLabel = -1,
buzbeee3acd072012-02-25 17:03:10 -0800371
372 kMipsFirst,
373 kMips32BitData = kMipsFirst, /* data [31..0] */
374 kMipsAddiu, /* addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] */
375 kMipsAddu, /* add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001] */
376 kMipsAnd, /* and d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100100] */
377 kMipsAndi, /* andi t,s,imm16 [001100] s[25..21] t[20..16] imm16[15..0] */
378 kMipsB, /* b o [0001000000000000] o[15..0] */
379 kMipsBal, /* bal o [0000010000010001] o[15..0] */
380 /* NOTE: the code tests the range kMipsBeq thru kMipsBne, so
381 adding an instruction in this range may require updates */
382 kMipsBeq, /* beq s,t,o [000100] s[25..21] t[20..16] o[15..0] */
383 kMipsBeqz, /* beqz s,o [000100] s[25..21] [00000] o[15..0] */
384 kMipsBgez, /* bgez s,o [000001] s[25..21] [00001] o[15..0] */
385 kMipsBgtz, /* bgtz s,o [000111] s[25..21] [00000] o[15..0] */
386 kMipsBlez, /* blez s,o [000110] s[25..21] [00000] o[15..0] */
387 kMipsBltz, /* bltz s,o [000001] s[25..21] [00000] o[15..0] */
388 kMipsBnez, /* bnez s,o [000101] s[25..21] [00000] o[15..0] */
389 kMipsBne, /* bne s,t,o [000101] s[25..21] t[20..16] o[15..0] */
390 kMipsDiv, /* div s,t [000000] s[25..21] t[20..16] [0000000000011010] */
391#if __mips_isa_rev>=2
392 kMipsExt, /* ext t,s,p,z [011111] s[25..21] t[20..16] z[15..11] p[10..6] [000000] */
393#endif
394 kMipsJal, /* jal t [000011] t[25..0] */
395 kMipsJalr, /* jalr d,s [000000] s[25..21] [00000] d[15..11]
396 hint[10..6] [001001] */
397 kMipsJr, /* jr s [000000] s[25..21] [0000000000] hint[10..6] [001000] */
398 kMipsLahi, /* lui t,imm16 [00111100000] t[20..16] imm16[15..0] load addr hi */
399 kMipsLalo, /* ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] load addr lo */
400 kMipsLui, /* lui t,imm16 [00111100000] t[20..16] imm16[15..0] */
401 kMipsLb, /* lb t,o(b) [100000] b[25..21] t[20..16] o[15..0] */
402 kMipsLbu, /* lbu t,o(b) [100100] b[25..21] t[20..16] o[15..0] */
403 kMipsLh, /* lh t,o(b) [100001] b[25..21] t[20..16] o[15..0] */
404 kMipsLhu, /* lhu t,o(b) [100101] b[25..21] t[20..16] o[15..0] */
405 kMipsLw, /* lw t,o(b) [100011] b[25..21] t[20..16] o[15..0] */
406 kMipsMfhi, /* mfhi d [0000000000000000] d[15..11] [00000010000] */
407 kMipsMflo, /* mflo d [0000000000000000] d[15..11] [00000010010] */
408 kMipsMove, /* move d,s [000000] s[25..21] [00000] d[15..11] [00000100101] */
409 kMipsMovz, /* movz d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000001010] */
410 kMipsMul, /* mul d,s,t [011100] s[25..21] t[20..16] d[15..11] [00000000010] */
411 kMipsNop, /* nop [00000000000000000000000000000000] */
412 kMipsNor, /* nor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100111] */
413 kMipsOr, /* or d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100101] */
414 kMipsOri, /* ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] */
415 kMipsPref, /* pref h,o(b) [101011] b[25..21] h[20..16] o[15..0] */
416 kMipsSb, /* sb t,o(b) [101000] b[25..21] t[20..16] o[15..0] */
417#if __mips_isa_rev>=2
418 kMipsSeb, /* seb d,t [01111100000] t[20..16] d[15..11] [10000100000] */
419 kMipsSeh, /* seh d,t [01111100000] t[20..16] d[15..11] [11000100000] */
420#endif
421 kMipsSh, /* sh t,o(b) [101001] b[25..21] t[20..16] o[15..0] */
422 kMipsSll, /* sll d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [000000] */
423 kMipsSllv, /* sllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000100] */
424 kMipsSlt, /* slt d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101010] */
425 kMipsSlti, /* slti t,s,imm16 [001010] s[25..21] t[20..16] imm16[15..0] */
426 kMipsSltu, /* sltu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101011] */
427 kMipsSra, /* sra d,s,imm5 [00000000000] t[20..16] d[15..11] imm5[10..6] [000011] */
428 kMipsSrav, /* srav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000111] */
429 kMipsSrl, /* srl d,t,a [00000000000] t[20..16] d[20..16] a[10..6] [000010] */
430 kMipsSrlv, /* srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110] */
431 kMipsSubu, /* subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011] */
432 kMipsSw, /* sw t,o(b) [101011] b[25..21] t[20..16] o[15..0] */
433 kMipsXor, /* xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110] */
434 kMipsXori, /* xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0] */
435#ifdef __mips_hard_float
436 kMipsFadds, /* add.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000000] */
437 kMipsFsubs, /* sub.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000001] */
438 kMipsFmuls, /* mul.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000010] */
439 kMipsFdivs, /* div.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000011] */
440 kMipsFaddd, /* add.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000000] */
441 kMipsFsubd, /* sub.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000001] */
442 kMipsFmuld, /* mul.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000010] */
443 kMipsFdivd, /* div.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000011] */
444 kMipsFcvtsd, /* cvt.s.d d,s [01000110001] [00000] s[15..11] d[10..6] [100000] */
445 kMipsFcvtsw, /* cvt.s.w d,s [01000110100] [00000] s[15..11] d[10..6] [100000] */
446 kMipsFcvtds, /* cvt.d.s d,s [01000110000] [00000] s[15..11] d[10..6] [100001] */
447 kMipsFcvtdw, /* cvt.d.w d,s [01000110100] [00000] s[15..11] d[10..6] [100001] */
448 kMipsFcvtws, /* cvt.w.d d,s [01000110000] [00000] s[15..11] d[10..6] [100100] */
449 kMipsFcvtwd, /* cvt.w.d d,s [01000110001] [00000] s[15..11] d[10..6] [100100] */
450 kMipsFmovs, /* mov.s d,s [01000110000] [00000] s[15..11] d[10..6] [000110] */
451 kMipsFmovd, /* mov.d d,s [01000110001] [00000] s[15..11] d[10..6] [000110] */
452 kMipsFlwc1, /* lwc1 t,o(b) [110001] b[25..21] t[20..16] o[15..0] */
453 kMipsFldc1, /* ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0] */
454 kMipsFswc1, /* swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0] */
455 kMipsFsdc1, /* sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0] */
456 kMipsMfc1, /* mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000] */
457 kMipsMtc1, /* mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000] */
458#endif
459 kMipsUndefined, /* undefined [011001xxxxxxxxxxxxxxxx] */
460 kMipsLast
461} MipsOpCode;
462
463/* Bit flags describing the behavior of each native opcode */
464typedef enum MipsOpFeatureFlags {
465 kIsBranch = 0,
466 kRegDef0,
467 kRegDef1,
468 kRegDefSP,
469 kRegDefLR,
470 kRegDefList0,
471 kRegDefList1,
472 kRegUse0,
473 kRegUse1,
474 kRegUse2,
475 kRegUse3,
476 kRegUseSP,
477 kRegUsePC,
478 kRegUseList0,
479 kRegUseList1,
480 kNoOperand,
481 kIsUnaryOp,
482 kIsBinaryOp,
483 kIsTertiaryOp,
484 kIsQuadOp,
485 kIsIT,
486 kSetsCCodes,
487 kUsesCCodes,
488 kMemLoad,
489 kMemStore,
490} MipsOpFeatureFlags;
491
492#define IS_LOAD (1 << kMemLoad)
493#define IS_STORE (1 << kMemStore)
494#define IS_BRANCH (1 << kIsBranch)
495#define REG_DEF0 (1 << kRegDef0)
496#define REG_DEF1 (1 << kRegDef1)
497#define REG_DEF_SP (1 << kRegDefSP)
498#define REG_DEF_LR (1 << kRegDefLR)
499#define REG_DEF_LIST0 (1 << kRegDefList0)
500#define REG_DEF_LIST1 (1 << kRegDefList1)
501#define REG_USE0 (1 << kRegUse0)
502#define REG_USE1 (1 << kRegUse1)
503#define REG_USE2 (1 << kRegUse2)
504#define REG_USE3 (1 << kRegUse3)
505#define REG_USE_SP (1 << kRegUseSP)
506#define REG_USE_PC (1 << kRegUsePC)
507#define REG_USE_LIST0 (1 << kRegUseList0)
508#define REG_USE_LIST1 (1 << kRegUseList1)
509#define NO_OPERAND (1 << kNoOperand)
510#define IS_UNARY_OP (1 << kIsUnaryOp)
511#define IS_BINARY_OP (1 << kIsBinaryOp)
512#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
513#define IS_QUAD_OP (1 << kIsQuadOp)
514#define IS_IT (1 << kIsIT)
515#define SETS_CCODES (1 << kSetsCCodes)
516#define USES_CCODES (1 << kUsesCCodes)
517
518/* Common combo register usage patterns */
519#define REG_USE01 (REG_USE0 | REG_USE1)
520#define REG_USE02 (REG_USE0 | REG_USE2)
521#define REG_USE012 (REG_USE01 | REG_USE2)
522#define REG_USE12 (REG_USE1 | REG_USE2)
523#define REG_USE23 (REG_USE2 | REG_USE3)
524#define REG_DEF01 (REG_DEF0 | REG_DEF1)
525#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
526#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
527#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2)
528#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01)
529#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12)
530#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2)
531
532/* Instruction assembly fieldLoc kind */
533typedef enum MipsEncodingKind {
534 kFmtUnused,
535 kFmtBitBlt, /* Bit string using end/start */
536 kFmtDfp, /* Double FP reg */
537 kFmtSfp, /* Single FP reg */
538} MipsEncodingKind;
539
540/* Struct used to define the snippet positions for each Thumb opcode */
541typedef struct MipsEncodingMap {
542 u4 skeleton;
543 struct {
544 MipsEncodingKind kind;
545 int end; /* end for kFmtBitBlt, 1-bit slice end for FP regs */
546 int start; /* start for kFmtBitBlt, 4-bit slice end for FP regs */
547 } fieldLoc[4];
548 MipsOpCode opcode;
549 int flags;
550 const char *name;
551 const char* fmt;
552 int size;
553} MipsEncodingMap;
554
555/* Keys for target-specific scheduling and other optimization hints */
556typedef enum MipsTargetOptHints {
557 kMaxHoistDistance,
558} MipsTargetOptHints;
559
560extern MipsEncodingMap EncodingMap[kMipsLast];
561
562/*
563 * Each instance of this struct holds a pseudo or real LIR instruction:
564 * - pseudo ones (eg labels and marks) and will be discarded by the assembler.
565 * - real ones will be assembled
566 *
567 * FIXME: notes below are Arm-specific. We have 32 core registers instead
568 * of 16, and no IT blocks. Must widen this or overload in order to
569 * support all 32 FP regs. Perhaps use r0 for ccodes, eliminate IT block
570 * and overload gp with fp status word? (or just use a single bit for
571 * both core and fp condition code/status word?
572 *
573 * Machine resources are encoded into a 64-bit vector, where the encodings are
574 * as following:
575 * - [ 0..15]: general purpose registers including PC, SP, and LR
576 * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
577 * starts at bit 16
578 * - [48]: IT block
579 * - [49]: integer condition code
580 * - [50]: floatint-point status word
581 */
582typedef struct MipsLIR {
583 LIR generic;
584 MipsOpCode opcode;
585 int operands[4]; // [0..3] = [dest, src1, src2, extra]
586 struct {
587 bool isNop:1; // LIR is optimized away
588 bool pcRelFixup:1; // May need pc-relative fixup
589 unsigned int age:4; // default is 0, set lazily by the optimizer
590 unsigned int size:3; // in bytes
591 unsigned int unused:23;
592 } flags;
593 int aliasInfo; // For Dalvik register access & litpool disambiguation
594 u8 useMask; // Resource mask for use
595 u8 defMask; // Resource mask for def
596} MipsLIR;
597
598typedef struct SwitchTable {
599 int offset;
600 const u2* table; // Original dex table
601 int vaddr; // Dalvik offset of switch opcode
602 MipsLIR* bxInst; // Switch indirect branch instruction
603 MipsLIR** targets; // Array of case targets
604} SwitchTable;
605
606typedef struct FillArrayData {
607 int offset;
608 const u2* table; // Original dex table
609 int size;
610 int vaddr; // Dalvik offset of OP_FILL_ARRAY_DATA opcode
611} FillArrayData;
612
613/* Utility macros to traverse the LIR/MipsLIR list */
614#define NEXT_LIR(lir) ((MipsLIR *) lir->generic.next)
615#define PREV_LIR(lir) ((MipsLIR *) lir->generic.prev)
616
617#define NEXT_LIR_LVALUE(lir) (lir)->generic.next
618#define PREV_LIR_LVALUE(lir) (lir)->generic.prev
619
620#define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535))
621#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766))
622#define IS_SIMM16_2WORD(v) ((-32764 <= (v)) && ((v) <= 32763)) /* 2 offsets must fit */
623
624} // namespace art
625
626#endif // ART_COMPILER_COMPILER_CODEGEN_MIPS_MIPSLIR_H_