blob: a6f426e76fb436fa517d752d36058445ea2f5b8b [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
196typedef enum OpKind {
197 kOpMov,
198 kOpMvn,
199 kOpCmp,
200 kOpLsl,
201 kOpLsr,
202 kOpAsr,
203 kOpRor,
204 kOpNot,
205 kOpAnd,
206 kOpOr,
207 kOpXor,
208 kOpNeg,
209 kOpAdd,
210 kOpAdc,
211 kOpSub,
212 kOpSbc,
213 kOpRsub,
214 kOpMul,
215 kOpDiv,
216 kOpRem,
217 kOpBic,
218 kOpCmn,
219 kOpTst,
220 kOpBkpt,
221 kOpBlx,
222 kOpPush,
223 kOpPop,
224 kOp2Char,
225 kOp2Short,
226 kOp2Byte,
227 kOpCondBr,
228 kOpUncondBr,
229 kOpInvalid,
230} OpKind;
231
232/*
233 * FIXME:
234 * Originally had r4PC as r_S0, rFP as r_S1, rSELF as r_S2, rINST as r_S4
235 * Remap - don't need r4PC, rFP or rINST. Might make sense to keep
236 * Method* in one of these since we have so many registers to play with.
237 */
238
239#define rSUSPEND r_S0
240#define rSELF r_S1
241#define rSP r_SP
242
243/* FIXME: don't do this - find and fix all rLR's */
244#define rLR r_RA
245
246/*
247 * Annotate special-purpose core registers:
248 */
249
250typedef enum NativeRegisterPool {
251 r_ZERO = 0,
252 r_AT = 1,
253 r_V0 = 2,
254 r_V1 = 3,
255 r_A0 = 4,
256 r_A1 = 5,
257 r_A2 = 6,
258 r_A3 = 7,
259 r_T0 = 8,
260 r_T1 = 9,
261 r_T2 = 10,
262 r_T3 = 11,
263 r_T4 = 12,
264 r_T5 = 13,
265 r_T6 = 14,
266 r_T7 = 15,
267 r_S0 = 16,
268 r_S1 = 17,
269 r_S2 = 18,
270 r_S3 = 19,
271 r_S4 = 20,
272 r_S5 = 21,
273 r_S6 = 22,
274 r_S7 = 23,
275 r_T8 = 24,
276 r_T9 = 25,
277 r_K0 = 26,
278 r_K1 = 27,
279 r_GP = 28,
280 r_SP = 29,
281 r_FP = 30,
282 r_RA = 31,
283
284 r_F0 = 0 + FP_REG_OFFSET,
285 r_F1,
286 r_F2,
287 r_F3,
288 r_F4,
289 r_F5,
290 r_F6,
291 r_F7,
292 r_F8,
293 r_F9,
294 r_F10,
295 r_F11,
296 r_F12,
297 r_F13,
298 r_F14,
299 r_F15,
300#if 0 /* only 16 fp regs supported currently */
301 r_F16,
302 r_F17,
303 r_F18,
304 r_F19,
305 r_F20,
306 r_F21,
307 r_F22,
308 r_F23,
309 r_F24,
310 r_F25,
311 r_F26,
312 r_F27,
313 r_F28,
314 r_F29,
315 r_F30,
316 r_F31,
317#endif
318 r_DF0 = r_F0 + FP_DOUBLE,
319 r_DF1 = r_F2 + FP_DOUBLE,
320 r_DF2 = r_F4 + FP_DOUBLE,
321 r_DF3 = r_F6 + FP_DOUBLE,
322 r_DF4 = r_F8 + FP_DOUBLE,
323 r_DF5 = r_F10 + FP_DOUBLE,
324 r_DF6 = r_F12 + FP_DOUBLE,
325 r_DF7 = r_F14 + FP_DOUBLE,
326#if 0 /* only 16 fp regs supported currently */
327 r_DF8 = r_F16 + FP_DOUBLE,
328 r_DF9 = r_F18 + FP_DOUBLE,
329 r_DF10 = r_F20 + FP_DOUBLE,
330 r_DF11 = r_F22 + FP_DOUBLE,
331 r_DF12 = r_F24 + FP_DOUBLE,
332 r_DF13 = r_F26 + FP_DOUBLE,
333 r_DF14 = r_F28 + FP_DOUBLE,
334 r_DF15 = r_F30 + FP_DOUBLE,
335#endif
336 r_HI = EXTRA_REG_OFFSET,
337 r_LO,
338 r_PC,
339} NativeRegisterPool;
340
341/* Shift encodings */
342typedef enum MipsShiftEncodings {
343 kMipsLsl = 0x0,
344 kMipsLsr = 0x1,
345 kMipsAsr = 0x2,
346 kMipsRor = 0x3
347} MipsShiftEncodings;
348
349/* condition encodings */
350typedef enum MipsConditionCode {
351 kMipsCondEq = 0x0, /* 0000 */
352 kMipsCondNe = 0x1, /* 0001 */
353 kMipsCondCs = 0x2, /* 0010 */
354 kMipsCondCc = 0x3, /* 0011 */
355 kMipsCondMi = 0x4, /* 0100 */
356 kMipsCondPl = 0x5, /* 0101 */
357 kMipsCondVs = 0x6, /* 0110 */
358 kMipsCondVc = 0x7, /* 0111 */
359 kMipsCondHi = 0x8, /* 1000 */
360 kMipsCondLs = 0x9, /* 1001 */
361 kMipsCondGe = 0xa, /* 1010 */
362 kMipsCondLt = 0xb, /* 1011 */
363 kMipsCondGt = 0xc, /* 1100 */
364 kMipsCondLe = 0xd, /* 1101 */
365 kMipsCondAl = 0xe, /* 1110 */
366 kMipsCondNv = 0xf, /* 1111 */
367} MipsConditionCode;
368
369typedef enum MipsThrowKind {
370 kMipsThrowNullPointer,
371 kMipsThrowDivZero,
372 kMipsThrowArrayBounds,
373 kMipsThrowVerificationError,
374 kMipsThrowNegArraySize,
375 kMipsThrowNoSuchMethod,
376 kMipsThrowStackOverflow,
377} MipsThrowKind;
378
379#define isPseudoOpCode(opCode) ((int)(opCode) < 0)
380
381/*
382 * The following enum defines the list of supported Thumb instructions by the
383 * assembler. Their corresponding snippet positions will be defined in
384 * Assemble.c.
385 */
386typedef enum MipsOpCode {
387 kMipsPseudoSuspendTarget = -15,
388 kMipsPseudoThrowTarget = -14,
389 kMipsPseudoCaseLabel = -13,
390 kMipsPseudoMethodEntry = -12,
391 kMipsPseudoMethodExit = -11,
392 kMipsPseudoBarrier = -10,
393 kMipsPseudoExtended = -9,
394 kMipsPseudoSSARep = -8,
395 kMipsPseudoEntryBlock = -7,
396 kMipsPseudoExitBlock = -6,
397 kMipsPseudoTargetLabel = -5,
398 kMipsPseudoDalvikByteCodeBoundary = -4,
399 kMipsPseudoPseudoAlign4 = -3,
400 kMipsPseudoEHBlockLabel = -2,
401 kMipsPseudoNormalBlockLabel = -1,
402
403 kMipsFirst,
404 kMips32BitData = kMipsFirst, /* data [31..0] */
405 kMipsAddiu, /* addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] */
406 kMipsAddu, /* add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001] */
407 kMipsAnd, /* and d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100100] */
408 kMipsAndi, /* andi t,s,imm16 [001100] s[25..21] t[20..16] imm16[15..0] */
409 kMipsB, /* b o [0001000000000000] o[15..0] */
410 kMipsBal, /* bal o [0000010000010001] o[15..0] */
411 /* NOTE: the code tests the range kMipsBeq thru kMipsBne, so
412 adding an instruction in this range may require updates */
413 kMipsBeq, /* beq s,t,o [000100] s[25..21] t[20..16] o[15..0] */
414 kMipsBeqz, /* beqz s,o [000100] s[25..21] [00000] o[15..0] */
415 kMipsBgez, /* bgez s,o [000001] s[25..21] [00001] o[15..0] */
416 kMipsBgtz, /* bgtz s,o [000111] s[25..21] [00000] o[15..0] */
417 kMipsBlez, /* blez s,o [000110] s[25..21] [00000] o[15..0] */
418 kMipsBltz, /* bltz s,o [000001] s[25..21] [00000] o[15..0] */
419 kMipsBnez, /* bnez s,o [000101] s[25..21] [00000] o[15..0] */
420 kMipsBne, /* bne s,t,o [000101] s[25..21] t[20..16] o[15..0] */
421 kMipsDiv, /* div s,t [000000] s[25..21] t[20..16] [0000000000011010] */
422#if __mips_isa_rev>=2
423 kMipsExt, /* ext t,s,p,z [011111] s[25..21] t[20..16] z[15..11] p[10..6] [000000] */
424#endif
425 kMipsJal, /* jal t [000011] t[25..0] */
426 kMipsJalr, /* jalr d,s [000000] s[25..21] [00000] d[15..11]
427 hint[10..6] [001001] */
428 kMipsJr, /* jr s [000000] s[25..21] [0000000000] hint[10..6] [001000] */
429 kMipsLahi, /* lui t,imm16 [00111100000] t[20..16] imm16[15..0] load addr hi */
430 kMipsLalo, /* ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] load addr lo */
431 kMipsLui, /* lui t,imm16 [00111100000] t[20..16] imm16[15..0] */
432 kMipsLb, /* lb t,o(b) [100000] b[25..21] t[20..16] o[15..0] */
433 kMipsLbu, /* lbu t,o(b) [100100] b[25..21] t[20..16] o[15..0] */
434 kMipsLh, /* lh t,o(b) [100001] b[25..21] t[20..16] o[15..0] */
435 kMipsLhu, /* lhu t,o(b) [100101] b[25..21] t[20..16] o[15..0] */
436 kMipsLw, /* lw t,o(b) [100011] b[25..21] t[20..16] o[15..0] */
437 kMipsMfhi, /* mfhi d [0000000000000000] d[15..11] [00000010000] */
438 kMipsMflo, /* mflo d [0000000000000000] d[15..11] [00000010010] */
439 kMipsMove, /* move d,s [000000] s[25..21] [00000] d[15..11] [00000100101] */
440 kMipsMovz, /* movz d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000001010] */
441 kMipsMul, /* mul d,s,t [011100] s[25..21] t[20..16] d[15..11] [00000000010] */
442 kMipsNop, /* nop [00000000000000000000000000000000] */
443 kMipsNor, /* nor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100111] */
444 kMipsOr, /* or d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100101] */
445 kMipsOri, /* ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] */
446 kMipsPref, /* pref h,o(b) [101011] b[25..21] h[20..16] o[15..0] */
447 kMipsSb, /* sb t,o(b) [101000] b[25..21] t[20..16] o[15..0] */
448#if __mips_isa_rev>=2
449 kMipsSeb, /* seb d,t [01111100000] t[20..16] d[15..11] [10000100000] */
450 kMipsSeh, /* seh d,t [01111100000] t[20..16] d[15..11] [11000100000] */
451#endif
452 kMipsSh, /* sh t,o(b) [101001] b[25..21] t[20..16] o[15..0] */
453 kMipsSll, /* sll d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [000000] */
454 kMipsSllv, /* sllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000100] */
455 kMipsSlt, /* slt d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101010] */
456 kMipsSlti, /* slti t,s,imm16 [001010] s[25..21] t[20..16] imm16[15..0] */
457 kMipsSltu, /* sltu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101011] */
458 kMipsSra, /* sra d,s,imm5 [00000000000] t[20..16] d[15..11] imm5[10..6] [000011] */
459 kMipsSrav, /* srav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000111] */
460 kMipsSrl, /* srl d,t,a [00000000000] t[20..16] d[20..16] a[10..6] [000010] */
461 kMipsSrlv, /* srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110] */
462 kMipsSubu, /* subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011] */
463 kMipsSw, /* sw t,o(b) [101011] b[25..21] t[20..16] o[15..0] */
464 kMipsXor, /* xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110] */
465 kMipsXori, /* xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0] */
466#ifdef __mips_hard_float
467 kMipsFadds, /* add.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000000] */
468 kMipsFsubs, /* sub.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000001] */
469 kMipsFmuls, /* mul.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000010] */
470 kMipsFdivs, /* div.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000011] */
471 kMipsFaddd, /* add.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000000] */
472 kMipsFsubd, /* sub.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000001] */
473 kMipsFmuld, /* mul.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000010] */
474 kMipsFdivd, /* div.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000011] */
475 kMipsFcvtsd, /* cvt.s.d d,s [01000110001] [00000] s[15..11] d[10..6] [100000] */
476 kMipsFcvtsw, /* cvt.s.w d,s [01000110100] [00000] s[15..11] d[10..6] [100000] */
477 kMipsFcvtds, /* cvt.d.s d,s [01000110000] [00000] s[15..11] d[10..6] [100001] */
478 kMipsFcvtdw, /* cvt.d.w d,s [01000110100] [00000] s[15..11] d[10..6] [100001] */
479 kMipsFcvtws, /* cvt.w.d d,s [01000110000] [00000] s[15..11] d[10..6] [100100] */
480 kMipsFcvtwd, /* cvt.w.d d,s [01000110001] [00000] s[15..11] d[10..6] [100100] */
481 kMipsFmovs, /* mov.s d,s [01000110000] [00000] s[15..11] d[10..6] [000110] */
482 kMipsFmovd, /* mov.d d,s [01000110001] [00000] s[15..11] d[10..6] [000110] */
483 kMipsFlwc1, /* lwc1 t,o(b) [110001] b[25..21] t[20..16] o[15..0] */
484 kMipsFldc1, /* ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0] */
485 kMipsFswc1, /* swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0] */
486 kMipsFsdc1, /* sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0] */
487 kMipsMfc1, /* mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000] */
488 kMipsMtc1, /* mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000] */
489#endif
490 kMipsUndefined, /* undefined [011001xxxxxxxxxxxxxxxx] */
491 kMipsLast
492} MipsOpCode;
493
494/* Bit flags describing the behavior of each native opcode */
495typedef enum MipsOpFeatureFlags {
496 kIsBranch = 0,
497 kRegDef0,
498 kRegDef1,
499 kRegDefSP,
500 kRegDefLR,
501 kRegDefList0,
502 kRegDefList1,
503 kRegUse0,
504 kRegUse1,
505 kRegUse2,
506 kRegUse3,
507 kRegUseSP,
508 kRegUsePC,
509 kRegUseList0,
510 kRegUseList1,
511 kNoOperand,
512 kIsUnaryOp,
513 kIsBinaryOp,
514 kIsTertiaryOp,
515 kIsQuadOp,
516 kIsIT,
517 kSetsCCodes,
518 kUsesCCodes,
519 kMemLoad,
520 kMemStore,
521} MipsOpFeatureFlags;
522
523#define IS_LOAD (1 << kMemLoad)
524#define IS_STORE (1 << kMemStore)
525#define IS_BRANCH (1 << kIsBranch)
526#define REG_DEF0 (1 << kRegDef0)
527#define REG_DEF1 (1 << kRegDef1)
528#define REG_DEF_SP (1 << kRegDefSP)
529#define REG_DEF_LR (1 << kRegDefLR)
530#define REG_DEF_LIST0 (1 << kRegDefList0)
531#define REG_DEF_LIST1 (1 << kRegDefList1)
532#define REG_USE0 (1 << kRegUse0)
533#define REG_USE1 (1 << kRegUse1)
534#define REG_USE2 (1 << kRegUse2)
535#define REG_USE3 (1 << kRegUse3)
536#define REG_USE_SP (1 << kRegUseSP)
537#define REG_USE_PC (1 << kRegUsePC)
538#define REG_USE_LIST0 (1 << kRegUseList0)
539#define REG_USE_LIST1 (1 << kRegUseList1)
540#define NO_OPERAND (1 << kNoOperand)
541#define IS_UNARY_OP (1 << kIsUnaryOp)
542#define IS_BINARY_OP (1 << kIsBinaryOp)
543#define IS_TERTIARY_OP (1 << kIsTertiaryOp)
544#define IS_QUAD_OP (1 << kIsQuadOp)
545#define IS_IT (1 << kIsIT)
546#define SETS_CCODES (1 << kSetsCCodes)
547#define USES_CCODES (1 << kUsesCCodes)
548
549/* Common combo register usage patterns */
550#define REG_USE01 (REG_USE0 | REG_USE1)
551#define REG_USE02 (REG_USE0 | REG_USE2)
552#define REG_USE012 (REG_USE01 | REG_USE2)
553#define REG_USE12 (REG_USE1 | REG_USE2)
554#define REG_USE23 (REG_USE2 | REG_USE3)
555#define REG_DEF01 (REG_DEF0 | REG_DEF1)
556#define REG_DEF0_USE0 (REG_DEF0 | REG_USE0)
557#define REG_DEF0_USE1 (REG_DEF0 | REG_USE1)
558#define REG_DEF0_USE2 (REG_DEF0 | REG_USE2)
559#define REG_DEF0_USE01 (REG_DEF0 | REG_USE01)
560#define REG_DEF0_USE12 (REG_DEF0 | REG_USE12)
561#define REG_DEF01_USE2 (REG_DEF0 | REG_DEF1 | REG_USE2)
562
563/* Instruction assembly fieldLoc kind */
564typedef enum MipsEncodingKind {
565 kFmtUnused,
566 kFmtBitBlt, /* Bit string using end/start */
567 kFmtDfp, /* Double FP reg */
568 kFmtSfp, /* Single FP reg */
569} MipsEncodingKind;
570
571/* Struct used to define the snippet positions for each Thumb opcode */
572typedef struct MipsEncodingMap {
573 u4 skeleton;
574 struct {
575 MipsEncodingKind kind;
576 int end; /* end for kFmtBitBlt, 1-bit slice end for FP regs */
577 int start; /* start for kFmtBitBlt, 4-bit slice end for FP regs */
578 } fieldLoc[4];
579 MipsOpCode opcode;
580 int flags;
581 const char *name;
582 const char* fmt;
583 int size;
584} MipsEncodingMap;
585
586/* Keys for target-specific scheduling and other optimization hints */
587typedef enum MipsTargetOptHints {
588 kMaxHoistDistance,
589} MipsTargetOptHints;
590
591extern MipsEncodingMap EncodingMap[kMipsLast];
592
593/*
594 * Each instance of this struct holds a pseudo or real LIR instruction:
595 * - pseudo ones (eg labels and marks) and will be discarded by the assembler.
596 * - real ones will be assembled
597 *
598 * FIXME: notes below are Arm-specific. We have 32 core registers instead
599 * of 16, and no IT blocks. Must widen this or overload in order to
600 * support all 32 FP regs. Perhaps use r0 for ccodes, eliminate IT block
601 * and overload gp with fp status word? (or just use a single bit for
602 * both core and fp condition code/status word?
603 *
604 * Machine resources are encoded into a 64-bit vector, where the encodings are
605 * as following:
606 * - [ 0..15]: general purpose registers including PC, SP, and LR
607 * - [16..47]: floating-point registers where d0 is expanded to s[01] and s0
608 * starts at bit 16
609 * - [48]: IT block
610 * - [49]: integer condition code
611 * - [50]: floatint-point status word
612 */
613typedef struct MipsLIR {
614 LIR generic;
615 MipsOpCode opcode;
616 int operands[4]; // [0..3] = [dest, src1, src2, extra]
617 struct {
618 bool isNop:1; // LIR is optimized away
619 bool pcRelFixup:1; // May need pc-relative fixup
620 unsigned int age:4; // default is 0, set lazily by the optimizer
621 unsigned int size:3; // in bytes
622 unsigned int unused:23;
623 } flags;
624 int aliasInfo; // For Dalvik register access & litpool disambiguation
625 u8 useMask; // Resource mask for use
626 u8 defMask; // Resource mask for def
627} MipsLIR;
628
629typedef struct SwitchTable {
630 int offset;
631 const u2* table; // Original dex table
632 int vaddr; // Dalvik offset of switch opcode
633 MipsLIR* bxInst; // Switch indirect branch instruction
634 MipsLIR** targets; // Array of case targets
635} SwitchTable;
636
637typedef struct FillArrayData {
638 int offset;
639 const u2* table; // Original dex table
640 int size;
641 int vaddr; // Dalvik offset of OP_FILL_ARRAY_DATA opcode
642} FillArrayData;
643
644/* Utility macros to traverse the LIR/MipsLIR list */
645#define NEXT_LIR(lir) ((MipsLIR *) lir->generic.next)
646#define PREV_LIR(lir) ((MipsLIR *) lir->generic.prev)
647
648#define NEXT_LIR_LVALUE(lir) (lir)->generic.next
649#define PREV_LIR_LVALUE(lir) (lir)->generic.prev
650
651#define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535))
652#define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766))
653#define IS_SIMM16_2WORD(v) ((-32764 <= (v)) && ((v) <= 32763)) /* 2 offsets must fit */
654
655} // namespace art
656
657#endif // ART_COMPILER_COMPILER_CODEGEN_MIPS_MIPSLIR_H_