1 /* 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_DEX_QUICK_MIPS_MIPS_LIR_H_ 18 #define ART_COMPILER_DEX_QUICK_MIPS_MIPS_LIR_H_ 19 20 #include "dex/compiler_internals.h" 21 22 namespace art { 23 24 /* 25 * Runtime register conventions. 26 * 27 * zero is always the value 0 28 * at is scratch (normally used as temp reg by assembler) 29 * v0, v1 are scratch (normally hold subroutine return values) 30 * a0-a3 are scratch (normally hold subroutine arguments) 31 * t0-t8 are scratch 32 * t9 is scratch (normally used for function calls) 33 * s0 (rMIPS_SUSPEND) is reserved [holds suspend-check counter] 34 * s1 (rMIPS_SELF) is reserved [holds current &Thread] 35 * s2-s7 are callee save (promotion target) 36 * k0, k1 are reserved for use by interrupt handlers 37 * gp is reserved for global pointer 38 * sp is reserved 39 * s8 is callee save (promotion target) 40 * ra is scratch (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 currently 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 * Stack frame diagram (stack grows down, higher addresses at top): 61 * 62 * +------------------------+ 63 * | IN[ins-1] | {Note: resides in caller's frame} 64 * | . | 65 * | IN[0] | 66 * | caller's Method* | 67 * +========================+ {Note: start of callee's frame} 68 * | spill region | {variable sized - will include lr if non-leaf.} 69 * +------------------------+ 70 * | ...filler word... | {Note: used as 2nd word of V[locals-1] if long] 71 * +------------------------+ 72 * | V[locals-1] | 73 * | V[locals-2] | 74 * | . | 75 * | . | 76 * | V[1] | 77 * | V[0] | 78 * +------------------------+ 79 * | 0 to 3 words padding | 80 * +------------------------+ 81 * | OUT[outs-1] | 82 * | OUT[outs-2] | 83 * | . | 84 * | OUT[0] | 85 * | cur_method* | <<== sp w/ 16-byte alignment 86 * +========================+ 87 */ 88 89 // Offset to distingish FP regs. 90 #define MIPS_FP_REG_OFFSET 32 91 // Offset to distinguish DP FP regs. 92 #define MIPS_FP_DOUBLE 64 93 // Offset to distingish the extra regs. 94 #define MIPS_EXTRA_REG_OFFSET 128 95 // Reg types. 96 #define MIPS_REGTYPE(x) (x & (MIPS_FP_REG_OFFSET | MIPS_FP_DOUBLE)) 97 #define MIPS_FPREG(x) ((x & MIPS_FP_REG_OFFSET) == MIPS_FP_REG_OFFSET) 98 #define MIPS_EXTRAREG(x) ((x & MIPS_EXTRA_REG_OFFSET) == MIPS_EXTRA_REG_OFFSET) 99 #define MIPS_DOUBLEREG(x) ((x & MIPS_FP_DOUBLE) == MIPS_FP_DOUBLE) 100 #define MIPS_SINGLEREG(x) (MIPS_FPREG(x) && !MIPS_DOUBLEREG(x)) 101 /* 102 * Note: the low register of a floating point pair is sufficient to 103 * create the name of a double, but require both names to be passed to 104 * allow for asserts to verify that the pair is consecutive if significant 105 * rework is done in this area. Also, it is a good reminder in the calling 106 * code that reg locations always describe doubles as a pair of singles. 107 */ 108 #define MIPS_S2D(x, y) ((x) | MIPS_FP_DOUBLE) 109 // Mask to strip off fp flags. 110 #define MIPS_FP_REG_MASK (MIPS_FP_REG_OFFSET-1) 111 112 #ifdef HAVE_LITTLE_ENDIAN 113 #define LOWORD_OFFSET 0 114 #define HIWORD_OFFSET 4 115 #define r_ARG0 r_A0 116 #define r_ARG1 r_A1 117 #define r_ARG2 r_A2 118 #define r_ARG3 r_A3 119 #define r_RESULT0 r_V0 120 #define r_RESULT1 r_V1 121 #else 122 #define LOWORD_OFFSET 4 123 #define HIWORD_OFFSET 0 124 #define r_ARG0 r_A1 125 #define r_ARG1 r_A0 126 #define r_ARG2 r_A3 127 #define r_ARG3 r_A2 128 #define r_RESULT0 r_V1 129 #define r_RESULT1 r_V0 130 #endif 131 132 // These are the same for both big and little endian. 133 #define r_FARG0 r_F12 134 #define r_FARG1 r_F13 135 #define r_FARG2 r_F14 136 #define r_FARG3 r_F15 137 #define r_FRESULT0 r_F0 138 #define r_FRESULT1 r_F1 139 140 // Regs not used for Mips. 141 #define rMIPS_PC INVALID_REG 142 143 // RegisterLocation templates return values (r_V0, or r_V0/r_V1). 144 #define MIPS_LOC_C_RETURN {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, r_V0, INVALID_REG, \ 145 INVALID_SREG, INVALID_SREG} 146 #define MIPS_LOC_C_RETURN_FLOAT {kLocPhysReg, 0, 0, 0, 0, 0, 0, 0, 1, r_FRESULT0, \ 147 INVALID_REG, INVALID_SREG, INVALID_SREG} 148 #define MIPS_LOC_C_RETURN_WIDE {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r_RESULT0, \ 149 r_RESULT1, INVALID_SREG, INVALID_SREG} 150 #define MIPS_LOC_C_RETURN_DOUBLE {kLocPhysReg, 1, 0, 0, 0, 0, 0, 0, 1, r_FRESULT0, \ 151 r_FRESULT1, INVALID_SREG, INVALID_SREG} 152 153 enum MipsResourceEncodingPos { 154 kMipsGPReg0 = 0, 155 kMipsRegSP = 29, 156 kMipsRegLR = 31, 157 kMipsFPReg0 = 32, // only 16 fp regs supported currently. 158 kMipsFPRegEnd = 48, 159 kMipsRegHI = kMipsFPRegEnd, 160 kMipsRegLO, 161 kMipsRegPC, 162 kMipsRegEnd = 51, 163 }; 164 165 #define ENCODE_MIPS_REG_LIST(N) (static_cast<uint64_t>(N)) 166 #define ENCODE_MIPS_REG_SP (1ULL << kMipsRegSP) 167 #define ENCODE_MIPS_REG_LR (1ULL << kMipsRegLR) 168 #define ENCODE_MIPS_REG_PC (1ULL << kMipsRegPC) 169 170 enum MipsNativeRegisterPool { 171 r_ZERO = 0, 172 r_AT = 1, 173 r_V0 = 2, 174 r_V1 = 3, 175 r_A0 = 4, 176 r_A1 = 5, 177 r_A2 = 6, 178 r_A3 = 7, 179 r_T0 = 8, 180 r_T1 = 9, 181 r_T2 = 10, 182 r_T3 = 11, 183 r_T4 = 12, 184 r_T5 = 13, 185 r_T6 = 14, 186 r_T7 = 15, 187 r_S0 = 16, 188 r_S1 = 17, 189 r_S2 = 18, 190 r_S3 = 19, 191 r_S4 = 20, 192 r_S5 = 21, 193 r_S6 = 22, 194 r_S7 = 23, 195 r_T8 = 24, 196 r_T9 = 25, 197 r_K0 = 26, 198 r_K1 = 27, 199 r_GP = 28, 200 r_SP = 29, 201 r_FP = 30, 202 r_RA = 31, 203 204 r_F0 = 0 + MIPS_FP_REG_OFFSET, 205 r_F1, 206 r_F2, 207 r_F3, 208 r_F4, 209 r_F5, 210 r_F6, 211 r_F7, 212 r_F8, 213 r_F9, 214 r_F10, 215 r_F11, 216 r_F12, 217 r_F13, 218 r_F14, 219 r_F15, 220 #if 0 221 /* 222 * TODO: The shared resource mask doesn't have enough bit positions to describe all 223 * MIPS registers. Expand it and enable use of fp registers 16 through 31. 224 */ 225 r_F16, 226 r_F17, 227 r_F18, 228 r_F19, 229 r_F20, 230 r_F21, 231 r_F22, 232 r_F23, 233 r_F24, 234 r_F25, 235 r_F26, 236 r_F27, 237 r_F28, 238 r_F29, 239 r_F30, 240 r_F31, 241 #endif 242 r_DF0 = r_F0 + MIPS_FP_DOUBLE, 243 r_DF1 = r_F2 + MIPS_FP_DOUBLE, 244 r_DF2 = r_F4 + MIPS_FP_DOUBLE, 245 r_DF3 = r_F6 + MIPS_FP_DOUBLE, 246 r_DF4 = r_F8 + MIPS_FP_DOUBLE, 247 r_DF5 = r_F10 + MIPS_FP_DOUBLE, 248 r_DF6 = r_F12 + MIPS_FP_DOUBLE, 249 r_DF7 = r_F14 + MIPS_FP_DOUBLE, 250 #if 0 // TODO: expand resource mask to enable use of all MIPS fp registers. 251 r_DF8 = r_F16 + MIPS_FP_DOUBLE, 252 r_DF9 = r_F18 + MIPS_FP_DOUBLE, 253 r_DF10 = r_F20 + MIPS_FP_DOUBLE, 254 r_DF11 = r_F22 + MIPS_FP_DOUBLE, 255 r_DF12 = r_F24 + MIPS_FP_DOUBLE, 256 r_DF13 = r_F26 + MIPS_FP_DOUBLE, 257 r_DF14 = r_F28 + MIPS_FP_DOUBLE, 258 r_DF15 = r_F30 + MIPS_FP_DOUBLE, 259 #endif 260 r_HI = MIPS_EXTRA_REG_OFFSET, 261 r_LO, 262 r_PC, 263 }; 264 265 #define rMIPS_SUSPEND r_S0 266 #define rMIPS_SELF r_S1 267 #define rMIPS_SP r_SP 268 #define rMIPS_ARG0 r_ARG0 269 #define rMIPS_ARG1 r_ARG1 270 #define rMIPS_ARG2 r_ARG2 271 #define rMIPS_ARG3 r_ARG3 272 #define rMIPS_FARG0 r_FARG0 273 #define rMIPS_FARG1 r_FARG1 274 #define rMIPS_FARG2 r_FARG2 275 #define rMIPS_FARG3 r_FARG3 276 #define rMIPS_RET0 r_RESULT0 277 #define rMIPS_RET1 r_RESULT1 278 #define rMIPS_INVOKE_TGT r_T9 279 #define rMIPS_COUNT INVALID_REG 280 #define rMIPS_LR r_RA 281 282 enum MipsShiftEncodings { 283 kMipsLsl = 0x0, 284 kMipsLsr = 0x1, 285 kMipsAsr = 0x2, 286 kMipsRor = 0x3 287 }; 288 289 // MIPS sync kinds (Note: support for kinds other than kSYNC0 may not exist). 290 #define kSYNC0 0x00 291 #define kSYNC_WMB 0x04 292 #define kSYNC_MB 0x01 293 #define kSYNC_ACQUIRE 0x11 294 #define kSYNC_RELEASE 0x12 295 #define kSYNC_RMB 0x13 296 297 // TODO: Use smaller hammer when appropriate for target CPU. 298 #define kST kSYNC0 299 #define kSY kSYNC0 300 301 /* 302 * The following enum defines the list of supported Thumb instructions by the 303 * assembler. Their corresponding EncodingMap positions will be defined in 304 * Assemble.cc. 305 */ 306 enum MipsOpCode { 307 kMipsFirst = 0, 308 kMips32BitData = kMipsFirst, // data [31..0]. 309 kMipsAddiu, // addiu t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0]. 310 kMipsAddu, // add d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100001]. 311 kMipsAnd, // and d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100100]. 312 kMipsAndi, // andi t,s,imm16 [001100] s[25..21] t[20..16] imm16[15..0]. 313 kMipsB, // b o [0001000000000000] o[15..0]. 314 kMipsBal, // bal o [0000010000010001] o[15..0]. 315 // NOTE: the code tests the range kMipsBeq thru kMipsBne, so adding an instruction in this 316 // range may require updates. 317 kMipsBeq, // beq s,t,o [000100] s[25..21] t[20..16] o[15..0]. 318 kMipsBeqz, // beqz s,o [000100] s[25..21] [00000] o[15..0]. 319 kMipsBgez, // bgez s,o [000001] s[25..21] [00001] o[15..0]. 320 kMipsBgtz, // bgtz s,o [000111] s[25..21] [00000] o[15..0]. 321 kMipsBlez, // blez s,o [000110] s[25..21] [00000] o[15..0]. 322 kMipsBltz, // bltz s,o [000001] s[25..21] [00000] o[15..0]. 323 kMipsBnez, // bnez s,o [000101] s[25..21] [00000] o[15..0]. 324 kMipsBne, // bne s,t,o [000101] s[25..21] t[20..16] o[15..0]. 325 kMipsDiv, // div s,t [000000] s[25..21] t[20..16] [0000000000011010]. 326 #if __mips_isa_rev >= 2 327 kMipsExt, // ext t,s,p,z [011111] s[25..21] t[20..16] z[15..11] p[10..6] [000000]. 328 #endif 329 kMipsJal, // jal t [000011] t[25..0]. 330 kMipsJalr, // jalr d,s [000000] s[25..21] [00000] d[15..11] hint[10..6] [001001]. 331 kMipsJr, // jr s [000000] s[25..21] [0000000000] hint[10..6] [001000]. 332 kMipsLahi, // lui t,imm16 [00111100000] t[20..16] imm16[15..0] load addr hi. 333 kMipsLalo, // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0] load addr lo. 334 kMipsLui, // lui t,imm16 [00111100000] t[20..16] imm16[15..0]. 335 kMipsLb, // lb t,o(b) [100000] b[25..21] t[20..16] o[15..0]. 336 kMipsLbu, // lbu t,o(b) [100100] b[25..21] t[20..16] o[15..0]. 337 kMipsLh, // lh t,o(b) [100001] b[25..21] t[20..16] o[15..0]. 338 kMipsLhu, // lhu t,o(b) [100101] b[25..21] t[20..16] o[15..0]. 339 kMipsLw, // lw t,o(b) [100011] b[25..21] t[20..16] o[15..0]. 340 kMipsMfhi, // mfhi d [0000000000000000] d[15..11] [00000010000]. 341 kMipsMflo, // mflo d [0000000000000000] d[15..11] [00000010010]. 342 kMipsMove, // move d,s [000000] s[25..21] [00000] d[15..11] [00000100101]. 343 kMipsMovz, // movz d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000001010]. 344 kMipsMul, // mul d,s,t [011100] s[25..21] t[20..16] d[15..11] [00000000010]. 345 kMipsNop, // nop [00000000000000000000000000000000]. 346 kMipsNor, // nor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100111]. 347 kMipsOr, // or d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100101]. 348 kMipsOri, // ori t,s,imm16 [001001] s[25..21] t[20..16] imm16[15..0]. 349 kMipsPref, // pref h,o(b) [101011] b[25..21] h[20..16] o[15..0]. 350 kMipsSb, // sb t,o(b) [101000] b[25..21] t[20..16] o[15..0]. 351 #if __mips_isa_rev >= 2 352 kMipsSeb, // seb d,t [01111100000] t[20..16] d[15..11] [10000100000]. 353 kMipsSeh, // seh d,t [01111100000] t[20..16] d[15..11] [11000100000]. 354 #endif 355 kMipsSh, // sh t,o(b) [101001] b[25..21] t[20..16] o[15..0]. 356 kMipsSll, // sll d,t,a [00000000000] t[20..16] d[15..11] a[10..6] [000000]. 357 kMipsSllv, // sllv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000100]. 358 kMipsSlt, // slt d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101010]. 359 kMipsSlti, // slti t,s,imm16 [001010] s[25..21] t[20..16] imm16[15..0]. 360 kMipsSltu, // sltu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000101011]. 361 kMipsSra, // sra d,s,imm5 [00000000000] t[20..16] d[15..11] imm5[10..6] [000011]. 362 kMipsSrav, // srav d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000111]. 363 kMipsSrl, // srl d,t,a [00000000000] t[20..16] d[20..16] a[10..6] [000010]. 364 kMipsSrlv, // srlv d,t,s [000000] s[25..21] t[20..16] d[15..11] [00000000110]. 365 kMipsSubu, // subu d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100011]. 366 kMipsSw, // sw t,o(b) [101011] b[25..21] t[20..16] o[15..0]. 367 kMipsXor, // xor d,s,t [000000] s[25..21] t[20..16] d[15..11] [00000100110]. 368 kMipsXori, // xori t,s,imm16 [001110] s[25..21] t[20..16] imm16[15..0]. 369 kMipsFadds, // add.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000000]. 370 kMipsFsubs, // sub.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000001]. 371 kMipsFmuls, // mul.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000010]. 372 kMipsFdivs, // div.s d,s,t [01000110000] t[20..16] s[15..11] d[10..6] [000011]. 373 kMipsFaddd, // add.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000000]. 374 kMipsFsubd, // sub.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000001]. 375 kMipsFmuld, // mul.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000010]. 376 kMipsFdivd, // div.d d,s,t [01000110001] t[20..16] s[15..11] d[10..6] [000011]. 377 kMipsFcvtsd, // cvt.s.d d,s [01000110001] [00000] s[15..11] d[10..6] [100000]. 378 kMipsFcvtsw, // cvt.s.w d,s [01000110100] [00000] s[15..11] d[10..6] [100000]. 379 kMipsFcvtds, // cvt.d.s d,s [01000110000] [00000] s[15..11] d[10..6] [100001]. 380 kMipsFcvtdw, // cvt.d.w d,s [01000110100] [00000] s[15..11] d[10..6] [100001]. 381 kMipsFcvtws, // cvt.w.d d,s [01000110000] [00000] s[15..11] d[10..6] [100100]. 382 kMipsFcvtwd, // cvt.w.d d,s [01000110001] [00000] s[15..11] d[10..6] [100100]. 383 kMipsFmovs, // mov.s d,s [01000110000] [00000] s[15..11] d[10..6] [000110]. 384 kMipsFmovd, // mov.d d,s [01000110001] [00000] s[15..11] d[10..6] [000110]. 385 kMipsFlwc1, // lwc1 t,o(b) [110001] b[25..21] t[20..16] o[15..0]. 386 kMipsFldc1, // ldc1 t,o(b) [110101] b[25..21] t[20..16] o[15..0]. 387 kMipsFswc1, // swc1 t,o(b) [111001] b[25..21] t[20..16] o[15..0]. 388 kMipsFsdc1, // sdc1 t,o(b) [111101] b[25..21] t[20..16] o[15..0]. 389 kMipsMfc1, // mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000]. 390 kMipsMtc1, // mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000]. 391 kMipsDelta, // Psuedo for ori t, s, <label>-<label>. 392 kMipsDeltaHi, // Pseudo for lui t, high16(<label>-<label>). 393 kMipsDeltaLo, // Pseudo for ori t, s, low16(<label>-<label>). 394 kMipsCurrPC, // jal to .+8 to materialize pc. 395 kMipsSync, // sync kind [000000] [0000000000000000] s[10..6] [001111]. 396 kMipsUndefined, // undefined [011001xxxxxxxxxxxxxxxx]. 397 kMipsLast 398 }; 399 400 // Instruction assembly field_loc kind. 401 enum MipsEncodingKind { 402 kFmtUnused, 403 kFmtBitBlt, /* Bit string using end/start */ 404 kFmtDfp, /* Double FP reg */ 405 kFmtSfp, /* Single FP reg */ 406 kFmtBlt5_2, /* Same 5-bit field to 2 locations */ 407 }; 408 409 // Struct used to define the snippet positions for each MIPS opcode. 410 struct MipsEncodingMap { 411 uint32_t skeleton; 412 struct { 413 MipsEncodingKind kind; 414 int end; // end for kFmtBitBlt, 1-bit slice end for FP regs. 415 int start; // start for kFmtBitBlt, 4-bit slice end for FP regs. 416 } field_loc[4]; 417 MipsOpCode opcode; 418 uint64_t flags; 419 const char *name; 420 const char* fmt; 421 int size; // Note: size is in bytes. 422 }; 423 424 extern MipsEncodingMap EncodingMap[kMipsLast]; 425 426 #define IS_UIMM16(v) ((0 <= (v)) && ((v) <= 65535)) 427 #define IS_SIMM16(v) ((-32768 <= (v)) && ((v) <= 32766)) 428 #define IS_SIMM16_2WORD(v) ((-32764 <= (v)) && ((v) <= 32763)) // 2 offsets must fit. 429 430 } // namespace art 431 432 #endif // ART_COMPILER_DEX_QUICK_MIPS_MIPS_LIR_H_ 433