blob: 3063e6951836e5effe226f36a684e1fbbd354b7b [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#include "../../CompilerInternals.h"
18#include "MipsLIR.h"
19#include "../Ralloc.h"
20
21#include <string>
22
23namespace art {
24
buzbeef0504cd2012-11-13 16:31:10 -080025RegLocation locCReturn()
26{
27 RegLocation res = MIPS_LOC_C_RETURN;
28 return res;
29}
30
31RegLocation locCReturnWide()
32{
33 RegLocation res = MIPS_LOC_C_RETURN_WIDE;
34 return res;
35}
36
37RegLocation locCReturnFloat()
38{
39 RegLocation res = MIPS_LOC_C_RETURN_FLOAT;
40 return res;
41}
42
43RegLocation locCReturnDouble()
44{
45 RegLocation res = MIPS_LOC_C_RETURN_DOUBLE;
46 return res;
47}
48
49// Return a target-dependent special register.
50int targetReg(SpecialTargetRegister reg) {
51 int res = INVALID_REG;
52 switch (reg) {
53 case kSelf: res = rMIPS_SELF; break;
54 case kSuspend: res = rMIPS_SUSPEND; break;
55 case kLr: res = rMIPS_LR; break;
56 case kPc: res = rMIPS_PC; break;
57 case kSp: res = rMIPS_SP; break;
58 case kArg0: res = rMIPS_ARG0; break;
59 case kArg1: res = rMIPS_ARG1; break;
60 case kArg2: res = rMIPS_ARG2; break;
61 case kArg3: res = rMIPS_ARG3; break;
62 case kFArg0: res = rMIPS_FARG0; break;
63 case kFArg1: res = rMIPS_FARG1; break;
64 case kFArg2: res = rMIPS_FARG2; break;
65 case kFArg3: res = rMIPS_FARG3; break;
66 case kRet0: res = rMIPS_RET0; break;
67 case kRet1: res = rMIPS_RET1; break;
68 case kInvokeTgt: res = rMIPS_INVOKE_TGT; break;
69 case kCount: res = rMIPS_COUNT; break;
70 }
71 return res;
72}
73
74// Create a double from a pair of singles.
75int s2d(int lowReg, int highReg)
76{
77 return MIPS_S2D(lowReg, highReg);
78}
79
80// Is reg a single or double?
81bool fpReg(int reg)
82{
83 return MIPS_FPREG(reg);
84}
85
86// Is reg a single?
87bool singleReg(int reg)
88{
89 return MIPS_SINGLEREG(reg);
90}
91
92// Is reg a double?
93bool doubleReg(int reg)
94{
95 return MIPS_DOUBLEREG(reg);
96}
97
98// Return mask to strip off fp reg flags and bias.
99uint32_t fpRegMask()
100{
101 return MIPS_FP_REG_MASK;
102}
103
104// True if both regs single, both core or both double.
105bool sameRegType(int reg1, int reg2)
106{
107 return (MIPS_REGTYPE(reg1) == MIPS_REGTYPE(reg2));
108}
109
buzbeeec137432012-11-13 12:13:16 -0800110/*
111 * Decode the register id.
112 */
113u8 getRegMaskCommon(CompilationUnit* cUnit, int reg)
114{
115 u8 seed;
116 int shift;
117 int regId;
118
119
120 regId = reg & 0x1f;
121 /* Each double register is equal to a pair of single-precision FP registers */
buzbeef0504cd2012-11-13 16:31:10 -0800122 seed = MIPS_DOUBLEREG(reg) ? 3 : 1;
buzbeeec137432012-11-13 12:13:16 -0800123 /* FP register starts at bit position 16 */
buzbeef0504cd2012-11-13 16:31:10 -0800124 shift = MIPS_FPREG(reg) ? kMipsFPReg0 : 0;
buzbeeec137432012-11-13 12:13:16 -0800125 /* Expand the double register id into single offset */
126 shift += regId;
127 return (seed << shift);
128}
129
130uint64_t getPCUseDefEncoding()
131{
132 return ENCODE_MIPS_REG_PC;
133}
134
135
buzbeeb046e162012-10-30 15:48:42 -0700136void setupTargetResourceMasks(CompilationUnit* cUnit, LIR* lir)
137{
138 DCHECK_EQ(cUnit->instructionSet, kMips);
139
140 // Mips-specific resource map setup here.
buzbeeec137432012-11-13 12:13:16 -0800141 uint64_t flags = EncodingMap[lir->opcode].flags;
142
143 if (flags & REG_DEF_SP) {
144 lir->defMask |= ENCODE_MIPS_REG_SP;
145 }
146
147 if (flags & REG_USE_SP) {
148 lir->useMask |= ENCODE_MIPS_REG_SP;
149 }
150
buzbeeb046e162012-10-30 15:48:42 -0700151 if (flags & REG_DEF_LR) {
buzbeeec137432012-11-13 12:13:16 -0800152 lir->defMask |= ENCODE_MIPS_REG_LR;
buzbeeb046e162012-10-30 15:48:42 -0700153 }
154}
155
buzbeee3acd072012-02-25 17:03:10 -0800156/* For dumping instructions */
157#define MIPS_REG_COUNT 32
158static const char *mipsRegName[MIPS_REG_COUNT] = {
Bill Buzbeea114add2012-05-03 15:00:40 -0700159 "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
160 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
161 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
162 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
buzbeee3acd072012-02-25 17:03:10 -0800163};
164
165/*
166 * Interpret a format string and build a string no longer than size
167 * See format key in Assemble.c.
168 */
buzbee5de34942012-03-01 14:51:57 -0800169std::string buildInsnString(const char *fmt, LIR *lir, unsigned char* baseAddr)
buzbeee3acd072012-02-25 17:03:10 -0800170{
Bill Buzbeea114add2012-05-03 15:00:40 -0700171 std::string buf;
172 int i;
173 const char *fmtEnd = &fmt[strlen(fmt)];
174 char tbuf[256];
175 char nc;
176 while (fmt < fmtEnd) {
177 int operand;
178 if (*fmt == '!') {
179 fmt++;
180 DCHECK_LT(fmt, fmtEnd);
181 nc = *fmt++;
182 if (nc=='!') {
183 strcpy(tbuf, "!");
184 } else {
185 DCHECK_LT(fmt, fmtEnd);
186 DCHECK_LT((unsigned)(nc-'0'), 4u);
187 operand = lir->operands[nc-'0'];
188 switch (*fmt++) {
189 case 'b':
190 strcpy(tbuf,"0000");
191 for (i=3; i>= 0; i--) {
192 tbuf[i] += operand & 1;
193 operand >>= 1;
194 }
195 break;
196 case 's':
buzbeef0504cd2012-11-13 16:31:10 -0800197 sprintf(tbuf,"$f%d",operand & MIPS_FP_REG_MASK);
Bill Buzbeea114add2012-05-03 15:00:40 -0700198 break;
199 case 'S':
buzbeef0504cd2012-11-13 16:31:10 -0800200 DCHECK_EQ(((operand & MIPS_FP_REG_MASK) & 1), 0);
201 sprintf(tbuf,"$f%d",operand & MIPS_FP_REG_MASK);
Bill Buzbeea114add2012-05-03 15:00:40 -0700202 break;
203 case 'h':
204 sprintf(tbuf,"%04x", operand);
205 break;
206 case 'M':
207 case 'd':
208 sprintf(tbuf,"%d", operand);
209 break;
210 case 'D':
211 sprintf(tbuf,"%d", operand+1);
212 break;
213 case 'E':
214 sprintf(tbuf,"%d", operand*4);
215 break;
216 case 'F':
217 sprintf(tbuf,"%d", operand*2);
218 break;
219 case 't':
220 sprintf(tbuf,"0x%08x (L%p)", (int) baseAddr + lir->offset + 4 +
221 (operand << 2), lir->target);
222 break;
223 case 'T':
224 sprintf(tbuf,"0x%08x", (int) (operand << 2));
225 break;
226 case 'u': {
227 int offset_1 = lir->operands[0];
228 int offset_2 = NEXT_LIR(lir)->operands[0];
229 intptr_t target =
230 ((((intptr_t) baseAddr + lir->offset + 4) & ~3) +
231 (offset_1 << 21 >> 9) + (offset_2 << 1)) & 0xfffffffc;
232 sprintf(tbuf, "%p", (void *) target);
233 break;
234 }
buzbeee3acd072012-02-25 17:03:10 -0800235
Bill Buzbeea114add2012-05-03 15:00:40 -0700236 /* Nothing to print for BLX_2 */
237 case 'v':
238 strcpy(tbuf, "see above");
239 break;
240 case 'r':
241 DCHECK(operand >= 0 && operand < MIPS_REG_COUNT);
242 strcpy(tbuf, mipsRegName[operand]);
243 break;
244 case 'N':
245 // Placeholder for delay slot handling
246 strcpy(tbuf, "; nop");
247 break;
248 default:
249 strcpy(tbuf,"DecodeError");
250 break;
251 }
252 buf += tbuf;
253 }
254 } else {
255 buf += *fmt++;
buzbeee3acd072012-02-25 17:03:10 -0800256 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700257 }
258 return buf;
buzbeee3acd072012-02-25 17:03:10 -0800259}
260
buzbee408ad162012-06-06 16:45:18 -0700261// FIXME: need to redo resource maps for MIPS - fix this at that time
buzbeee3acd072012-02-25 17:03:10 -0800262void oatDumpResourceMask(LIR *lir, u8 mask, const char *prefix)
263{
Bill Buzbeea114add2012-05-03 15:00:40 -0700264 char buf[256];
265 buf[0] = 0;
266 LIR *mipsLIR = (LIR *) lir;
buzbeee3acd072012-02-25 17:03:10 -0800267
Bill Buzbeea114add2012-05-03 15:00:40 -0700268 if (mask == ENCODE_ALL) {
269 strcpy(buf, "all");
270 } else {
271 char num[8];
272 int i;
buzbeee3acd072012-02-25 17:03:10 -0800273
buzbeeec137432012-11-13 12:13:16 -0800274 for (i = 0; i < kMipsRegEnd; i++) {
Bill Buzbeea114add2012-05-03 15:00:40 -0700275 if (mask & (1ULL << i)) {
276 sprintf(num, "%d ", i);
277 strcat(buf, num);
278 }
buzbeee3acd072012-02-25 17:03:10 -0800279 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700280
281 if (mask & ENCODE_CCODE) {
282 strcat(buf, "cc ");
buzbeee3acd072012-02-25 17:03:10 -0800283 }
Bill Buzbeea114add2012-05-03 15:00:40 -0700284 if (mask & ENCODE_FP_STATUS) {
285 strcat(buf, "fpcc ");
286 }
287 /* Memory bits */
288 if (mipsLIR && (mask & ENCODE_DALVIK_REG)) {
289 sprintf(buf + strlen(buf), "dr%d%s", mipsLIR->aliasInfo & 0xffff,
290 (mipsLIR->aliasInfo & 0x80000000) ? "(+1)" : "");
291 }
292 if (mask & ENCODE_LITERAL) {
293 strcat(buf, "lit ");
294 }
295
296 if (mask & ENCODE_HEAP_REF) {
297 strcat(buf, "heap ");
298 }
299 if (mask & ENCODE_MUST_NOT_ALIAS) {
300 strcat(buf, "noalias ");
301 }
302 }
303 if (buf[0]) {
304 LOG(INFO) << prefix << ": " << buf;
305 }
buzbeee3acd072012-02-25 17:03:10 -0800306}
307
buzbeee3acd072012-02-25 17:03:10 -0800308} // namespace art