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 18 /*! \file LowerHelper.cpp 19 \brief This file implements helper functions for lowering 20 21 With NCG O0: all registers are hard-coded ; 22 With NCG O1: the lowering module will use variables that will be allocated to a physical register by the register allocator. 23 24 register types: FS 32-bit or 64-bit; 25 XMM: SS(32-bit) SD (64-bit); 26 GPR: 8-bit, 16-bit, 32-bit; 27 LowOpndRegType tells whether it is gpr, xmm or fs; 28 OpndSize can be OpndSize_8, OpndSize_16, OpndSize_32, OpndSize_64 29 30 A single native instruction can use multiple physical registers. 31 we can't call freeReg in the middle of emitting a native instruction, 32 since it may free the physical register used by an operand and cause two operands being allocated to the same physical register. 33 34 When allocating a physical register for an operand, we can't spill the operands that are already allocated. To avoid that, we call startNativeCode before each native instruction, here flag "canSpill" is set to true for each physical register; 35 when a physical register is allocated, we set its flag "canSpill" to false; 36 at end of each native instruction, call endNativeCode to set flag "canSpill" to true. 37 */ 38 39 #include "libdex/DexOpcodes.h" 40 #include "libdex/DexFile.h" 41 #include "Lower.h" 42 #include "NcgAot.h" 43 #include "enc_wrapper.h" 44 #include "vm/mterp/Mterp.h" 45 #include "NcgHelper.h" 46 #include <math.h> 47 #include "interp/InterpState.h" 48 49 extern "C" int64_t __divdi3(int64_t, int64_t); 50 extern "C" int64_t __moddi3(int64_t, int64_t); 51 bool isScratchPhysical; 52 LowOp* lirTable[200]; 53 int num_lirs_in_table = 0; 54 55 //4 tables are defined: GPR integer ALU ops, ALU ops in FPU, SSE 32-bit, SSE 64-bit 56 //the index to the table is the opcode 57 //add_opc, or_opc, adc_opc, sbb_opc, 58 //and_opc, sub_opc, xor_opc, cmp_opc, 59 //mul_opc, imul_opc, div_opc, idiv_opc, 60 //sll_opc, srl_opc, sra, (SSE) 61 //shl_opc, shr_opc, sal_opc, sar_opc, //integer shift 62 //neg_opc, not_opc, andn_opc, (SSE) 63 //n_alu 64 //!mnemonic for integer ALU operations 65 const Mnemonic map_of_alu_opcode_2_mnemonic[] = { 66 Mnemonic_ADD, Mnemonic_OR, Mnemonic_ADC, Mnemonic_SBB, 67 Mnemonic_AND, Mnemonic_SUB, Mnemonic_XOR, Mnemonic_CMP, 68 Mnemonic_MUL, Mnemonic_IMUL, Mnemonic_DIV, Mnemonic_IDIV, 69 Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 70 Mnemonic_SHL, Mnemonic_SHR, Mnemonic_SAL, Mnemonic_SAR, 71 Mnemonic_NEG, Mnemonic_NOT, Mnemonic_Null, 72 Mnemonic_Null 73 }; 74 //!mnemonic for ALU operations in FPU 75 const Mnemonic map_of_fpu_opcode_2_mnemonic[] = { 76 Mnemonic_FADD, Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 77 Mnemonic_Null, Mnemonic_FSUB, Mnemonic_Null, Mnemonic_Null, 78 Mnemonic_FMUL, Mnemonic_Null, Mnemonic_FDIV, Mnemonic_Null, 79 Mnemonic_Null, Mnemonic_Null, 80 Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 81 Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 82 Mnemonic_Null 83 }; 84 //!mnemonic for SSE 32-bit 85 const Mnemonic map_of_sse_opcode_2_mnemonic[] = { 86 Mnemonic_ADDSD, Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 87 Mnemonic_Null, Mnemonic_SUBSD, Mnemonic_XORPD, Mnemonic_Null, 88 Mnemonic_MULSD, Mnemonic_Null, Mnemonic_DIVSD, Mnemonic_Null, 89 Mnemonic_Null, Mnemonic_Null, 90 Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 91 Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 92 Mnemonic_Null 93 }; 94 //!mnemonic for SSE 64-bit integer 95 const Mnemonic map_of_64_opcode_2_mnemonic[] = { 96 Mnemonic_PADDQ, Mnemonic_POR, Mnemonic_Null, Mnemonic_Null, 97 Mnemonic_PAND, Mnemonic_PSUBQ, Mnemonic_PXOR, Mnemonic_Null, 98 Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 99 Mnemonic_PSLLQ, Mnemonic_PSRLQ, Mnemonic_Null, 100 Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, Mnemonic_Null, 101 Mnemonic_Null, Mnemonic_Null, Mnemonic_PANDN, 102 Mnemonic_Null 103 }; 104 105 //////////////////////////////////////////////// 106 //!update fields of LowOpndReg 107 108 //! 109 void set_reg_opnd(LowOpndReg* op_reg, int reg, bool isPhysical, LowOpndRegType type) { 110 op_reg->regType = type; 111 if(isPhysical) { 112 op_reg->logicalReg = -1; 113 op_reg->physicalReg = reg; 114 } 115 else 116 op_reg->logicalReg = reg; 117 return; 118 } 119 //!update fields of LowOpndMem 120 121 //! 122 void set_mem_opnd(LowOpndMem* mem, int disp, int base, bool isPhysical) { 123 mem->m_disp.value = disp; 124 mem->hasScale = false; 125 mem->m_base.regType = LowOpndRegType_gp; 126 if(isPhysical) { 127 mem->m_base.logicalReg = -1; 128 mem->m_base.physicalReg = base; 129 } else { 130 mem->m_base.logicalReg = base; 131 } 132 return; 133 } 134 //!update fields of LowOpndMem 135 136 //! 137 void set_mem_opnd_scale(LowOpndMem* mem, int base, bool isPhysical, int disp, int index, bool indexPhysical, int scale) { 138 mem->hasScale = true; 139 mem->m_base.regType = LowOpndRegType_gp; 140 if(isPhysical) { 141 mem->m_base.logicalReg = -1; 142 mem->m_base.physicalReg = base; 143 } else { 144 mem->m_base.logicalReg = base; 145 } 146 if(indexPhysical) { 147 mem->m_index.logicalReg = -1; 148 mem->m_index.physicalReg = index; 149 } else { 150 mem->m_index.logicalReg = index; 151 } 152 mem->m_disp.value = disp; 153 mem->m_scale.value = scale; 154 return; 155 } 156 //!return either LowOpndRegType_xmm or LowOpndRegType_gp 157 158 //! 159 inline LowOpndRegType getTypeFromIntSize(OpndSize size) { 160 return size == OpndSize_64 ? LowOpndRegType_xmm : LowOpndRegType_gp; 161 } 162 163 // copied from JIT compiler 164 typedef struct AtomMemBlock { 165 size_t bytesAllocated; 166 struct AtomMemBlock *next; 167 char ptr[0]; 168 } AtomMemBlock; 169 170 #define ATOMBLOCK_DEFAULT_SIZE 4096 171 AtomMemBlock *atomMemHead = NULL; 172 AtomMemBlock *currentAtomMem = NULL; 173 void * atomNew(size_t size) { 174 lowOpTimeStamp++; //one LowOp constructed 175 if(atomMemHead == NULL) { 176 atomMemHead = (AtomMemBlock*)malloc(sizeof(AtomMemBlock) + ATOMBLOCK_DEFAULT_SIZE); 177 if(atomMemHead == NULL) { 178 ALOGE("Memory allocation failed"); 179 return NULL; 180 } 181 currentAtomMem = atomMemHead; 182 currentAtomMem->bytesAllocated = 0; 183 currentAtomMem->next = NULL; 184 } 185 size = (size + 3) & ~3; 186 if (size > ATOMBLOCK_DEFAULT_SIZE) { 187 ALOGE("Requesting %d bytes which exceed the maximal size allowed", size); 188 return NULL; 189 } 190 retry: 191 if (size + currentAtomMem->bytesAllocated <= ATOMBLOCK_DEFAULT_SIZE) { 192 void *ptr; 193 ptr = ¤tAtomMem->ptr[currentAtomMem->bytesAllocated]; 194 return ptr; 195 } 196 if (currentAtomMem->next) { 197 currentAtomMem = currentAtomMem->next; 198 goto retry; 199 } 200 /* Time to allocate a new arena */ 201 AtomMemBlock *newAtomMem = (AtomMemBlock*)malloc(sizeof(AtomMemBlock) + ATOMBLOCK_DEFAULT_SIZE); 202 if(newAtomMem == NULL) { 203 ALOGE("Memory allocation failed"); 204 return NULL; 205 } 206 newAtomMem->bytesAllocated = 0; 207 newAtomMem->next = NULL; 208 currentAtomMem->next = newAtomMem; 209 currentAtomMem = newAtomMem; 210 goto retry; 211 ALOGE("atomNew requesting %d bytes", size); 212 return NULL; 213 } 214 215 void freeAtomMem() { 216 //LOGI("free all atom memory"); 217 AtomMemBlock * tmpMem = atomMemHead; 218 while(tmpMem != NULL) { 219 tmpMem->bytesAllocated = 0; 220 tmpMem = tmpMem->next; 221 } 222 currentAtomMem = atomMemHead; 223 } 224 225 LowOpImm* dump_special(AtomOpCode cc, int imm) { 226 LowOpImm* op = (LowOpImm*)atomNew(sizeof(LowOpImm)); 227 op->lop.opCode = Mnemonic_NULL; 228 op->lop.opCode2 = cc; 229 op->lop.opnd1.type = LowOpndType_Imm; 230 op->lop.numOperands = 1; 231 op->immOpnd.value = imm; 232 //stream = encoder_imm(m, size, imm, stream); 233 return op; 234 } 235 236 LowOpLabel* lower_label(Mnemonic m, OpndSize size, int imm, const char* label, bool isLocal) { 237 stream = encoder_imm(m, size, imm, stream); 238 return NULL; 239 } 240 241 LowOpLabel* dump_label(Mnemonic m, OpndSize size, int imm, 242 const char* label, bool isLocal) { 243 return lower_label(m, size, imm, label, isLocal); 244 } 245 246 LowOpNCG* dump_ncg(Mnemonic m, OpndSize size, int imm) { 247 stream = encoder_imm(m, size, imm, stream); 248 return NULL; 249 } 250 251 //!update fields of LowOp and generate a x86 instruction with a single immediate operand 252 253 //! 254 LowOpImm* lower_imm(Mnemonic m, OpndSize size, int imm, bool updateTable) { 255 stream = encoder_imm(m, size, imm, stream); 256 return NULL; 257 } 258 259 LowOpImm* dump_imm(Mnemonic m, OpndSize size, int imm) { 260 return lower_imm(m, size, imm, true); 261 } 262 263 LowOpImm* dump_imm_with_codeaddr(Mnemonic m, OpndSize size, 264 int imm, char* codePtr) { 265 encoder_imm(m, size, imm, codePtr); 266 return NULL; 267 } 268 269 //!update fields of LowOp and generate a x86 instruction that takes a single memory operand 270 271 //!With NCG O1, we call freeReg to free up physical registers, then call registerAlloc to allocate a physical register for memory base 272 LowOpMem* lower_mem(Mnemonic m, AtomOpCode m2, OpndSize size, 273 int disp, int base_reg) { 274 stream = encoder_mem(m, size, disp, base_reg, true, stream); 275 return NULL; 276 } 277 278 LowOpMem* dump_mem(Mnemonic m, AtomOpCode m2, OpndSize size, 279 int disp, int base_reg, bool isBasePhysical) { 280 if(gDvm.executionMode == kExecutionModeNcgO1) { 281 freeReg(true); 282 //type of the base is gpr 283 int regAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 284 return lower_mem(m, m2, size, disp, regAll); 285 } else { 286 stream = encoder_mem(m, size, disp, base_reg, isBasePhysical, stream); 287 return NULL; 288 } 289 } 290 //!update fields of LowOp and generate a x86 instruction that takes a single reg operand 291 292 //!With NCG O1, wecall freeReg to free up physical registers, then call registerAlloc to allocate a physical register for the single operand 293 LowOpReg* lower_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 294 int reg, LowOpndRegType type) { 295 stream = encoder_reg(m, size, reg, true, type, stream); 296 return NULL; 297 } 298 299 LowOpReg* dump_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 300 int reg, bool isPhysical, LowOpndRegType type) { 301 if(gDvm.executionMode == kExecutionModeNcgO1) { 302 freeReg(true); 303 if(m == Mnemonic_MUL || m == Mnemonic_IDIV) { 304 //these two instructions use eax & edx implicitly 305 touchEax(); 306 touchEdx(); 307 } 308 int regAll = registerAlloc(type, reg, isPhysical, true); 309 return lower_reg(m, m2, size, regAll, type); 310 } else { 311 stream = encoder_reg(m, size, reg, isPhysical, type, stream); 312 return NULL; 313 } 314 } 315 LowOpReg* dump_reg_noalloc(Mnemonic m, OpndSize size, 316 int reg, bool isPhysical, LowOpndRegType type) { 317 return lower_reg(m, ATOM_NORMAL, size, reg, type); 318 } 319 320 LowOpRegReg* lower_reg_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 321 int reg, int reg2, LowOpndRegType type) { 322 if(m == Mnemonic_FUCOMP || m == Mnemonic_FUCOM) { 323 stream = encoder_compare_fp_stack(m == Mnemonic_FUCOMP, 324 reg-reg2, size==OpndSize_64, stream); 325 } 326 else { 327 stream = encoder_reg_reg(m, size, reg, true, reg2, true, type, stream); 328 } 329 return NULL; 330 } 331 332 //!update fields of LowOp and generate a x86 instruction that takes two reg operands 333 334 //Here, both registers are physical 335 LowOpRegReg* dump_reg_reg_noalloc(Mnemonic m, OpndSize size, 336 int reg, bool isPhysical, 337 int reg2, bool isPhysical2, LowOpndRegType type) { 338 return lower_reg_reg(m, ATOM_NORMAL, size, reg, reg2, type); 339 } 340 341 inline bool isMnemonicMove(Mnemonic m) { 342 return (m == Mnemonic_MOV || m == Mnemonic_MOVQ || 343 m == Mnemonic_MOVSS || m == Mnemonic_MOVSD); 344 } 345 //!update fields of LowOp and generate a x86 instruction that takes two reg operands 346 347 //!here dst reg is already allocated to a physical reg 348 //! we should not spill the physical register for dst when allocating for src 349 LowOpRegReg* dump_reg_reg_noalloc_dst(Mnemonic m, OpndSize size, 350 int reg, bool isPhysical, 351 int reg2, bool isPhysical2, LowOpndRegType type) { 352 if(gDvm.executionMode == kExecutionModeNcgO1) { 353 int regAll = registerAlloc(type, reg, isPhysical, true); 354 /* remove move from one register to the same register */ 355 if(isMnemonicMove(m) && regAll == reg2) return NULL; 356 return lower_reg_reg(m, ATOM_NORMAL, size, regAll, reg2, type); 357 } else { 358 stream = encoder_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2, type, stream); 359 return NULL; 360 } 361 } 362 //!update fields of LowOp and generate a x86 instruction that takes two reg operands 363 364 //!here src reg is already allocated to a physical reg 365 LowOpRegReg* dump_reg_reg_noalloc_src(Mnemonic m, AtomOpCode m2, OpndSize size, 366 int reg, bool isPhysical, 367 int reg2, bool isPhysical2, LowOpndRegType type) { 368 if(gDvm.executionMode == kExecutionModeNcgO1) { 369 int regAll2; 370 if(isMnemonicMove(m) && checkTempReg2(reg2, type, isPhysical2, reg)) { //dst reg is logical 371 //only from get_virtual_reg_all 372 regAll2 = registerAllocMove(reg2, type, isPhysical2, reg); 373 } else { 374 regAll2 = registerAlloc(type, reg2, isPhysical2, true); 375 return lower_reg_reg(m, m2, size, reg, regAll2, type); 376 } 377 } else { 378 stream = encoder_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2, type, stream); 379 return NULL; 380 } 381 return NULL; 382 } 383 //!update fields of LowOp and generate a x86 instruction that takes two reg operands 384 385 //! 386 LowOpRegReg* dump_reg_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 387 int reg, bool isPhysical, 388 int reg2, bool isPhysical2, LowOpndRegType type) { 389 if(gDvm.executionMode == kExecutionModeNcgO1) { 390 startNativeCode(-1, -1); 391 //reg is source if m is MOV 392 freeReg(true); 393 int regAll = registerAlloc(type, reg, isPhysical, true); 394 int regAll2; 395 LowOpRegReg* op = NULL; 396 #ifdef MOVE_OPT2 397 if(isMnemonicMove(m) && 398 ((reg != PhysicalReg_EDI && reg != PhysicalReg_ESP && reg != PhysicalReg_EBP) || (!isPhysical)) && 399 isPhysical2 == false) { //dst reg is logical 400 //called from move_reg_to_reg 401 regAll2 = registerAllocMove(reg2, type, isPhysical2, regAll); 402 } else { 403 #endif 404 donotSpillReg(regAll); 405 regAll2 = registerAlloc(type, reg2, isPhysical2, true); 406 op = lower_reg_reg(m, m2, size, regAll, regAll2, type); 407 #ifdef MOVE_OPT2 408 } 409 #endif 410 endNativeCode(); 411 return op; 412 } 413 else { 414 stream = encoder_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2, type, stream); 415 } 416 return NULL; 417 } 418 419 LowOpRegMem* lower_mem_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 420 int disp, int base_reg, 421 MemoryAccessType mType, int mIndex, 422 int reg, LowOpndRegType type, bool isMoves) { 423 if(m == Mnemonic_MOVSX) { 424 stream = encoder_moves_mem_to_reg(size, disp, base_reg, true, 425 reg, true, stream); 426 } 427 else if(m == Mnemonic_MOVZX) { 428 stream = encoder_movez_mem_to_reg(size, disp, base_reg, true, 429 reg, true, stream); 430 } 431 else { 432 stream = encoder_mem_reg(m, size, disp, base_reg, true, 433 reg, true, type, stream); 434 } 435 return NULL; 436 } 437 438 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 439 440 //!Here, operands are already allocated to physical registers 441 LowOpRegMem* dump_mem_reg_noalloc(Mnemonic m, OpndSize size, 442 int disp, int base_reg, bool isBasePhysical, 443 MemoryAccessType mType, int mIndex, 444 int reg, bool isPhysical, LowOpndRegType type) { 445 return lower_mem_reg(m, ATOM_NORMAL, size, disp, base_reg, mType, mIndex, reg, type, false); 446 } 447 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 448 449 //!Here, memory operand is already allocated to physical register 450 LowOpRegMem* dump_mem_reg_noalloc_mem(Mnemonic m, AtomOpCode m2, OpndSize size, 451 int disp, int base_reg, bool isBasePhysical, 452 MemoryAccessType mType, int mIndex, 453 int reg, bool isPhysical, LowOpndRegType type) { 454 if(gDvm.executionMode == kExecutionModeNcgO1) { 455 int regAll = registerAlloc(type, reg, isPhysical, true); 456 return lower_mem_reg(m, m2, size, disp, base_reg, mType, mIndex, regAll, type, false); 457 } else { 458 stream = encoder_mem_reg(m, size, disp, base_reg, isBasePhysical, 459 reg, isPhysical, type, stream); 460 } 461 return NULL; 462 } 463 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 464 465 //! 466 LowOpRegMem* dump_mem_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 467 int disp, int base_reg, bool isBasePhysical, 468 MemoryAccessType mType, int mIndex, 469 int reg, bool isPhysical, LowOpndRegType type) { 470 if(gDvm.executionMode == kExecutionModeNcgO1) { 471 startNativeCode(-1, -1); 472 freeReg(true); 473 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 474 //it is okay to use the same physical register 475 if(isMnemonicMove(m)) { 476 freeReg(true); 477 } else { 478 donotSpillReg(baseAll); 479 } 480 int regAll = registerAlloc(type, reg, isPhysical, true); 481 endNativeCode(); 482 return lower_mem_reg(m, m2, size, disp, baseAll, mType, mIndex, regAll, type, false); 483 } else { 484 stream = encoder_mem_reg(m, size, disp, base_reg, isBasePhysical, 485 reg, isPhysical, type, stream); 486 } 487 return NULL; 488 } 489 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 490 491 //! 492 LowOpRegMem* dump_moves_mem_reg(Mnemonic m, OpndSize size, 493 int disp, int base_reg, bool isBasePhysical, 494 int reg, bool isPhysical) { 495 if(gDvm.executionMode == kExecutionModeNcgO1) { 496 startNativeCode(-1, -1); 497 freeReg(true); 498 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 499 donotSpillReg(baseAll); 500 int regAll = registerAlloc(LowOpndRegType_gp, reg, isPhysical, true); 501 endNativeCode(); 502 return lower_mem_reg(m, ATOM_NORMAL, size, disp, baseAll, MemoryAccess_Unknown, -1, 503 regAll, LowOpndRegType_gp, true/*moves*/); 504 } else { 505 stream = encoder_moves_mem_to_reg(size, disp, base_reg, isBasePhysical, reg, isPhysical, stream); 506 } 507 return NULL; 508 } 509 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 510 511 //! 512 LowOpRegMem* dump_movez_mem_reg(Mnemonic m, OpndSize size, 513 int disp, int base_reg, bool isBasePhysical, 514 int reg, bool isPhysical) { 515 if(gDvm.executionMode == kExecutionModeNcgO1) { 516 startNativeCode(-1, -1); 517 freeReg(true); 518 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 519 donotSpillReg(baseAll); 520 int regAll = registerAlloc(LowOpndRegType_gp, reg, isPhysical, true); 521 endNativeCode(); 522 return lower_mem_reg(m, ATOM_NORMAL, size, disp, baseAll, MemoryAccess_Unknown, -1, 523 regAll, LowOpndRegType_gp, true/*moves*/); 524 } else { 525 stream = encoder_movez_mem_to_reg(size, disp, base_reg, isBasePhysical, reg, isPhysical, stream); 526 } 527 return NULL; 528 } 529 530 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one reg operand 531 532 //! 533 LowOpRegReg* dump_movez_reg_reg(Mnemonic m, OpndSize size, 534 int reg, bool isPhysical, 535 int reg2, bool isPhysical2) { 536 LowOpRegReg* op = (LowOpRegReg*)atomNew(sizeof(LowOpRegReg)); 537 op->lop.opCode = m; 538 op->lop.opnd1.size = OpndSize_32; 539 op->lop.opnd1.type = LowOpndType_Reg; 540 op->lop.opnd2.size = size; 541 op->lop.opnd2.type = LowOpndType_Reg; 542 set_reg_opnd(&(op->regOpnd1), reg2, isPhysical2, LowOpndRegType_gp); 543 set_reg_opnd(&(op->regOpnd2), reg, isPhysical, LowOpndRegType_gp); 544 if(gDvm.executionMode == kExecutionModeNcgO1) { 545 startNativeCode(-1, -1); 546 //reg is source if m is MOV 547 freeReg(true); 548 int regAll = registerAlloc(LowOpndRegType_gp, reg, isPhysical, true); 549 donotSpillReg(regAll); 550 int regAll2 = registerAlloc(LowOpndRegType_gp, reg2, isPhysical2, true); 551 stream = encoder_movez_reg_to_reg(size, regAll, true, regAll2, true, 552 LowOpndRegType_gp, stream); 553 endNativeCode(); 554 } 555 else { 556 stream = encoder_movez_reg_to_reg(size, reg, isPhysical, reg2, 557 isPhysical2, LowOpndRegType_gp, stream); 558 } 559 return NULL; 560 } 561 562 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 563 564 //! 565 LowOpRegMem* lower_mem_scale_reg(Mnemonic m, OpndSize size, int base_reg, int disp, int index_reg, 566 int scale, int reg, LowOpndRegType type) { 567 bool isMovzs = (m == Mnemonic_MOVZX || m == Mnemonic_MOVSX); 568 if(isMovzs) 569 stream = encoder_movzs_mem_disp_scale_reg(m, size, base_reg, true, disp, index_reg, true, 570 scale, reg, true, type, stream); 571 else { 572 if(disp == 0) 573 stream = encoder_mem_scale_reg(m, size, base_reg, true, index_reg, true, 574 scale, reg, true, type, stream); 575 else 576 stream = encoder_mem_disp_scale_reg(m, size, base_reg, true, disp, index_reg, true, 577 scale, reg, true, type, stream); 578 } 579 return NULL; 580 } 581 582 LowOpRegMem* dump_mem_scale_reg(Mnemonic m, OpndSize size, 583 int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, 584 int reg, bool isPhysical, LowOpndRegType type) { 585 if(gDvm.executionMode == kExecutionModeNcgO1) { 586 startNativeCode(-1, -1); 587 freeReg(true); 588 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 589 donotSpillReg(baseAll); //make sure index will not use the same physical reg 590 int indexAll = registerAlloc(LowOpndRegType_gp, index_reg, isIndexPhysical, true); 591 if(isMnemonicMove(m)) { 592 freeReg(true); 593 doSpillReg(baseAll); //base can be used now 594 } else { 595 donotSpillReg(indexAll); 596 } 597 bool isMovzs = (m == Mnemonic_MOVZX || m == Mnemonic_MOVSX); 598 int regAll = registerAlloc(isMovzs ? LowOpndRegType_gp : type, reg, isPhysical, true); 599 endNativeCode(); 600 return lower_mem_scale_reg(m, size, baseAll, disp, indexAll, scale, regAll, type); 601 } else { 602 stream = encoder_mem_scale_reg(m, size, base_reg, isBasePhysical, index_reg, 603 isIndexPhysical, scale, reg, isPhysical, type, stream); 604 } 605 return NULL; 606 } 607 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 608 609 //! 610 LowOpMemReg* lower_reg_mem_scale(Mnemonic m, OpndSize size, int reg, 611 int base_reg, int disp, int index_reg, int scale, LowOpndRegType type) { 612 if(disp == 0) 613 stream = encoder_reg_mem_scale(m, size, reg, true, base_reg, true, 614 index_reg, true, scale, type, stream); 615 else 616 stream = encoder_reg_mem_disp_scale(m, size, reg, true, base_reg, true, 617 disp, index_reg, true, scale, type, stream); 618 return NULL; 619 } 620 621 LowOpMemReg* dump_reg_mem_scale(Mnemonic m, OpndSize size, 622 int reg, bool isPhysical, 623 int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, 624 LowOpndRegType type) { 625 if(gDvm.executionMode == kExecutionModeNcgO1) { 626 startNativeCode(-1, -1); 627 freeReg(true); 628 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 629 donotSpillReg(baseAll); 630 int indexAll = registerAlloc(LowOpndRegType_gp, index_reg, isIndexPhysical, true); 631 donotSpillReg(indexAll); 632 int regAll = registerAlloc(type, reg, isPhysical, true); 633 endNativeCode(); 634 return lower_reg_mem_scale(m, size, regAll, baseAll, disp, indexAll, scale, type); 635 } else { 636 stream = encoder_reg_mem_scale(m, size, reg, isPhysical, base_reg, isBasePhysical, 637 index_reg, isIndexPhysical, scale, type, stream); 638 } 639 return NULL; 640 } 641 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 642 643 //!Here operands are already allocated 644 LowOpMemReg* lower_reg_mem(Mnemonic m, AtomOpCode m2, OpndSize size, int reg, 645 int disp, int base_reg, MemoryAccessType mType, int mIndex, 646 LowOpndRegType type) { 647 stream = encoder_reg_mem(m, size, reg, true, disp, base_reg, true, type, stream); 648 return NULL; 649 } 650 651 LowOpMemReg* dump_reg_mem_noalloc(Mnemonic m, OpndSize size, 652 int reg, bool isPhysical, 653 int disp, int base_reg, bool isBasePhysical, 654 MemoryAccessType mType, int mIndex, LowOpndRegType type) { 655 return lower_reg_mem(m, ATOM_NORMAL, size, reg, disp, base_reg, mType, mIndex, type); 656 } 657 //!update fields of LowOp and generate a x86 instruction that takes one reg operand and one mem operand 658 659 //! 660 LowOpMemReg* dump_reg_mem(Mnemonic m, AtomOpCode m2, OpndSize size, 661 int reg, bool isPhysical, 662 int disp, int base_reg, bool isBasePhysical, 663 MemoryAccessType mType, int mIndex, LowOpndRegType type) { 664 if(gDvm.executionMode == kExecutionModeNcgO1) { 665 startNativeCode(-1, -1); 666 freeReg(true); 667 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 668 donotSpillReg(baseAll); 669 int regAll = registerAlloc(type, reg, isPhysical, true); 670 endNativeCode(); 671 return lower_reg_mem(m, m2, size, regAll, disp, baseAll, mType, mIndex, type); 672 } else { 673 stream = encoder_reg_mem(m, size, reg, isPhysical, disp, base_reg, isBasePhysical, type, stream); 674 } 675 return NULL; 676 } 677 //!update fields of LowOp and generate a x86 instruction that takes one immediate and one reg operand 678 679 //!The reg operand is allocated already 680 LowOpRegImm* lower_imm_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 681 int imm, int reg, LowOpndRegType type, bool chaining) { 682 stream = encoder_imm_reg(m, size, imm, reg, true, type, stream); 683 return NULL; 684 } 685 686 LowOpRegImm* dump_imm_reg_noalloc(Mnemonic m, OpndSize size, 687 int imm, int reg, bool isPhysical, LowOpndRegType type) { 688 return lower_imm_reg(m, ATOM_NORMAL, size, imm, reg, type, false); 689 } 690 //!update fields of LowOp and generate a x86 instruction that takes one immediate and one reg operand 691 692 //! 693 LowOpRegImm* dump_imm_reg(Mnemonic m, AtomOpCode m2, OpndSize size, 694 int imm, int reg, bool isPhysical, LowOpndRegType type, bool chaining) { 695 if(gDvm.executionMode == kExecutionModeNcgO1) { 696 freeReg(true); 697 int regAll = registerAlloc(type, reg, isPhysical, true); 698 return lower_imm_reg(m, m2, size, imm, regAll, type, chaining); 699 } else { 700 stream = encoder_imm_reg(m, size, imm, reg, isPhysical, type, stream); 701 } 702 return NULL; 703 } 704 //!update fields of LowOp and generate a x86 instruction that takes one immediate and one mem operand 705 706 //!The mem operand is already allocated 707 LowOpMemImm* lower_imm_mem(Mnemonic m, AtomOpCode m2, OpndSize size, int imm, 708 int disp, int base_reg, MemoryAccessType mType, int mIndex, 709 bool chaining) { 710 stream = encoder_imm_mem(m, size, imm, disp, base_reg, true, stream); 711 return NULL; 712 } 713 714 LowOpMemImm* dump_imm_mem_noalloc(Mnemonic m, OpndSize size, 715 int imm, 716 int disp, int base_reg, bool isBasePhysical, 717 MemoryAccessType mType, int mIndex) { 718 return lower_imm_mem(m, ATOM_NORMAL, size, imm, disp, base_reg, mType, mIndex, false); 719 } 720 //!update fields of LowOp and generate a x86 instruction that takes one immediate and one mem operand 721 722 //! 723 LowOpMemImm* dump_imm_mem(Mnemonic m, AtomOpCode m2, OpndSize size, 724 int imm, 725 int disp, int base_reg, bool isBasePhysical, 726 MemoryAccessType mType, int mIndex, bool chaining) { 727 if(gDvm.executionMode == kExecutionModeNcgO1) { 728 /* do not free register if the base is %edi, %esp, or %ebp 729 make sure dump_imm_mem will only generate a single instruction */ 730 if(!isBasePhysical || (base_reg != PhysicalReg_EDI && 731 base_reg != PhysicalReg_ESP && 732 base_reg != PhysicalReg_EBP)) { 733 freeReg(true); 734 } 735 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 736 return lower_imm_mem(m, m2, size, imm, disp, baseAll, mType, mIndex, chaining); 737 } else { 738 stream = encoder_imm_mem(m, size, imm, disp, base_reg, isBasePhysical, stream); 739 } 740 return NULL; 741 } 742 //!update fields of LowOp and generate a x86 instruction that uses the FP stack and takes one mem operand 743 744 //! 745 LowOpMemReg* lower_fp_mem(Mnemonic m, OpndSize size, int reg, 746 int disp, int base_reg, MemoryAccessType mType, int mIndex) { 747 stream = encoder_fp_mem(m, size, reg, disp, base_reg, true, stream); 748 return NULL; 749 } 750 751 LowOpMemReg* dump_fp_mem(Mnemonic m, OpndSize size, int reg, 752 int disp, int base_reg, bool isBasePhysical, 753 MemoryAccessType mType, int mIndex) { 754 if(gDvm.executionMode == kExecutionModeNcgO1) { 755 freeReg(true); 756 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 757 return lower_fp_mem(m, size, reg, disp, baseAll, mType, mIndex); 758 } else { 759 stream = encoder_fp_mem(m, size, reg, disp, base_reg, isBasePhysical, stream); 760 } 761 return NULL; 762 } 763 //!update fields of LowOp and generate a x86 instruction that uses the FP stack and takes one mem operand 764 765 //! 766 LowOpRegMem* lower_mem_fp(Mnemonic m, OpndSize size, int disp, int base_reg, 767 MemoryAccessType mType, int mIndex, int reg) { 768 stream = encoder_mem_fp(m, size, disp, base_reg, true, reg, stream); 769 return NULL; 770 } 771 772 LowOpRegMem* dump_mem_fp(Mnemonic m, OpndSize size, 773 int disp, int base_reg, bool isBasePhysical, 774 MemoryAccessType mType, int mIndex, 775 int reg) { 776 if(gDvm.executionMode == kExecutionModeNcgO1) { 777 freeReg(true); 778 int baseAll = registerAlloc(LowOpndRegType_gp, base_reg, isBasePhysical, true); 779 return lower_mem_fp(m, size, disp, baseAll, mType, mIndex, reg); 780 } else { 781 stream = encoder_mem_fp(m, size, disp, base_reg, isBasePhysical, reg, stream); 782 } 783 return NULL; 784 } 785 /////////////////////////////////////////////////////////////// 786 /////////////////////////////////////////////////////////////// 787 //OPERAND ORDER: 788 //LowOp same as EncoderBase destination first 789 //parameter order of function: src first 790 791 ////////////////////////////////// IA32 native instructions ////////////// 792 //! generate a native instruction lea 793 794 //! 795 void load_effective_addr(int disp, int base_reg, bool isBasePhysical, 796 int reg, bool isPhysical) { 797 Mnemonic m = Mnemonic_LEA; 798 dump_mem_reg(m, ATOM_NORMAL, OpndSize_32, disp, base_reg, isBasePhysical, 799 MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp); 800 } 801 //! generate a native instruction lea 802 803 //! 804 void load_effective_addr_scale(int base_reg, bool isBasePhysical, 805 int index_reg, bool isIndexPhysical, int scale, 806 int reg, bool isPhysical) { 807 Mnemonic m = Mnemonic_LEA; 808 dump_mem_scale_reg(m, OpndSize_32, 809 base_reg, isBasePhysical, 0/*disp*/, index_reg, isIndexPhysical, scale, 810 reg, isPhysical, LowOpndRegType_gp); 811 } 812 //!fldcw 813 814 //! 815 void load_fpu_cw(int disp, int base_reg, bool isBasePhysical) { 816 Mnemonic m = Mnemonic_FLDCW; 817 dump_mem(m, ATOM_NORMAL, OpndSize_16, disp, base_reg, isBasePhysical); 818 } 819 //!fnstcw 820 821 //! 822 void store_fpu_cw(bool checkException, int disp, int base_reg, bool isBasePhysical) { 823 assert(!checkException); 824 Mnemonic m = Mnemonic_FNSTCW; 825 dump_mem(m, ATOM_NORMAL, OpndSize_16, disp, base_reg, isBasePhysical); 826 } 827 //!cdq 828 829 //! 830 void convert_integer(OpndSize srcSize, OpndSize dstSize) { //cbw, cwd, cdq 831 assert(srcSize == OpndSize_32 && dstSize == OpndSize_64); 832 Mnemonic m = Mnemonic_CDQ; 833 dump_reg_reg(m, ATOM_NORMAL, OpndSize_32, PhysicalReg_EAX, true, PhysicalReg_EDX, true, LowOpndRegType_gp); 834 } 835 //!fld: load from memory (float or double) to stack 836 837 //! 838 void load_fp_stack(LowOp* op, OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fld(s|l) 839 Mnemonic m = Mnemonic_FLD; 840 dump_mem_fp(m, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, 0); //ST0 841 } 842 //! fild: load from memory (int or long) to stack 843 844 //! 845 void load_int_fp_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fild(ll|l) 846 Mnemonic m = Mnemonic_FILD; 847 dump_mem_fp(m, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, 0); //ST0 848 } 849 //!fild: load from memory (absolute addr) 850 851 //! 852 void load_int_fp_stack_imm(OpndSize size, int imm) {//fild(ll|l) 853 return load_int_fp_stack(size, imm, PhysicalReg_Null, true); 854 } 855 //!fst: store from stack to memory (float or double) 856 857 //! 858 void store_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fst(p)(s|l) 859 Mnemonic m = pop ? Mnemonic_FSTP : Mnemonic_FST; 860 dump_fp_mem(m, size, 0, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1); 861 } 862 //!fist: store from stack to memory (int or long) 863 864 //! 865 void store_int_fp_stack(LowOp* op, bool pop, OpndSize size, int disp, int base_reg, bool isBasePhysical) {//fist(p)(l) 866 Mnemonic m = pop ? Mnemonic_FISTP : Mnemonic_FIST; 867 dump_fp_mem(m, size, 0, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1); 868 } 869 //!cmp reg, mem 870 871 //! 872 void compare_reg_mem(LowOp* op, OpndSize size, int reg, bool isPhysical, 873 int disp, int base_reg, bool isBasePhysical) { 874 Mnemonic m = Mnemonic_CMP; 875 dump_reg_mem(m, ATOM_NORMAL, size, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, getTypeFromIntSize(size)); 876 } 877 //!cmp mem, reg 878 879 //! 880 void compare_mem_reg(OpndSize size, 881 int disp, int base_reg, bool isBasePhysical, 882 int reg, bool isPhysical) { 883 Mnemonic m = Mnemonic_CMP; 884 dump_mem_reg(m, ATOM_NORMAL, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, getTypeFromIntSize(size)); 885 } 886 //! compare a VR with a temporary variable 887 888 //! 889 void compare_VR_reg_all(OpndSize size, 890 int vA, 891 int reg, bool isPhysical, Mnemonic m) { 892 LowOpndRegType type = getTypeFromIntSize(size); 893 LowOpndRegType pType = type; 894 if(m == Mnemonic_COMISS) { 895 size = OpndSize_32; 896 type = LowOpndRegType_ss; 897 pType = LowOpndRegType_xmm; 898 } 899 if(gDvm.executionMode == kExecutionModeNcgO1) { 900 int tmpValue[2]; 901 int isConst = isVirtualRegConstant(vA, type, tmpValue, true/*updateRefCount*/); 902 if(isConst == 3) { 903 if(m == Mnemonic_COMISS) { 904 #ifdef DEBUG_NCG_O1 905 LOGI("VR is const and SS in compare_VR_reg"); 906 #endif 907 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 908 //dumpImmToMem(vA+1, OpndSize_32, 0); //CHECK necessary? will overwrite vA+1!!! 909 dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, reg, isPhysical, pType); 910 return; 911 } 912 else if(size != OpndSize_64) { 913 #ifdef DEBUG_NCG_O1 914 LOGI("VR is const and 32 bits in compare_VR_reg"); 915 #endif 916 dump_imm_reg(m, ATOM_NORMAL, size, tmpValue[0], reg, isPhysical, pType, false); 917 return; 918 } 919 else if(size == OpndSize_64) { 920 #ifdef DEBUG_NCG_O1 921 LOGI("VR is const and 64 bits in compare_VR_reg"); 922 #endif 923 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 924 dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]); 925 dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true, 926 MemoryAccess_VR, vA, reg, isPhysical, pType); 927 return; 928 } 929 } 930 if(isConst == 1) dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 931 if(isConst == 2) dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]); 932 freeReg(true); 933 int regAll = checkVirtualReg(vA, type, 0/*do not update*/); 934 if(regAll != PhysicalReg_Null) { //do not spill regAll when allocating register for dst 935 startNativeCode(-1, -1); 936 donotSpillReg(regAll); 937 dump_reg_reg_noalloc_src(m, ATOM_NORMAL, size, regAll, true, reg, isPhysical, pType); 938 endNativeCode(); 939 } 940 else { 941 //virtual register is not allocated to a physical register 942 dump_mem_reg_noalloc_mem(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true, 943 MemoryAccess_VR, vA, reg, isPhysical, pType); 944 } 945 updateRefCount(vA, type); 946 return; 947 } else { 948 dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true, 949 MemoryAccess_VR, vA, reg, isPhysical, pType); 950 return; 951 } 952 } 953 void compare_VR_reg(OpndSize size, 954 int vA, 955 int reg, bool isPhysical) { 956 Mnemonic m = Mnemonic_CMP; 957 return compare_VR_reg_all(size, vA, reg, isPhysical, m); 958 } 959 void compare_VR_ss_reg(int vA, int reg, bool isPhysical) { 960 Mnemonic m = Mnemonic_COMISS; 961 return compare_VR_reg_all(OpndSize_32, vA, reg, isPhysical, m); 962 } 963 void compare_VR_sd_reg(int vA, int reg, bool isPhysical) { 964 Mnemonic m = Mnemonic_COMISD; 965 return compare_VR_reg_all(OpndSize_64, vA, reg, isPhysical, m); 966 } 967 //!load VR to stack 968 969 //! 970 void load_fp_stack_VR_all(OpndSize size, int vB, Mnemonic m) { 971 if(gDvm.executionMode == kExecutionModeNcgO1) { 972 //can't load from immediate to fp stack 973 int tmpValue[2]; 974 int isConst = isVirtualRegConstant(vB, getTypeFromIntSize(size), tmpValue, false/*updateRefCount*/); 975 if(isConst > 0) { 976 if(size != OpndSize_64) { 977 #ifdef DEBUG_NCG_O1 978 LOGI("VR is const and 32 bits in load_fp_stack"); 979 #endif 980 dumpImmToMem(vB, OpndSize_32, tmpValue[0]); 981 } 982 else { 983 #ifdef DEBUG_NCG_O1 984 LOGI("VR is const and 64 bits in load_fp_stack_VR"); 985 #endif 986 if(isConst == 1 || isConst == 3) dumpImmToMem(vB, OpndSize_32, tmpValue[0]); 987 if(isConst == 2 || isConst == 3) dumpImmToMem(vB+1, OpndSize_32, tmpValue[1]); 988 } 989 } 990 else { //if VR was updated by a def of gp, a xfer point was inserted 991 //if VR was updated by a def of xmm, a xfer point was inserted 992 #if 0 993 int regAll = checkVirtualReg(vB, size, 1); 994 if(regAll != PhysicalReg_Null) //dump from register to memory 995 dump_reg_mem_noalloc(m, size, regAll, true, 4*vB, PhysicalReg_FP, true, 996 MemoryAccess_VR, vB, getTypeFromIntSize(size)); 997 #endif 998 } 999 dump_mem_fp(m, size, 4*vB, PhysicalReg_FP, true, MemoryAccess_VR, vB, 0); 1000 } else { 1001 dump_mem_fp(m, size, 4*vB, PhysicalReg_FP, true, MemoryAccess_VR, vB, 0); 1002 } 1003 } 1004 //!load VR(float or double) to stack 1005 1006 //! 1007 void load_fp_stack_VR(OpndSize size, int vA) {//fld(s|l) 1008 Mnemonic m = Mnemonic_FLD; 1009 return load_fp_stack_VR_all(size, vA, m); 1010 } 1011 //!load VR(int or long) to stack 1012 1013 //! 1014 void load_int_fp_stack_VR(OpndSize size, int vA) {//fild(ll|l) 1015 Mnemonic m = Mnemonic_FILD; 1016 return load_fp_stack_VR_all(size, vA, m); 1017 } 1018 //!store from stack to VR (float or double) 1019 1020 //! 1021 void store_fp_stack_VR(bool pop, OpndSize size, int vA) {//fst(p)(s|l) 1022 Mnemonic m = pop ? Mnemonic_FSTP : Mnemonic_FST; 1023 dump_fp_mem(m, size, 0, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA); 1024 if(gDvm.executionMode == kExecutionModeNcgO1) { 1025 if(size == OpndSize_32) 1026 updateVirtualReg(vA, LowOpndRegType_fs_s); 1027 else 1028 updateVirtualReg(vA, LowOpndRegType_fs); 1029 } 1030 } 1031 //!store from stack to VR (int or long) 1032 1033 //! 1034 void store_int_fp_stack_VR(bool pop, OpndSize size, int vA) {//fist(p)(l) 1035 Mnemonic m = pop ? Mnemonic_FISTP : Mnemonic_FIST; 1036 dump_fp_mem(m, size, 0, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA); 1037 if(gDvm.executionMode == kExecutionModeNcgO1) { 1038 if(size == OpndSize_32) 1039 updateVirtualReg(vA, LowOpndRegType_fs_s); 1040 else 1041 updateVirtualReg(vA, LowOpndRegType_fs); 1042 } 1043 } 1044 //! ALU ops in FPU, one operand is a VR 1045 1046 //! 1047 void fpu_VR(ALU_Opcode opc, OpndSize size, int vA) { 1048 Mnemonic m = map_of_fpu_opcode_2_mnemonic[opc]; 1049 if(gDvm.executionMode == kExecutionModeNcgO1) { 1050 int tmpValue[2]; 1051 int isConst = isVirtualRegConstant(vA, getTypeFromIntSize(size), tmpValue, false/*updateRefCount*/); 1052 if(isConst > 0) { 1053 if(size != OpndSize_64) { 1054 //allocate a register for dst 1055 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1056 } 1057 else { 1058 if((isConst == 1 || isConst == 3) && size == OpndSize_64) { 1059 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1060 } 1061 if((isConst == 2 || isConst == 3) && size == OpndSize_64) { 1062 dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]); 1063 } 1064 } 1065 } 1066 if(!isInMemory(vA, size)) { 1067 ALOGE("fpu_VR"); 1068 } 1069 dump_mem_fp(m, size, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, 0); 1070 } else { 1071 dump_mem_fp(m, size, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, 0); 1072 } 1073 } 1074 //! cmp imm reg 1075 1076 //! 1077 void compare_imm_reg(OpndSize size, int imm, 1078 int reg, bool isPhysical) { 1079 if(imm == 0) { 1080 LowOpndRegType type = getTypeFromIntSize(size); 1081 Mnemonic m = Mnemonic_TEST; 1082 if(gDvm.executionMode == kExecutionModeNcgO1) { 1083 freeReg(true); 1084 int regAll = registerAlloc(type, reg, isPhysical, true); 1085 lower_reg_reg(m, ATOM_NORMAL, size, regAll, regAll, type); 1086 } else { 1087 stream = encoder_reg_reg(m, size, reg, isPhysical, reg, isPhysical, type, stream); 1088 } 1089 return; 1090 } 1091 Mnemonic m = Mnemonic_CMP; 1092 dump_imm_reg(m, ATOM_NORMAL, size, imm, reg, isPhysical, getTypeFromIntSize(size), false); 1093 } 1094 //! cmp imm mem 1095 1096 //! 1097 void compare_imm_mem(OpndSize size, int imm, 1098 int disp, int base_reg, bool isBasePhysical) { 1099 Mnemonic m = Mnemonic_CMP; 1100 dump_imm_mem(m, ATOM_NORMAL, size, imm, disp, 1101 base_reg, isBasePhysical, MemoryAccess_Unknown, -1, false); 1102 } 1103 //! cmp imm VR 1104 1105 //! 1106 void compare_imm_VR(OpndSize size, int imm, 1107 int vA) { 1108 Mnemonic m = Mnemonic_CMP; 1109 if(gDvm.executionMode == kExecutionModeNcgO1) { 1110 if(size != OpndSize_32) ALOGE("only 32 bits supported in compare_imm_VR"); 1111 int tmpValue[2]; 1112 int isConst = isVirtualRegConstant(vA, getTypeFromIntSize(size), tmpValue, false/*updateRefCount*/); 1113 if(isConst > 0) { 1114 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1115 } 1116 int regAll = checkVirtualReg(vA, getTypeFromIntSize(size), 0); 1117 if(regAll != PhysicalReg_Null) 1118 dump_imm_reg_noalloc(m, size, imm, regAll, true, LowOpndRegType_gp); 1119 else 1120 dump_imm_mem_noalloc(m, size, imm, 4*vA, PhysicalReg_FP, true, 1121 MemoryAccess_VR, vA); 1122 updateRefCount(vA, getTypeFromIntSize(size)); 1123 } else { 1124 dump_imm_mem(m, ATOM_NORMAL, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, false); 1125 } 1126 } 1127 //! cmp reg reg 1128 1129 //! 1130 void compare_reg_reg(int reg1, bool isPhysical1, 1131 int reg2, bool isPhysical2) { 1132 Mnemonic m = Mnemonic_CMP; 1133 dump_reg_reg(m, ATOM_NORMAL, OpndSize_32, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_gp); 1134 } 1135 void compare_reg_reg_16(int reg1, bool isPhysical1, 1136 int reg2, bool isPhysical2) { 1137 Mnemonic m = Mnemonic_CMP; 1138 dump_reg_reg(m, ATOM_NORMAL, OpndSize_16, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_gp); 1139 } 1140 1141 //! comiss mem reg 1142 1143 //!SSE, XMM: comparison of floating point numbers 1144 void compare_ss_mem_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical, 1145 int reg, bool isPhysical) { 1146 Mnemonic m = Mnemonic_COMISS; 1147 dump_mem_reg(m, ATOM_NORMAL, OpndSize_32, disp, base_reg, isBasePhysical, 1148 MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm); 1149 } 1150 //! comiss reg reg 1151 1152 //! 1153 void compare_ss_reg_with_reg(LowOp* op, int reg1, bool isPhysical1, 1154 int reg2, bool isPhysical2) { 1155 Mnemonic m = Mnemonic_COMISS; 1156 dump_reg_reg(m, ATOM_NORMAL, OpndSize_32, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_xmm); 1157 } 1158 //! comisd mem reg 1159 1160 //! 1161 void compare_sd_mem_with_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical, 1162 int reg, bool isPhysical) { 1163 Mnemonic m = Mnemonic_COMISD; 1164 dump_mem_reg(m, ATOM_NORMAL, OpndSize_64, disp, base_reg, isBasePhysical, 1165 MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm); 1166 } 1167 //! comisd reg reg 1168 1169 //! 1170 void compare_sd_reg_with_reg(LowOp* op, int reg1, bool isPhysical1, 1171 int reg2, bool isPhysical2) { 1172 Mnemonic m = Mnemonic_COMISD; 1173 dump_reg_reg(m, ATOM_NORMAL, OpndSize_64, reg1, isPhysical1, reg2, isPhysical2, LowOpndRegType_xmm); 1174 } 1175 //! fucom[p] 1176 1177 //! 1178 void compare_fp_stack(bool pop, int reg, bool isDouble) { //compare ST(0) with ST(reg) 1179 Mnemonic m = pop ? Mnemonic_FUCOMP : Mnemonic_FUCOM; 1180 lower_reg_reg(m, ATOM_NORMAL, isDouble ? OpndSize_64 : OpndSize_32, 1181 PhysicalReg_ST0+reg, PhysicalReg_ST0, LowOpndRegType_fs); 1182 } 1183 /*! 1184 \brief generate a single return instruction 1185 1186 */ 1187 LowOp* lower_return() { 1188 stream = encoder_return(stream); 1189 return NULL; 1190 } 1191 1192 void x86_return() { 1193 lower_return(); 1194 } 1195 1196 //!test imm reg 1197 1198 //! 1199 void test_imm_reg(OpndSize size, int imm, int reg, bool isPhysical) { 1200 dump_imm_reg(Mnemonic_TEST, ATOM_NORMAL, size, imm, reg, isPhysical, getTypeFromIntSize(size), false); 1201 } 1202 //!test imm mem 1203 1204 //! 1205 void test_imm_mem(OpndSize size, int imm, int disp, int reg, bool isPhysical) { 1206 dump_imm_mem(Mnemonic_TEST, ATOM_NORMAL, size, imm, disp, reg, isPhysical, MemoryAccess_Unknown, -1, false); 1207 } 1208 //!alu unary op with one reg operand 1209 1210 //! 1211 void alu_unary_reg(OpndSize size, ALU_Opcode opc, int reg, bool isPhysical) { 1212 Mnemonic m; 1213 if(size == OpndSize_64) 1214 m = map_of_64_opcode_2_mnemonic[opc]; 1215 else 1216 m = map_of_alu_opcode_2_mnemonic[opc]; 1217 dump_reg(m, ATOM_NORMAL_ALU, size, reg, isPhysical, getTypeFromIntSize(size)); 1218 } 1219 //!alu unary op with one mem operand 1220 1221 //! 1222 void alu_unary_mem(LowOp* op, OpndSize size, ALU_Opcode opc, int disp, int base_reg, bool isBasePhysical) { 1223 Mnemonic m; 1224 if(size == OpndSize_64) 1225 m = map_of_64_opcode_2_mnemonic[opc]; 1226 else 1227 m = map_of_alu_opcode_2_mnemonic[opc]; 1228 dump_mem(m, ATOM_NORMAL_ALU, size, disp, base_reg, isBasePhysical); 1229 } 1230 //!alu binary op with immediate and one mem operand 1231 1232 //! 1233 void alu_binary_imm_mem(OpndSize size, ALU_Opcode opc, int imm, int disp, int base_reg, bool isBasePhysical) { 1234 Mnemonic m; 1235 if(size == OpndSize_64) 1236 m = map_of_64_opcode_2_mnemonic[opc]; 1237 else 1238 m = map_of_alu_opcode_2_mnemonic[opc]; 1239 dump_imm_mem(m, ATOM_NORMAL_ALU, size, imm, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, false); 1240 } 1241 //!alu binary op with immediate and one reg operand 1242 1243 //! 1244 void alu_binary_imm_reg(OpndSize size, ALU_Opcode opc, int imm, int reg, bool isPhysical) { 1245 Mnemonic m; 1246 if(size == OpndSize_64) 1247 m = map_of_64_opcode_2_mnemonic[opc]; 1248 else 1249 m = map_of_alu_opcode_2_mnemonic[opc]; 1250 dump_imm_reg(m, ATOM_NORMAL_ALU, size, imm, reg, isPhysical, getTypeFromIntSize(size), false); 1251 } 1252 //!alu binary op with one mem operand and one reg operand 1253 1254 //! 1255 void alu_binary_mem_reg(OpndSize size, ALU_Opcode opc, 1256 int disp, int base_reg, bool isBasePhysical, 1257 int reg, bool isPhysical) { 1258 Mnemonic m; 1259 if(size == OpndSize_64) 1260 m = map_of_64_opcode_2_mnemonic[opc]; 1261 else 1262 m = map_of_alu_opcode_2_mnemonic[opc]; 1263 dump_mem_reg(m, ATOM_NORMAL_ALU, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, getTypeFromIntSize(size)); 1264 } 1265 1266 void alu_sd_binary_VR_reg(ALU_Opcode opc, int vA, int reg, bool isPhysical, bool isSD) { 1267 Mnemonic m; 1268 if(isSD) m = map_of_sse_opcode_2_mnemonic[opc]; 1269 else m = (Mnemonic)(map_of_sse_opcode_2_mnemonic[opc]+1); //from SD to SS 1270 OpndSize size = isSD ? OpndSize_64 : OpndSize_32; 1271 if(gDvm.executionMode == kExecutionModeNcgO1) { 1272 LowOpndRegType type = isSD ? LowOpndRegType_xmm : LowOpndRegType_ss; //type of the mem operand 1273 int tmpValue[2]; 1274 int isConst = isVirtualRegConstant(vA, type, tmpValue, 1275 true/*updateRefCount*/); 1276 if(isConst == 3 && !isSD) { 1277 //isConst can be 0 or 3, mem32, use xmm 1278 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1279 dump_mem_reg(m, ATOM_NORMAL_ALU, OpndSize_32, 4*vA, PhysicalReg_FP, true, 1280 MemoryAccess_VR, vA, reg, isPhysical, 1281 LowOpndRegType_xmm); 1282 return; 1283 } 1284 if(isConst == 3 && isSD) { 1285 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1286 dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]); 1287 dump_mem_reg(m, ATOM_NORMAL_ALU, OpndSize_64, 4*vA, PhysicalReg_FP, true, 1288 MemoryAccess_VR, vA, reg, isPhysical, LowOpndRegType_xmm); 1289 return; 1290 } 1291 if(isConst == 1) dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1292 if(isConst == 2) dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]); 1293 freeReg(true); 1294 1295 int regAll = checkVirtualReg(vA, type, 0/*do not update refCount*/); 1296 if(regAll != PhysicalReg_Null) { 1297 startNativeCode(-1, -1); //should we use vA, type 1298 //CHECK: callupdateVRAtUse 1299 donotSpillReg(regAll); 1300 dump_reg_reg_noalloc_src(m, ATOM_NORMAL_ALU, size, regAll, true, reg, 1301 isPhysical, LowOpndRegType_xmm); 1302 endNativeCode(); 1303 } 1304 else { 1305 dump_mem_reg_noalloc_mem(m, ATOM_NORMAL_ALU, size, 4*vA, PhysicalReg_FP, true, 1306 MemoryAccess_VR, vA, reg, isPhysical, LowOpndRegType_xmm); 1307 } 1308 updateRefCount(vA, type); 1309 } 1310 else { 1311 dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true, 1312 MemoryAccess_VR, vA, reg, isPhysical, LowOpndRegType_xmm); 1313 } 1314 } 1315 1316 //!alu binary op with a VR and one reg operand 1317 1318 //! 1319 void alu_binary_VR_reg(OpndSize size, ALU_Opcode opc, int vA, int reg, bool isPhysical) { 1320 Mnemonic m; 1321 if(size == OpndSize_64) 1322 m = map_of_64_opcode_2_mnemonic[opc]; 1323 else 1324 m = map_of_alu_opcode_2_mnemonic[opc]; 1325 if(gDvm.executionMode == kExecutionModeNcgO1) { 1326 int tmpValue[2]; 1327 int isConst = isVirtualRegConstant(vA, getTypeFromIntSize(size), tmpValue, 1328 true/*updateRefCount*/); 1329 if(isConst == 3 && size != OpndSize_64) { 1330 //allocate a register for dst 1331 dump_imm_reg(m, ATOM_NORMAL_ALU, size, tmpValue[0], reg, isPhysical, 1332 getTypeFromIntSize(size), false); 1333 return; 1334 } 1335 if(isConst == 3 && size == OpndSize_64) { 1336 dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1337 dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]); 1338 dump_mem_reg(m, ATOM_NORMAL_ALU, size, 4*vA, PhysicalReg_FP, true, 1339 MemoryAccess_VR, vA, reg, isPhysical, getTypeFromIntSize(size)); 1340 return; 1341 } 1342 if(isConst == 1) dumpImmToMem(vA, OpndSize_32, tmpValue[0]); 1343 if(isConst == 2) dumpImmToMem(vA+1, OpndSize_32, tmpValue[1]); 1344 1345 freeReg(true); 1346 int regAll = checkVirtualReg(vA, getTypeFromIntSize(size), 0); 1347 if(regAll != PhysicalReg_Null) { 1348 startNativeCode(-1, -1); 1349 donotSpillReg(regAll); 1350 dump_reg_reg_noalloc_src(m, ATOM_NORMAL_ALU, size, regAll, true, reg, 1351 isPhysical, getTypeFromIntSize(size)); 1352 endNativeCode(); 1353 } 1354 else { 1355 dump_mem_reg_noalloc_mem(m, ATOM_NORMAL_ALU, size, 4*vA, PhysicalReg_FP, true, 1356 MemoryAccess_VR, vA, reg, isPhysical, getTypeFromIntSize(size)); 1357 } 1358 updateRefCount(vA, getTypeFromIntSize(size)); 1359 } 1360 else { 1361 dump_mem_reg(m, ATOM_NORMAL, size, 4*vA, PhysicalReg_FP, true, 1362 MemoryAccess_VR, vA, reg, isPhysical, getTypeFromIntSize(size)); 1363 } 1364 } 1365 //!alu binary op with two reg operands 1366 1367 //! 1368 void alu_binary_reg_reg(OpndSize size, ALU_Opcode opc, 1369 int reg1, bool isPhysical1, 1370 int reg2, bool isPhysical2) { 1371 Mnemonic m; 1372 if(size == OpndSize_64) 1373 m = map_of_64_opcode_2_mnemonic[opc]; 1374 else 1375 m = map_of_alu_opcode_2_mnemonic[opc]; 1376 dump_reg_reg(m, ATOM_NORMAL_ALU, size, reg1, isPhysical1, reg2, isPhysical2, getTypeFromIntSize(size)); 1377 } 1378 //!alu binary op with one reg operand and one mem operand 1379 1380 //! 1381 void alu_binary_reg_mem(OpndSize size, ALU_Opcode opc, 1382 int reg, bool isPhysical, 1383 int disp, int base_reg, bool isBasePhysical) { //destination is mem!! 1384 Mnemonic m; 1385 if(size == OpndSize_64) 1386 m = map_of_64_opcode_2_mnemonic[opc]; 1387 else 1388 m = map_of_alu_opcode_2_mnemonic[opc]; 1389 dump_reg_mem(m, ATOM_NORMAL_ALU, size, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, getTypeFromIntSize(size)); 1390 } 1391 //!FPU ops with one mem operand 1392 1393 //! 1394 void fpu_mem(LowOp* op, ALU_Opcode opc, OpndSize size, int disp, int base_reg, bool isBasePhysical) { 1395 Mnemonic m = map_of_fpu_opcode_2_mnemonic[opc]; 1396 dump_mem_fp(m, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, 0); 1397 } 1398 //!SSE 32-bit ALU 1399 1400 //! 1401 void alu_ss_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical, 1402 int reg2, bool isPhysical2) { 1403 Mnemonic m = (Mnemonic)(map_of_sse_opcode_2_mnemonic[opc]+1); //from SD to SS 1404 dump_reg_reg(m, ATOM_NORMAL_ALU, OpndSize_32, reg, isPhysical, reg2, isPhysical2, LowOpndRegType_xmm); 1405 } 1406 //!SSE 64-bit ALU 1407 1408 //! 1409 void alu_sd_binary_reg_reg(ALU_Opcode opc, int reg, bool isPhysical, 1410 int reg2, bool isPhysical2) { 1411 Mnemonic m = map_of_sse_opcode_2_mnemonic[opc]; 1412 dump_reg_reg(m, ATOM_NORMAL_ALU, OpndSize_64, reg, isPhysical, reg2, isPhysical2, LowOpndRegType_xmm); 1413 } 1414 //!push reg to native stack 1415 1416 //! 1417 void push_reg_to_stack(OpndSize size, int reg, bool isPhysical) { 1418 dump_reg(Mnemonic_PUSH, ATOM_NORMAL, size, reg, isPhysical, getTypeFromIntSize(size)); 1419 } 1420 //!push mem to native stack 1421 1422 //! 1423 void push_mem_to_stack(OpndSize size, int disp, int base_reg, bool isBasePhysical) { 1424 dump_mem(Mnemonic_PUSH, ATOM_NORMAL, size, disp, base_reg, isBasePhysical); 1425 } 1426 //!move from reg to memory 1427 1428 //! 1429 void move_reg_to_mem(OpndSize size, 1430 int reg, bool isPhysical, 1431 int disp, int base_reg, bool isBasePhysical) { 1432 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1433 dump_reg_mem(m, ATOM_NORMAL, size, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, getTypeFromIntSize(size)); 1434 } 1435 //!move from reg to memory 1436 1437 //!Operands are already allocated 1438 void move_reg_to_mem_noalloc(OpndSize size, 1439 int reg, bool isPhysical, 1440 int disp, int base_reg, bool isBasePhysical, 1441 MemoryAccessType mType, int mIndex) { 1442 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1443 dump_reg_mem_noalloc(m, size, reg, isPhysical, disp, base_reg, isBasePhysical, mType, mIndex, getTypeFromIntSize(size)); 1444 } 1445 //!move from memory to reg 1446 1447 //! 1448 LowOpRegMem* move_mem_to_reg(OpndSize size, 1449 int disp, int base_reg, bool isBasePhysical, 1450 int reg, bool isPhysical) { 1451 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1452 return dump_mem_reg(m, ATOM_NORMAL, size, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, getTypeFromIntSize(size)); 1453 } 1454 //!move from memory to reg 1455 1456 //!Operands are already allocated 1457 LowOpRegMem* move_mem_to_reg_noalloc(OpndSize size, 1458 int disp, int base_reg, bool isBasePhysical, 1459 MemoryAccessType mType, int mIndex, 1460 int reg, bool isPhysical) { 1461 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1462 return dump_mem_reg_noalloc(m, size, disp, base_reg, isBasePhysical, mType, mIndex, reg, isPhysical, getTypeFromIntSize(size)); 1463 } 1464 //!movss from memory to reg 1465 1466 //!Operands are already allocated 1467 LowOpRegMem* move_ss_mem_to_reg_noalloc(int disp, int base_reg, bool isBasePhysical, 1468 MemoryAccessType mType, int mIndex, 1469 int reg, bool isPhysical) { 1470 return dump_mem_reg_noalloc(Mnemonic_MOVSS, OpndSize_32, disp, base_reg, isBasePhysical, mType, mIndex, reg, isPhysical, LowOpndRegType_xmm); 1471 } 1472 //!movss from reg to memory 1473 1474 //!Operands are already allocated 1475 LowOpMemReg* move_ss_reg_to_mem_noalloc(int reg, bool isPhysical, 1476 int disp, int base_reg, bool isBasePhysical, 1477 MemoryAccessType mType, int mIndex) { 1478 return dump_reg_mem_noalloc(Mnemonic_MOVSS, OpndSize_32, reg, isPhysical, disp, base_reg, isBasePhysical, mType, mIndex, LowOpndRegType_xmm); 1479 } 1480 //!movzx from memory to reg 1481 1482 //! 1483 void movez_mem_to_reg(OpndSize size, 1484 int disp, int base_reg, bool isBasePhysical, 1485 int reg, bool isPhysical) { 1486 Mnemonic m = Mnemonic_MOVZX; 1487 dump_movez_mem_reg(m, size, disp, base_reg, isBasePhysical, reg, isPhysical); 1488 } 1489 1490 //!movzx from one reg to another reg 1491 1492 //! 1493 void movez_reg_to_reg(OpndSize size, 1494 int reg, bool isPhysical, 1495 int reg2, bool isPhysical2) { 1496 Mnemonic m = Mnemonic_MOVZX; 1497 dump_movez_reg_reg(m, size, reg, isPhysical, reg2, isPhysical2); 1498 } 1499 1500 void movez_mem_disp_scale_to_reg(OpndSize size, 1501 int base_reg, bool isBasePhysical, 1502 int disp, int index_reg, bool isIndexPhysical, int scale, 1503 int reg, bool isPhysical) { 1504 dump_mem_scale_reg(Mnemonic_MOVZX, size, base_reg, isBasePhysical, 1505 disp, index_reg, isIndexPhysical, scale, 1506 reg, isPhysical, LowOpndRegType_gp); 1507 } 1508 void moves_mem_disp_scale_to_reg(OpndSize size, 1509 int base_reg, bool isBasePhysical, 1510 int disp, int index_reg, bool isIndexPhysical, int scale, 1511 int reg, bool isPhysical) { 1512 dump_mem_scale_reg(Mnemonic_MOVSX, size, base_reg, isBasePhysical, 1513 disp, index_reg, isIndexPhysical, scale, 1514 reg, isPhysical, LowOpndRegType_gp); 1515 } 1516 1517 //!movsx from memory to reg 1518 1519 //! 1520 void moves_mem_to_reg(LowOp* op, OpndSize size, 1521 int disp, int base_reg, bool isBasePhysical, 1522 int reg, bool isPhysical) { 1523 Mnemonic m = Mnemonic_MOVSX; 1524 dump_moves_mem_reg(m, size, disp, base_reg, isBasePhysical, reg, isPhysical); 1525 } 1526 //!mov from one reg to another reg 1527 1528 //! 1529 void move_reg_to_reg(OpndSize size, 1530 int reg, bool isPhysical, 1531 int reg2, bool isPhysical2) { 1532 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1533 dump_reg_reg(m, ATOM_NORMAL, size, reg, isPhysical, reg2, isPhysical2, getTypeFromIntSize(size)); 1534 } 1535 //!mov from one reg to another reg 1536 1537 //!Operands are already allocated 1538 void move_reg_to_reg_noalloc(OpndSize size, 1539 int reg, bool isPhysical, 1540 int reg2, bool isPhysical2) { 1541 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1542 dump_reg_reg_noalloc(m, size, reg, isPhysical, reg2, isPhysical2, getTypeFromIntSize(size)); 1543 } 1544 //!move from memory to reg 1545 1546 //! 1547 void move_mem_scale_to_reg(OpndSize size, 1548 int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale, 1549 int reg, bool isPhysical) { 1550 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1551 dump_mem_scale_reg(m, size, base_reg, isBasePhysical, 0/*disp*/, index_reg, isIndexPhysical, scale, 1552 reg, isPhysical, getTypeFromIntSize(size)); 1553 } 1554 void move_mem_disp_scale_to_reg(OpndSize size, 1555 int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale, 1556 int reg, bool isPhysical) { 1557 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1558 dump_mem_scale_reg(m, size, base_reg, isBasePhysical, disp, index_reg, isIndexPhysical, scale, 1559 reg, isPhysical, getTypeFromIntSize(size)); 1560 } 1561 //!move from reg to memory 1562 1563 //! 1564 void move_reg_to_mem_scale(OpndSize size, 1565 int reg, bool isPhysical, 1566 int base_reg, bool isBasePhysical, int index_reg, bool isIndexPhysical, int scale) { 1567 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1568 dump_reg_mem_scale(m, size, reg, isPhysical, 1569 base_reg, isBasePhysical, 0/*disp*/, index_reg, isIndexPhysical, scale, 1570 getTypeFromIntSize(size)); 1571 } 1572 void move_reg_to_mem_disp_scale(OpndSize size, 1573 int reg, bool isPhysical, 1574 int base_reg, bool isBasePhysical, int disp, int index_reg, bool isIndexPhysical, int scale) { 1575 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1576 dump_reg_mem_scale(m, size, reg, isPhysical, 1577 base_reg, isBasePhysical, disp, index_reg, isIndexPhysical, scale, 1578 getTypeFromIntSize(size)); 1579 } 1580 1581 void move_chain_to_mem(OpndSize size, int imm, 1582 int disp, int base_reg, bool isBasePhysical) { 1583 dump_imm_mem(Mnemonic_MOV, ATOM_NORMAL, size, imm, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, true); 1584 } 1585 1586 //!move an immediate to memory 1587 1588 //! 1589 void move_imm_to_mem(OpndSize size, int imm, 1590 int disp, int base_reg, bool isBasePhysical) { 1591 assert(size != OpndSize_64); 1592 if(size == OpndSize_64) ALOGE("move_imm_to_mem with 64 bits"); 1593 dump_imm_mem(Mnemonic_MOV, ATOM_NORMAL, size, imm, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, false); 1594 } 1595 //! set a VR to an immediate 1596 1597 //! 1598 void set_VR_to_imm(u2 vA, OpndSize size, int imm) { 1599 assert(size != OpndSize_64); 1600 if(size == OpndSize_64) ALOGE("move_imm_to_mem with 64 bits"); 1601 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1602 if(gDvm.executionMode == kExecutionModeNcgO1) { 1603 int regAll = checkVirtualReg(vA, getTypeFromIntSize(size), 0); 1604 if(regAll != PhysicalReg_Null) { 1605 dump_imm_reg_noalloc(m, size, imm, regAll, true, LowOpndRegType_gp); 1606 updateRefCount(vA, getTypeFromIntSize(size)); 1607 updateVirtualReg(vA, getTypeFromIntSize(size)); 1608 return; 1609 } 1610 //will call freeReg 1611 freeReg(true); 1612 regAll = registerAlloc(LowOpndRegType_virtual | getTypeFromIntSize(size), vA, false/*dummy*/, true); 1613 if(regAll == PhysicalReg_Null) { 1614 dump_imm_mem_noalloc(m, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA); 1615 return; 1616 } 1617 dump_imm_reg_noalloc(m, size, imm, regAll, true, LowOpndRegType_gp); 1618 updateVirtualReg(vA, getTypeFromIntSize(size)); 1619 } 1620 else { 1621 dump_imm_mem(m, ATOM_NORMAL, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA, false); 1622 } 1623 } 1624 void set_VR_to_imm_noupdateref(LowOp* op, u2 vA, OpndSize size, int imm) { 1625 return; 1626 } 1627 //! set a VR to an immediate 1628 1629 //! Do not allocate a physical register for the VR 1630 void set_VR_to_imm_noalloc(u2 vA, OpndSize size, int imm) { 1631 assert(size != OpndSize_64); 1632 if(size == OpndSize_64) ALOGE("move_imm_to_mem with 64 bits"); 1633 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1634 dump_imm_mem_noalloc(m, size, imm, 4*vA, PhysicalReg_FP, true, MemoryAccess_VR, vA); 1635 } 1636 1637 void move_chain_to_reg(OpndSize size, int imm, int reg, bool isPhysical) { 1638 dump_imm_reg(Mnemonic_MOV, ATOM_NORMAL, size, imm, reg, isPhysical, LowOpndRegType_gp, true); 1639 } 1640 1641 //! move an immediate to reg 1642 1643 //! 1644 void move_imm_to_reg(OpndSize size, int imm, int reg, bool isPhysical) { 1645 assert(size != OpndSize_64); 1646 if(size == OpndSize_64) ALOGE("move_imm_to_reg with 64 bits"); 1647 Mnemonic m = Mnemonic_MOV; 1648 dump_imm_reg(m, ATOM_NORMAL, size, imm, reg, isPhysical, LowOpndRegType_gp, false); 1649 } 1650 //! move an immediate to reg 1651 1652 //! The operand is already allocated 1653 void move_imm_to_reg_noalloc(OpndSize size, int imm, int reg, bool isPhysical) { 1654 assert(size != OpndSize_64); 1655 if(size == OpndSize_64) ALOGE("move_imm_to_reg with 64 bits"); 1656 Mnemonic m = Mnemonic_MOV; 1657 dump_imm_reg_noalloc(m, size, imm, reg, isPhysical, LowOpndRegType_gp); 1658 } 1659 //!cmov from reg to reg 1660 1661 //! 1662 void conditional_move_reg_to_reg(OpndSize size, ConditionCode cc, int reg1, bool isPhysical1, int reg, bool isPhysical) { 1663 Mnemonic m = (Mnemonic)(Mnemonic_CMOVcc+cc); 1664 dump_reg_reg(m, ATOM_NORMAL, size, reg1, isPhysical1, reg, isPhysical, LowOpndRegType_gp); 1665 } 1666 //!movss from memory to reg 1667 1668 //! 1669 void move_ss_mem_to_reg(LowOp* op, int disp, int base_reg, bool isBasePhysical, 1670 int reg, bool isPhysical) { 1671 dump_mem_reg(Mnemonic_MOVSS, ATOM_NORMAL, OpndSize_32, disp, base_reg, isBasePhysical, 1672 MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm); 1673 } 1674 //!movss from reg to memory 1675 1676 //! 1677 void move_ss_reg_to_mem(LowOp* op, int reg, bool isPhysical, 1678 int disp, int base_reg, bool isBasePhysical) { 1679 dump_reg_mem(Mnemonic_MOVSS, ATOM_NORMAL, OpndSize_32, reg, isPhysical, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, LowOpndRegType_xmm); 1680 } 1681 //!movsd from memory to reg 1682 1683 //! 1684 void move_sd_mem_to_reg(int disp, int base_reg, bool isBasePhysical, 1685 int reg, bool isPhysical) { 1686 dump_mem_reg(Mnemonic_MOVSD, ATOM_NORMAL, OpndSize_64, disp, base_reg, isBasePhysical, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_xmm); 1687 } 1688 //!movsd from reg to memory 1689 1690 //! 1691 void move_sd_reg_to_mem(LowOp* op, int reg, bool isPhysical, 1692 int disp, int base_reg, bool isBasePhysical) { 1693 dump_reg_mem(Mnemonic_MOVSD, ATOM_NORMAL, OpndSize_64, reg, isPhysical, 1694 disp, base_reg, isBasePhysical, 1695 MemoryAccess_Unknown, -1, LowOpndRegType_xmm); 1696 } 1697 //!load from VR to a temporary 1698 1699 //! 1700 void get_virtual_reg_all(u2 vB, OpndSize size, int reg, bool isPhysical, Mnemonic m) { 1701 LowOpndRegType type = getTypeFromIntSize(size); 1702 LowOpndRegType pType = type;//gp or xmm 1703 OpndSize size2 = size; 1704 Mnemonic m2 = m; 1705 if(m == Mnemonic_MOVSS) { 1706 size = OpndSize_32; 1707 size2 = OpndSize_64; 1708 type = LowOpndRegType_ss; 1709 pType = LowOpndRegType_xmm; 1710 m2 = Mnemonic_MOVQ; //to move from one xmm register to another 1711 } 1712 if(gDvm.executionMode == kExecutionModeNcgO1) { 1713 int tmpValue[2]; 1714 int isConst; 1715 isConst = isVirtualRegConstant(vB, type, tmpValue, true/*updateRefCount*/); 1716 if(isConst == 3) { 1717 if(m == Mnemonic_MOVSS) { //load 32 bits from VR 1718 //VR is not mapped to a register but in memory 1719 dumpImmToMem(vB, OpndSize_32, tmpValue[0]); 1720 //temporary reg has "pType" (which is xmm) 1721 dump_mem_reg(m, ATOM_NORMAL, size, 4*vB, PhysicalReg_FP, true, 1722 MemoryAccess_VR, vB, reg, isPhysical, pType); 1723 return; 1724 } 1725 else if(m == Mnemonic_MOVSD || size == OpndSize_64) { 1726 //VR is not mapped to a register but in memory 1727 dumpImmToMem(vB, OpndSize_32, tmpValue[0]); 1728 dumpImmToMem(vB+1, OpndSize_32, tmpValue[1]); 1729 dump_mem_reg(m, ATOM_NORMAL, size, 4*vB, PhysicalReg_FP, true, 1730 MemoryAccess_VR, vB, reg, isPhysical, pType); 1731 return; 1732 } 1733 else if(size != OpndSize_64) { 1734 //VR is not mapped to a register 1735 dump_imm_reg(m, ATOM_NORMAL, size, tmpValue[0], reg, isPhysical, pType, false); 1736 return; 1737 } 1738 } 1739 if(isConst == 1) dumpImmToMem(vB, OpndSize_32, tmpValue[0]); 1740 if(isConst == 2) dumpImmToMem(vB+1, OpndSize_32, tmpValue[1]); 1741 freeReg(true); 1742 int regAll = checkVirtualReg(vB, type, 0); 1743 if(regAll != PhysicalReg_Null) { 1744 startNativeCode(vB, type); 1745 donotSpillReg(regAll); 1746 //check XFER_MEM_TO_XMM 1747 updateVRAtUse(vB, type, regAll); 1748 //temporary reg has "pType" 1749 dump_reg_reg_noalloc_src(m2, ATOM_NORMAL, size2, regAll, true, reg, isPhysical, pType); //register allocator handles assembly move 1750 endNativeCode(); 1751 updateRefCount(vB, type); 1752 return; 1753 } 1754 //not allocated to a register yet, no need to check XFER_MEM_TO_XMM 1755 regAll = registerAlloc(LowOpndRegType_virtual | type, vB, false/*dummy*/, false); 1756 if(regAll == PhysicalReg_Null) { 1757 dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true, 1758 MemoryAccess_VR, vB, reg, isPhysical, pType); 1759 return; 1760 } 1761 1762 //temporary reg has pType 1763 if(checkTempReg2(reg, pType, isPhysical, regAll)) { 1764 registerAllocMove(reg, pType, isPhysical, regAll); 1765 dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true, 1766 MemoryAccess_VR, vB, regAll, true, pType); 1767 updateRefCount(vB, type); 1768 return; 1769 } 1770 else { 1771 dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true, 1772 MemoryAccess_VR, vB, regAll, true, pType); 1773 //xmm with 32 bits 1774 startNativeCode(vB, type); 1775 donotSpillReg(regAll); 1776 dump_reg_reg_noalloc_src(m2, ATOM_NORMAL, size2, regAll, true, reg, isPhysical, pType); 1777 endNativeCode(); 1778 updateRefCount(vB, type); 1779 return; 1780 } 1781 } 1782 else { 1783 dump_mem_reg(m, ATOM_NORMAL, size, 4*vB, PhysicalReg_FP, true, 1784 MemoryAccess_VR, vB, reg, isPhysical, pType); 1785 } 1786 } 1787 void get_virtual_reg(u2 vB, OpndSize size, int reg, bool isPhysical) { 1788 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1789 return get_virtual_reg_all(vB, size, reg, isPhysical, m); 1790 } 1791 void get_virtual_reg_noalloc(u2 vB, OpndSize size, int reg, bool isPhysical) { 1792 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1793 dump_mem_reg_noalloc(m, size, 4*vB, PhysicalReg_FP, true, 1794 MemoryAccess_VR, vB, reg, isPhysical, getTypeFromIntSize(size)); 1795 } 1796 //3 cases: gp, xmm, ss 1797 //ss: the temporary register is xmm 1798 //!load from a temporary to a VR 1799 1800 //! 1801 void set_virtual_reg_all(u2 vA, OpndSize size, int reg, bool isPhysical, Mnemonic m) { 1802 LowOpndRegType type = getTypeFromIntSize(size); 1803 LowOpndRegType pType = type;//gp or xmm 1804 OpndSize size2 = size; 1805 Mnemonic m2 = m; 1806 if(m == Mnemonic_MOVSS) { 1807 size = OpndSize_32; 1808 size2 = OpndSize_64; 1809 type = LowOpndRegType_ss; 1810 pType = LowOpndRegType_xmm; 1811 m2 = Mnemonic_MOVQ; 1812 } 1813 if(gDvm.executionMode == kExecutionModeNcgO1) { 1814 //3 cases 1815 //1: virtual register is already allocated to a physical register 1816 // call dump_reg_reg_noalloc_dst 1817 //2: src reg is already allocated, VR is not yet allocated 1818 // allocate VR to the same physical register used by src reg 1819 // [call registerAllocMove] 1820 //3: both not yet allocated 1821 // allocate a physical register for the VR 1822 // then call dump_reg_reg_noalloc_dst 1823 //may need to convert from gp to xmm or the other way 1824 freeReg(true); 1825 int regAll = checkVirtualReg(vA, type, 0); 1826 if(regAll != PhysicalReg_Null) { //case 1 1827 startNativeCode(-1, -1); 1828 donotSpillReg(regAll); 1829 dump_reg_reg_noalloc_dst(m2, size2, reg, isPhysical, regAll, true, pType); //temporary reg is "pType" 1830 endNativeCode(); 1831 updateRefCount(vA, type); 1832 updateVirtualReg(vA, type); //will dump VR to memory, should happen afterwards 1833 return; 1834 } 1835 regAll = checkTempReg(reg, pType, isPhysical, vA); //vA is not used inside 1836 if(regAll != PhysicalReg_Null) { //case 2 1837 registerAllocMove(vA, LowOpndRegType_virtual | type, false, regAll); 1838 updateVirtualReg(vA, type); //will dump VR to memory, should happen afterwards 1839 return; //next native instruction starts at op 1840 } 1841 //case 3 1842 regAll = registerAlloc(LowOpndRegType_virtual | type, vA, false/*dummy*/, false); 1843 if(regAll == PhysicalReg_Null) { 1844 dump_reg_mem_noalloc(m, size, reg, isPhysical, 4*vA, PhysicalReg_FP, true, 1845 MemoryAccess_VR, vA, pType); 1846 return; 1847 } 1848 startNativeCode(-1, -1); 1849 donotSpillReg(regAll); 1850 dump_reg_reg_noalloc_dst(m2, size2, reg, isPhysical, regAll, true, pType); 1851 endNativeCode(); 1852 updateRefCount(vA, type); 1853 updateVirtualReg(vA, type); 1854 } 1855 else { 1856 dump_reg_mem(m, ATOM_NORMAL, size, reg, isPhysical, 4*vA, PhysicalReg_FP, true, 1857 MemoryAccess_VR, vA, pType); 1858 } 1859 } 1860 void set_virtual_reg(u2 vA, OpndSize size, int reg, bool isPhysical) { 1861 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1862 return set_virtual_reg_all(vA, size, reg, isPhysical, m); 1863 } 1864 void set_virtual_reg_noalloc(u2 vA, OpndSize size, int reg, bool isPhysical) { 1865 Mnemonic m = (size == OpndSize_64) ? Mnemonic_MOVQ : Mnemonic_MOV; 1866 dump_reg_mem_noalloc(m, size, reg, isPhysical, 4*vA, PhysicalReg_FP, true, 1867 MemoryAccess_VR, vA, getTypeFromIntSize(size)); 1868 } 1869 void get_VR_ss(int vB, int reg, bool isPhysical) { 1870 return get_virtual_reg_all(vB, OpndSize_64, reg, isPhysical, Mnemonic_MOVSS); 1871 } 1872 void set_VR_ss(int vA, int reg, bool isPhysical) { 1873 return set_virtual_reg_all(vA, OpndSize_64, reg, isPhysical, Mnemonic_MOVSS); 1874 } 1875 void get_VR_sd(int vB, int reg, bool isPhysical) { 1876 return get_virtual_reg_all(vB, OpndSize_64, reg, isPhysical, Mnemonic_MOVSD); 1877 } 1878 void set_VR_sd(int vA, int reg, bool isPhysical) { 1879 return set_virtual_reg_all(vA, OpndSize_64, reg, isPhysical, Mnemonic_MOVSD); 1880 } 1881 ////////////////////////////////// END: IA32 native instructions ////////////// 1882 //! generate native instructions to get current PC in the stack frame 1883 1884 //! 1885 int get_currentpc(int reg, bool isPhysical) { 1886 move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_localRefTop, PhysicalReg_FP, true, reg, isPhysical); 1887 return 1; 1888 } 1889 //!generate native code to perform null check 1890 1891 //!This function does not export PC 1892 int simpleNullCheck(int reg, bool isPhysical, int vr) { 1893 if(isVRNullCheck(vr, OpndSize_32)) { 1894 updateRefCount2(reg, LowOpndRegType_gp, isPhysical); 1895 num_removed_nullCheck++; 1896 return 0; 1897 } 1898 compare_imm_reg(OpndSize_32, 0, reg, isPhysical); 1899 conditional_jump_global_API(Condition_E, "common_errNullObject", false); 1900 setVRNullCheck(vr, OpndSize_32); 1901 return 0; 1902 } 1903 1904 /* only for O1 code generator */ 1905 int boundCheck(int vr_array, int reg_array, bool isPhysical_array, 1906 int vr_index, int reg_index, bool isPhysical_index, 1907 int exceptionNum) { 1908 #ifdef BOUNDCHECK_OPT 1909 if(isVRBoundCheck(vr_array, vr_index)) { 1910 updateRefCount2(reg_array, LowOpndRegType_gp, isPhysical_array); 1911 updateRefCount2(reg_index, LowOpndRegType_gp, isPhysical_index); 1912 return 0; 1913 } 1914 #endif 1915 compare_mem_reg(OpndSize_32, offArrayObject_length, 1916 reg_array, isPhysical_array, 1917 reg_index, isPhysical_index); 1918 1919 char errName[256]; 1920 sprintf(errName, "common_errArrayIndex"); 1921 handlePotentialException( 1922 Condition_NC, Condition_C, 1923 exceptionNum, errName); 1924 #ifdef BOUNDCHECK_OPT 1925 setVRBoundCheck(vr_array, vr_index); 1926 #endif 1927 return 0; 1928 } 1929 1930 //!generate native code to perform null check 1931 1932 //! 1933 int nullCheck(int reg, bool isPhysical, int exceptionNum, int vr) { 1934 char label[LABEL_SIZE]; 1935 1936 if(gDvm.executionMode == kExecutionModeNcgO1) { 1937 //nullCheck optimization is available in O1 mode only 1938 if(isVRNullCheck(vr, OpndSize_32)) { 1939 updateRefCount2(reg, LowOpndRegType_gp, isPhysical); 1940 if(exceptionNum <= 1) { 1941 updateRefCount2(PhysicalReg_EDX, LowOpndRegType_gp, true); 1942 updateRefCount2(PhysicalReg_EDX, LowOpndRegType_gp, true); 1943 } 1944 num_removed_nullCheck++; 1945 return 0; 1946 } 1947 compare_imm_reg(OpndSize_32, 0, reg, isPhysical); 1948 rememberState(exceptionNum); 1949 snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum); 1950 conditional_jump(Condition_NE, label, true); 1951 if(exceptionNum > 1) 1952 nextVersionOfHardReg(PhysicalReg_EDX, 2); //next version has 2 ref count 1953 export_pc(); //use %edx 1954 constVREndOfBB(); 1955 beforeCall("exception"); //dump GG, GL VRs 1956 unconditional_jump_global_API("common_errNullObject", false); 1957 insertLabel(label, true); 1958 goToState(exceptionNum); 1959 setVRNullCheck(vr, OpndSize_32); 1960 } else { 1961 compare_imm_reg(OpndSize_32, 0, reg, isPhysical); 1962 snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum); 1963 conditional_jump(Condition_NE, label, true); 1964 export_pc(); //use %edx 1965 unconditional_jump_global_API("common_errNullObject", false); 1966 insertLabel(label, true); 1967 } 1968 return 0; 1969 } 1970 //!generate native code to handle potential exception 1971 1972 //! 1973 int handlePotentialException( 1974 ConditionCode code_excep, ConditionCode code_okay, 1975 int exceptionNum, const char* errName) { 1976 char label[LABEL_SIZE]; 1977 1978 if(gDvm.executionMode == kExecutionModeNcgO1) { 1979 rememberState(exceptionNum); 1980 snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum); 1981 conditional_jump(code_okay, label, true); 1982 if(exceptionNum > 1) 1983 nextVersionOfHardReg(PhysicalReg_EDX, 2); //next version has 2 ref count 1984 export_pc(); //use %edx 1985 constVREndOfBB(); 1986 beforeCall("exception"); //dump GG, GL VRs 1987 if(!strcmp(errName, "common_throw_message")) { 1988 move_imm_to_reg(OpndSize_32, LstrInstantiationErrorPtr, PhysicalReg_ECX, true); 1989 } 1990 unconditional_jump_global_API(errName, false); 1991 insertLabel(label, true); 1992 goToState(exceptionNum); 1993 } else { 1994 snprintf(label, LABEL_SIZE, "after_exception_%d", exceptionNum); 1995 conditional_jump(code_okay, label, true); 1996 export_pc(); //use %edx 1997 if(!strcmp(errName, "common_throw_message")) { 1998 move_imm_to_reg(OpndSize_32, LstrInstantiationErrorPtr, PhysicalReg_ECX, true); 1999 } 2000 unconditional_jump_global_API(errName, false); 2001 insertLabel(label, true); 2002 } 2003 return 0; 2004 } 2005 //!generate native code to get the self pointer from glue 2006 2007 //!It uses one scratch register 2008 int get_self_pointer(int reg, bool isPhysical) { 2009 move_mem_to_reg(OpndSize_32, offEBP_self, PhysicalReg_EBP, true, reg, isPhysical); 2010 return 0; 2011 } 2012 //!generate native code to get ResStrings from glue 2013 2014 //!It uses two scratch registers 2015 int get_res_strings(int reg, bool isPhysical) { 2016 //if spill_loc_index > 0 || reg != NULL, use registerAlloc 2017 if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) { 2018 //if spill_loc_index > 0 2019 // load from spilled location, update spill_loc_index & physicalReg 2020 #if 0 2021 updateRefCount2(C_SCRATCH_1, LowOpndRegType_gp, isScratchPhysical); 2022 updateRefCount2(C_SCRATCH_1, LowOpndRegType_gp, isScratchPhysical); 2023 updateRefCount2(C_SCRATCH_2, LowOpndRegType_gp, isScratchPhysical); 2024 updateRefCount2(C_SCRATCH_2, LowOpndRegType_gp, isScratchPhysical); 2025 #endif 2026 startNativeCode(-1, -1); 2027 freeReg(true); 2028 int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/); 2029 donotSpillReg(regAll); 2030 dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResStrings, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp); 2031 endNativeCode(); 2032 } 2033 else 2034 { 2035 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2036 move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical); 2037 //glue is not in a physical reg nor in a spilled location 2038 updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg 2039 move_mem_to_reg(OpndSize_32, offDvmDex_pResStrings, C_SCRATCH_2, isScratchPhysical, reg, isPhysical); 2040 } 2041 return 0; 2042 } 2043 int get_res_classes(int reg, bool isPhysical) { 2044 //if spill_loc_index > 0 || reg != NULL, use registerAlloc 2045 if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) { 2046 //if spill_loc_index > 0 2047 // load from spilled location, updte spill_loc_index & physicalReg 2048 startNativeCode(-1, -1); 2049 freeReg(true); 2050 int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/); 2051 donotSpillReg(regAll); 2052 dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResClasses, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp); 2053 endNativeCode(); 2054 } 2055 else 2056 { 2057 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2058 move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical); 2059 //glue is not in a physical reg nor in a spilled location 2060 updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg 2061 move_mem_to_reg(OpndSize_32, offDvmDex_pResClasses, C_SCRATCH_2, isScratchPhysical, reg, isPhysical); 2062 } 2063 return 0; 2064 } 2065 //!generate native code to get ResFields from glue 2066 2067 //!It uses two scratch registers 2068 int get_res_fields(int reg, bool isPhysical) { 2069 //if spill_loc_index > 0 || reg != NULL, use registerAlloc 2070 if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) { 2071 //if spill_loc_index > 0 2072 // load from spilled location, updte spill_loc_index & physicalReg 2073 startNativeCode(-1, -1); 2074 freeReg(true); 2075 int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/); 2076 donotSpillReg(regAll); 2077 dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResFields, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp); 2078 endNativeCode(); 2079 } 2080 else 2081 { 2082 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2083 move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical); 2084 //glue is not in a physical reg nor in a spilled location 2085 updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg 2086 move_mem_to_reg(OpndSize_32, offDvmDex_pResFields, C_SCRATCH_2, isScratchPhysical, reg, isPhysical); 2087 } 2088 return 0; 2089 } 2090 //!generate native code to get ResMethods from glue 2091 2092 //!It uses two scratch registers 2093 int get_res_methods(int reg, bool isPhysical) { 2094 //if spill_loc_index > 0 || reg != NULL, use registerAlloc 2095 if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) { 2096 //if spill_loc_index > 0 2097 // load from spilled location, updte spill_loc_index & physicalReg 2098 startNativeCode(-1, -1); 2099 freeReg(true); 2100 int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/); 2101 donotSpillReg(regAll); 2102 dump_mem_reg_noalloc_mem(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, offDvmDex_pResMethods, regAll, true, MemoryAccess_Unknown, -1, reg, isPhysical, LowOpndRegType_gp); 2103 endNativeCode(); 2104 } 2105 else 2106 { 2107 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2108 move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical); 2109 //glue is not in a physical reg nor in a spilled location 2110 updateGlue(C_SCRATCH_2, isScratchPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg 2111 move_mem_to_reg(OpndSize_32, offDvmDex_pResMethods, C_SCRATCH_2, isScratchPhysical, reg, isPhysical); 2112 } 2113 return 0; 2114 } 2115 //!generate native code to get the current class object from glue 2116 2117 //!It uses two scratch registers 2118 int get_glue_method_class(int reg, bool isPhysical) { 2119 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2120 move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.method), C_SCRATCH_1, isScratchPhysical, C_SCRATCH_2, isScratchPhysical); 2121 move_mem_to_reg(OpndSize_32, offMethod_clazz, C_SCRATCH_2, isScratchPhysical, reg, isPhysical); 2122 return 0; 2123 } 2124 //!generate native code to get the current method from glue 2125 2126 //!It uses one scratch register 2127 int get_glue_method(int reg, bool isPhysical) { 2128 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2129 move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.method), C_SCRATCH_1, isScratchPhysical, reg, isPhysical); 2130 return 0; 2131 } 2132 //!generate native code to set the current method in glue 2133 2134 //!It uses one scratch register 2135 int set_glue_method(int reg, bool isPhysical) { 2136 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2137 move_reg_to_mem(OpndSize_32, reg, isPhysical, offsetof(Thread, interpSave.method), C_SCRATCH_1, isScratchPhysical); 2138 return 0; 2139 } 2140 2141 //!generate native code to get DvmDex from glue 2142 2143 //!It uses one scratch register 2144 int get_glue_dvmdex(int reg, bool isPhysical) { 2145 //if spill_loc_index > 0 || reg != NULL, use registerAlloc 2146 if(isGlueHandled(PhysicalReg_GLUE_DVMDEX)) { 2147 //if spill_loc_index > 0 2148 // load from spilled location, updte spill_loc_index & physicalReg 2149 startNativeCode(-1, -1); 2150 freeReg(true); 2151 int regAll = registerAlloc(LowOpndRegType_gp, PhysicalReg_GLUE_DVMDEX, false, false/*updateRefCount*/); 2152 donotSpillReg(regAll); 2153 dump_reg_reg_noalloc_src(Mnemonic_MOV, ATOM_NORMAL, OpndSize_32, regAll, true, 2154 reg, isPhysical, LowOpndRegType_gp); 2155 endNativeCode(); 2156 } 2157 else 2158 { 2159 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2160 move_mem_to_reg(OpndSize_32, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical, reg, isPhysical); 2161 //glue is not in a physical reg nor in a spilled location 2162 updateGlue(reg, isPhysical, PhysicalReg_GLUE_DVMDEX); //spill_loc_index is -1, set physicalReg 2163 } 2164 return 0; 2165 } 2166 //!generate native code to set DvmDex in glue 2167 2168 //!It uses one scratch register 2169 int set_glue_dvmdex(int reg, bool isPhysical) { 2170 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2171 move_reg_to_mem(OpndSize_32, reg, isPhysical, offsetof(Thread, interpSave.methodClassDex), C_SCRATCH_1, isScratchPhysical); 2172 return 0; 2173 } 2174 //!generate native code to get SuspendCount from glue 2175 2176 //!It uses one scratch register 2177 int get_suspendCount(int reg, bool isPhysical) { 2178 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2179 move_mem_to_reg(OpndSize_32, offsetof(Thread, suspendCount), C_SCRATCH_1, isScratchPhysical, reg, isPhysical); 2180 return 0; 2181 } 2182 2183 //!generate native code to get retval from glue 2184 2185 //!It uses one scratch register 2186 int get_return_value(OpndSize size, int reg, bool isPhysical) { 2187 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2188 move_mem_to_reg(size, offsetof(Thread, interpSave.retval), C_SCRATCH_1, isScratchPhysical, reg, isPhysical); 2189 return 0; 2190 } 2191 //!generate native code to set retval in glue 2192 2193 //!It uses one scratch register 2194 int set_return_value(OpndSize size, int reg, bool isPhysical) { 2195 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2196 move_reg_to_mem(size, reg, isPhysical, offsetof(Thread, interpSave.retval), C_SCRATCH_1, isScratchPhysical); 2197 return 0; 2198 } 2199 //!generate native code to clear exception object in glue 2200 2201 //!It uses two scratch registers 2202 int clear_exception() { 2203 get_self_pointer(C_SCRATCH_2, isScratchPhysical); 2204 move_imm_to_mem(OpndSize_32, 0, offsetof(Thread, exception), C_SCRATCH_2, isScratchPhysical); 2205 return 0; 2206 } 2207 //!generate native code to get exception object in glue 2208 2209 //!It uses two scratch registers 2210 int get_exception(int reg, bool isPhysical) { 2211 get_self_pointer(C_SCRATCH_2, isScratchPhysical); 2212 move_mem_to_reg(OpndSize_32, offsetof(Thread, exception), C_SCRATCH_2, isScratchPhysical, reg, isPhysical); 2213 return 0; 2214 } 2215 //!generate native code to set exception object in glue 2216 2217 //!It uses two scratch registers 2218 int set_exception(int reg, bool isPhysical) { 2219 get_self_pointer(C_SCRATCH_2, isScratchPhysical); 2220 move_reg_to_mem(OpndSize_32, reg, isPhysical, offsetof(Thread, exception), C_SCRATCH_2, isScratchPhysical); 2221 return 0; 2222 } 2223 //!generate native code to save frame pointer and current PC in stack frame to glue 2224 2225 //!It uses two scratch registers 2226 int save_pc_fp_to_glue() { 2227 get_self_pointer(C_SCRATCH_1, isScratchPhysical); 2228 move_reg_to_mem(OpndSize_32, PhysicalReg_FP, true, offsetof(Thread, interpSave.curFrame), C_SCRATCH_1, isScratchPhysical); 2229 2230 //from stack-save currentPc 2231 move_mem_to_reg(OpndSize_32, -sizeofStackSaveArea+offStackSaveArea_localRefTop, PhysicalReg_FP, true, C_SCRATCH_2, isScratchPhysical); 2232 move_reg_to_mem(OpndSize_32, C_SCRATCH_2, isScratchPhysical, offsetof(Thread, interpSave.pc), C_SCRATCH_1, isScratchPhysical); 2233 return 0; 2234 } 2235 //! get SaveArea pointer 2236 2237 //! 2238 int savearea_from_fp(int reg, bool isPhysical) { 2239 load_effective_addr(-sizeofStackSaveArea, PhysicalReg_FP, true, reg, isPhysical); 2240 return 0; 2241 } 2242 2243 #ifdef DEBUG_CALL_STACK3 2244 int call_debug_dumpSwitch() { 2245 typedef void (*vmHelper)(int); 2246 vmHelper funcPtr = debug_dumpSwitch; 2247 callFuncPtr((int)funcPtr, "debug_dumpSwitch"); 2248 return 0; 2249 } 2250 #endif 2251 2252 int call_dvmQuasiAtomicSwap64() { 2253 typedef int64_t (*vmHelper)(int64_t, volatile int64_t*); 2254 vmHelper funcPtr = dvmQuasiAtomicSwap64; 2255 if(gDvm.executionMode == kExecutionModeNcgO1) { 2256 beforeCall("dvmQuasiAtomicSwap64"); 2257 callFuncPtr((int)funcPtr, "dvmQuasiAtomicSwap64"); 2258 afterCall("dvmQuasiAtomicSwap64"); 2259 } else { 2260 callFuncPtr((int)funcPtr, "dvmQuasiAtomicSwap64"); 2261 } 2262 return 0; 2263 } 2264 2265 int call_dvmQuasiAtomicRead64() { 2266 typedef int64_t (*vmHelper)(volatile const int64_t*); 2267 vmHelper funcPtr = dvmQuasiAtomicRead64; 2268 if(gDvm.executionMode == kExecutionModeNcgO1) { 2269 beforeCall("dvmQuasiAtomiRead64"); 2270 callFuncPtr((int)funcPtr, "dvmQuasiAtomicRead64"); 2271 afterCall("dvmQuasiAtomicRead64"); 2272 touchEax(); //for return value 2273 touchEdx(); 2274 } else { 2275 callFuncPtr((int)funcPtr, "dvmQuasiAtomicRead64"); 2276 } 2277 return 0; 2278 } 2279 2280 int call_dvmJitToInterpPunt() { 2281 typedef void (*vmHelper)(int); 2282 vmHelper funcPtr = dvmJitToInterpPunt; 2283 callFuncPtr((int)funcPtr, "dvmJitToInterpPunt"); 2284 return 0; 2285 } 2286 2287 int call_dvmJitToInterpNormal() { 2288 typedef void (*vmHelper)(int); 2289 vmHelper funcPtr = dvmJitToInterpNormal; 2290 if(gDvm.executionMode == kExecutionModeNcgO1) { 2291 beforeCall("dvmJitToInterpNormal"); 2292 callFuncPtr((int)funcPtr, "dvmJitToInterpNormal"); 2293 afterCall("dvmJitToInterpNormal"); 2294 touchEbx(); 2295 } else { 2296 callFuncPtr((int)funcPtr, "dvmJitToInterpNormal"); 2297 } 2298 return 0; 2299 } 2300 2301 int call_dvmJitToInterpTraceSelectNoChain() { 2302 typedef void (*vmHelper)(int); 2303 vmHelper funcPtr = dvmJitToInterpTraceSelectNoChain; 2304 if(gDvm.executionMode == kExecutionModeNcgO1) { 2305 beforeCall("dvmJitToInterpTraceSelectNoChain"); 2306 callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelectNoChain"); 2307 afterCall("dvmJitToInterpTraceSelectNoChain"); 2308 touchEbx(); 2309 } else { 2310 callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelectNoChain"); 2311 } 2312 return 0; 2313 } 2314 2315 int call_dvmJitToInterpTraceSelect() { 2316 typedef void (*vmHelper)(int); 2317 vmHelper funcPtr = dvmJitToInterpTraceSelect; 2318 if(gDvm.executionMode == kExecutionModeNcgO1) { 2319 beforeCall("dvmJitToInterpTraceSelect"); 2320 callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelect"); 2321 afterCall("dvmJitToInterpTraceSelect"); 2322 touchEbx(); 2323 } else { 2324 callFuncPtr((int)funcPtr, "dvmJitToInterpTraceSelect"); 2325 } 2326 return 0; 2327 } 2328 2329 int call_dvmJitToPatchPredictedChain() { 2330 typedef const Method * (*vmHelper)(const Method *method, 2331 Thread *self, 2332 PredictedChainingCell *cell, 2333 const ClassObject *clazz); 2334 vmHelper funcPtr = dvmJitToPatchPredictedChain; 2335 if(gDvm.executionMode == kExecutionModeNcgO1) { 2336 beforeCall("dvmJitToPatchPredictedChain"); 2337 callFuncPtr((int)funcPtr, "dvmJitToPatchPredictedChain"); 2338 afterCall("dvmJitToPatchPredictedChain"); 2339 } else { 2340 callFuncPtr((int)funcPtr, "dvmJitToPatchPredictedChain"); 2341 } 2342 return 0; 2343 } 2344 2345 //!generate native code to call __moddi3 2346 2347 //! 2348 int call_moddi3() { 2349 if(gDvm.executionMode == kExecutionModeNcgO1) { 2350 beforeCall("moddi3"); 2351 callFuncPtr((intptr_t)__moddi3, "__moddi3"); 2352 afterCall("moddi3"); 2353 } else { 2354 callFuncPtr((intptr_t)__moddi3, "__moddi3"); 2355 } 2356 return 0; 2357 } 2358 //!generate native code to call __divdi3 2359 2360 //! 2361 int call_divdi3() { 2362 if(gDvm.executionMode == kExecutionModeNcgO1) { 2363 beforeCall("divdi3"); 2364 callFuncPtr((intptr_t)__divdi3, "__divdi3"); 2365 afterCall("divdi3"); 2366 } else { 2367 callFuncPtr((intptr_t)__divdi3, "__divdi3"); 2368 } 2369 return 0; 2370 } 2371 2372 //!generate native code to call fmod 2373 2374 //! 2375 int call_fmod() { 2376 typedef double (*libHelper)(double, double); 2377 libHelper funcPtr = fmod; 2378 if(gDvm.executionMode == kExecutionModeNcgO1) { 2379 beforeCall("fmod"); 2380 callFuncPtr((int)funcPtr, "fmod"); 2381 afterCall("fmod"); 2382 } else { 2383 callFuncPtr((int)funcPtr, "fmod"); 2384 } 2385 return 0; 2386 } 2387 //!generate native code to call fmodf 2388 2389 //! 2390 int call_fmodf() { 2391 typedef float (*libHelper)(float, float); 2392 libHelper funcPtr = fmodf; 2393 if(gDvm.executionMode == kExecutionModeNcgO1) { 2394 beforeCall("fmodf"); 2395 callFuncPtr((int)funcPtr, "fmodf"); 2396 afterCall("fmodf"); 2397 } else { 2398 callFuncPtr((int)funcPtr, "fmodf"); 2399 } 2400 return 0; 2401 } 2402 //!generate native code to call dvmFindCatchBlock 2403 2404 //! 2405 int call_dvmFindCatchBlock() { 2406 //int dvmFindCatchBlock(Thread* self, int relPc, Object* exception, 2407 //bool doUnroll, void** newFrame) 2408 typedef int (*vmHelper)(Thread*, int, Object*, bool, void**); 2409 vmHelper funcPtr = dvmFindCatchBlock; 2410 if(gDvm.executionMode == kExecutionModeNcgO1) { 2411 beforeCall("dvmFindCatchBlock"); 2412 callFuncPtr((int)funcPtr, "dvmFindCatchBlock"); 2413 afterCall("dvmFindCatchBlock"); 2414 } else { 2415 callFuncPtr((int)funcPtr, "dvmFindCatchBlock"); 2416 } 2417 return 0; 2418 } 2419 //!generate native code to call dvmThrowVerificationError 2420 2421 //! 2422 int call_dvmThrowVerificationError() { 2423 typedef void (*vmHelper)(const Method*, int, int); 2424 vmHelper funcPtr = dvmThrowVerificationError; 2425 if(gDvm.executionMode == kExecutionModeNcgO1) { 2426 beforeCall("dvmThrowVerificationError"); 2427 callFuncPtr((int)funcPtr, "dvmThrowVerificationError"); 2428 afterCall("dvmThrowVerificationError"); 2429 } else { 2430 callFuncPtr((int)funcPtr, "dvmThrowVerificationError"); 2431 } 2432 return 0; 2433 } 2434 2435 //!generate native code to call dvmResolveMethod 2436 2437 //! 2438 int call_dvmResolveMethod() { 2439 //Method* dvmResolveMethod(const ClassObject* referrer, u4 methodIdx, MethodType methodType); 2440 typedef Method* (*vmHelper)(const ClassObject*, u4, MethodType); 2441 vmHelper funcPtr = dvmResolveMethod; 2442 if(gDvm.executionMode == kExecutionModeNcgO1) { 2443 beforeCall("dvmResolveMethod"); 2444 callFuncPtr((int)funcPtr, "dvmResolveMethod"); 2445 afterCall("dvmResolveMethod"); 2446 } else { 2447 callFuncPtr((int)funcPtr, "dvmResolveMethod"); 2448 } 2449 return 0; 2450 } 2451 //!generate native code to call dvmResolveClass 2452 2453 //! 2454 int call_dvmResolveClass() { 2455 //ClassObject* dvmResolveClass(const ClassObject* referrer, u4 classIdx, bool fromUnverifiedConstant) 2456 typedef ClassObject* (*vmHelper)(const ClassObject*, u4, bool); 2457 vmHelper funcPtr = dvmResolveClass; 2458 if(gDvm.executionMode == kExecutionModeNcgO1) { 2459 beforeCall("dvmResolveClass"); 2460 callFuncPtr((int)funcPtr, "dvmResolveClass"); 2461 afterCall("dvmResolveClass"); 2462 } else { 2463 callFuncPtr((int)funcPtr, "dvmResolveClass"); 2464 } 2465 return 0; 2466 } 2467 2468 //!generate native code to call dvmInstanceofNonTrivial 2469 2470 //! 2471 int call_dvmInstanceofNonTrivial() { 2472 typedef int (*vmHelper)(const ClassObject*, const ClassObject*); 2473 vmHelper funcPtr = dvmInstanceofNonTrivial; 2474 if(gDvm.executionMode == kExecutionModeNcgO1) { 2475 beforeCall("dvmInstanceofNonTrivial"); 2476 callFuncPtr((int)funcPtr, "dvmInstanceofNonTrivial"); 2477 afterCall("dvmInstanceofNonTrivial"); 2478 } else { 2479 callFuncPtr((int)funcPtr, "dvmInstanceofNonTrivial"); 2480 } 2481 return 0; 2482 } 2483 //!generate native code to call dvmThrowException 2484 2485 //! 2486 int call_dvmThrow() { 2487 typedef void (*vmHelper)(ClassObject* exceptionClass, const char*); 2488 vmHelper funcPtr = dvmThrowException; 2489 if(gDvm.executionMode == kExecutionModeNcgO1) { 2490 beforeCall("dvmThrowException"); 2491 callFuncPtr((int)funcPtr, "dvmThrowException"); 2492 afterCall("dvmThrowException"); 2493 } else { 2494 callFuncPtr((int)funcPtr, "dvmThrowException"); 2495 } 2496 return 0; 2497 } 2498 //!generate native code to call dvmThrowExceptionWithClassMessage 2499 2500 //! 2501 int call_dvmThrowWithMessage() { 2502 typedef void (*vmHelper)(ClassObject* exceptionClass, const char*); 2503 vmHelper funcPtr = dvmThrowExceptionWithClassMessage; 2504 if(gDvm.executionMode == kExecutionModeNcgO1) { 2505 beforeCall("dvmThrowExceptionWithClassMessage"); 2506 callFuncPtr((int)funcPtr, "dvmThrowExceptionWithClassMessage"); 2507 afterCall("dvmThrowExceptionWithClassMessage"); 2508 } else { 2509 callFuncPtr((int)funcPtr, "dvmThrowExceptionWithClassMessage"); 2510 } 2511 return 0; 2512 } 2513 //!generate native code to call dvmCheckSuspendPending 2514 2515 //! 2516 int call_dvmCheckSuspendPending() { 2517 typedef bool (*vmHelper)(Thread*); 2518 vmHelper funcPtr = dvmCheckSuspendPending; 2519 if(gDvm.executionMode == kExecutionModeNcgO1) { 2520 beforeCall("dvmCheckSuspendPending"); 2521 callFuncPtr((int)funcPtr, "dvmCheckSuspendPending"); 2522 afterCall("dvmCheckSuspendPending"); 2523 } else { 2524 callFuncPtr((int)funcPtr, "dvmCheckSuspendPending"); 2525 } 2526 return 0; 2527 } 2528 //!generate native code to call dvmLockObject 2529 2530 //! 2531 int call_dvmLockObject() { 2532 typedef void (*vmHelper)(struct Thread*, struct Object*); 2533 vmHelper funcPtr = dvmLockObject; 2534 if(gDvm.executionMode == kExecutionModeNcgO1) { 2535 beforeCall("dvmLockObject"); 2536 callFuncPtr((int)funcPtr, "dvmLockObject"); 2537 afterCall("dvmLockObject"); 2538 } else { 2539 callFuncPtr((int)funcPtr, "dvmLockObject"); 2540 } 2541 return 0; 2542 } 2543 //!generate native code to call dvmUnlockObject 2544 2545 //! 2546 int call_dvmUnlockObject() { 2547 typedef bool (*vmHelper)(Thread*, Object*); 2548 vmHelper funcPtr = dvmUnlockObject; 2549 if(gDvm.executionMode == kExecutionModeNcgO1) { 2550 beforeCall("dvmUnlockObject"); 2551 callFuncPtr((int)funcPtr, "dvmUnlockObject"); 2552 afterCall("dvmUnlockObject"); 2553 } else { 2554 callFuncPtr((int)funcPtr, "dvmUnlockObject"); 2555 } 2556 return 0; 2557 } 2558 //!generate native code to call dvmInitClass 2559 2560 //! 2561 int call_dvmInitClass() { 2562 typedef bool (*vmHelper)(ClassObject*); 2563 vmHelper funcPtr = dvmInitClass; 2564 if(gDvm.executionMode == kExecutionModeNcgO1) { 2565 beforeCall("dvmInitClass"); 2566 callFuncPtr((int)funcPtr, "dvmInitClass"); 2567 afterCall("dvmInitClass"); 2568 } else { 2569 callFuncPtr((int)funcPtr, "dvmInitClass"); 2570 } 2571 return 0; 2572 } 2573 //!generate native code to call dvmAllocObject 2574 2575 //! 2576 int call_dvmAllocObject() { 2577 typedef Object* (*vmHelper)(ClassObject*, int); 2578 vmHelper funcPtr = dvmAllocObject; 2579 if(gDvm.executionMode == kExecutionModeNcgO1) { 2580 beforeCall("dvmAllocObject"); 2581 callFuncPtr((int)funcPtr, "dvmAllocObject"); 2582 afterCall("dvmAllocObject"); 2583 } else { 2584 callFuncPtr((int)funcPtr, "dvmAllocObject"); 2585 } 2586 return 0; 2587 } 2588 //!generate native code to call dvmAllocArrayByClass 2589 2590 //! 2591 int call_dvmAllocArrayByClass() { 2592 typedef ArrayObject* (*vmHelper)(ClassObject*, size_t, int); 2593 vmHelper funcPtr = dvmAllocArrayByClass; 2594 if(gDvm.executionMode == kExecutionModeNcgO1) { 2595 beforeCall("dvmAllocArrayByClass"); 2596 callFuncPtr((int)funcPtr, "dvmAllocArrayByClass"); 2597 afterCall("dvmAllocArrayByClass"); 2598 } else { 2599 callFuncPtr((int)funcPtr, "dvmAllocArrayByClass"); 2600 } 2601 return 0; 2602 } 2603 //!generate native code to call dvmAllocPrimitiveArray 2604 2605 //! 2606 int call_dvmAllocPrimitiveArray() { 2607 typedef ArrayObject* (*vmHelper)(char, size_t, int); 2608 vmHelper funcPtr = dvmAllocPrimitiveArray; 2609 if(gDvm.executionMode == kExecutionModeNcgO1) { 2610 beforeCall("dvmAllocPrimitiveArray"); 2611 callFuncPtr((int)funcPtr, "dvmAllocPrimitiveArray"); 2612 afterCall("dvmAllocPrimitiveArray"); 2613 } else { 2614 callFuncPtr((int)funcPtr, "dvmAllocPrimitiveArray"); 2615 } 2616 return 0; 2617 } 2618 //!generate native code to call dvmInterpHandleFillArrayData 2619 2620 //! 2621 int call_dvmInterpHandleFillArrayData() { 2622 typedef bool (*vmHelper)(ArrayObject*, const u2*); 2623 vmHelper funcPtr = dvmInterpHandleFillArrayData; 2624 if(gDvm.executionMode == kExecutionModeNcgO1) { 2625 beforeCall("dvmInterpHandleFillArrayData"); //before move_imm_to_reg to avoid spilling C_SCRATCH_1 2626 callFuncPtr((int)funcPtr, "dvmInterpHandleFillArrayData"); 2627 afterCall("dvmInterpHandleFillArrayData"); 2628 } else { 2629 callFuncPtr((int)funcPtr, "dvmInterpHandleFillArrayData"); 2630 } 2631 return 0; 2632 } 2633 2634 //!generate native code to call dvmNcgHandlePackedSwitch 2635 2636 //! 2637 int call_dvmNcgHandlePackedSwitch() { 2638 typedef s4 (*vmHelper)(const s4*, s4, u2, s4); 2639 vmHelper funcPtr = dvmNcgHandlePackedSwitch; 2640 if(gDvm.executionMode == kExecutionModeNcgO1) { 2641 beforeCall("dvmNcgHandlePackedSwitch"); 2642 callFuncPtr((int)funcPtr, "dvmNcgHandlePackedSwitch"); 2643 afterCall("dvmNcgHandlePackedSwitch"); 2644 } else { 2645 callFuncPtr((int)funcPtr, "dvmNcgHandlePackedSwitch"); 2646 } 2647 return 0; 2648 } 2649 2650 int call_dvmJitHandlePackedSwitch() { 2651 typedef s4 (*vmHelper)(const s4*, s4, u2, s4); 2652 vmHelper funcPtr = dvmJitHandlePackedSwitch; 2653 if(gDvm.executionMode == kExecutionModeNcgO1) { 2654 beforeCall("dvmJitHandlePackedSwitch"); 2655 callFuncPtr((int)funcPtr, "dvmJitHandlePackedSwitch"); 2656 afterCall("dvmJitHandlePackedSwitch"); 2657 } else { 2658 callFuncPtr((int)funcPtr, "dvmJitHandlePackedSwitch"); 2659 } 2660 return 0; 2661 } 2662 2663 //!generate native code to call dvmNcgHandleSparseSwitch 2664 2665 //! 2666 int call_dvmNcgHandleSparseSwitch() { 2667 typedef s4 (*vmHelper)(const s4*, u2, s4); 2668 vmHelper funcPtr = dvmNcgHandleSparseSwitch; 2669 if(gDvm.executionMode == kExecutionModeNcgO1) { 2670 beforeCall("dvmNcgHandleSparseSwitch"); 2671 callFuncPtr((int)funcPtr, "dvmNcgHandleSparseSwitch"); 2672 afterCall("dvmNcgHandleSparseSwitch"); 2673 } else { 2674 callFuncPtr((int)funcPtr, "dvmNcgHandleSparseSwitch"); 2675 } 2676 return 0; 2677 } 2678 2679 int call_dvmJitHandleSparseSwitch() { 2680 typedef s4 (*vmHelper)(const s4*, u2, s4); 2681 vmHelper funcPtr = dvmJitHandleSparseSwitch; 2682 if(gDvm.executionMode == kExecutionModeNcgO1) { 2683 beforeCall("dvmJitHandleSparseSwitch"); 2684 callFuncPtr((int)funcPtr, "dvmJitHandleSparseSwitch"); 2685 afterCall("dvmJitHandleSparseSwitch"); 2686 } else { 2687 callFuncPtr((int)funcPtr, "dvmJitHandleSparseSwitch"); 2688 } 2689 return 0; 2690 } 2691 2692 //!generate native code to call dvmCanPutArrayElement 2693 2694 //! 2695 int call_dvmCanPutArrayElement() { 2696 typedef bool (*vmHelper)(const ClassObject*, const ClassObject*); 2697 vmHelper funcPtr = dvmCanPutArrayElement; 2698 if(gDvm.executionMode == kExecutionModeNcgO1) { 2699 beforeCall("dvmCanPutArrayElement"); 2700 callFuncPtr((int)funcPtr, "dvmCanPutArrayElement"); 2701 afterCall("dvmCanPutArrayElement"); 2702 } else { 2703 callFuncPtr((int)funcPtr, "dvmCanPutArrayElement"); 2704 } 2705 return 0; 2706 } 2707 2708 //!generate native code to call dvmFindInterfaceMethodInCache2 2709 2710 //! 2711 int call_dvmFindInterfaceMethodInCache() { 2712 typedef Method* (*vmHelper)(ClassObject*, u4, const Method*, DvmDex*); 2713 vmHelper funcPtr = dvmFindInterfaceMethodInCache2; 2714 if(gDvm.executionMode == kExecutionModeNcgO1) { 2715 beforeCall("dvmFindInterfaceMethodInCache2"); 2716 callFuncPtr((int)funcPtr, "dvmFindInterfaceMethodInCache2"); 2717 afterCall("dvmFindInterfaceMethodInCache2"); 2718 } else { 2719 callFuncPtr((int)funcPtr, "dvmFindInterfaceMethodInCache2"); 2720 } 2721 return 0; 2722 } 2723 2724 //!generate native code to call dvmHandleStackOverflow 2725 2726 //! 2727 int call_dvmHandleStackOverflow() { 2728 typedef void (*vmHelper)(Thread*, const Method*); 2729 vmHelper funcPtr = dvmHandleStackOverflow; 2730 if(gDvm.executionMode == kExecutionModeNcgO1) { 2731 beforeCall("dvmHandleStackOverflow"); 2732 callFuncPtr((int)funcPtr, "dvmHandleStackOverflow"); 2733 afterCall("dvmHandleStackOverflow"); 2734 } else { 2735 callFuncPtr((int)funcPtr, "dvmHandleStackOverflow"); 2736 } 2737 return 0; 2738 } 2739 //!generate native code to call dvmResolveString 2740 2741 //! 2742 int call_dvmResolveString() { 2743 //StringObject* dvmResolveString(const ClassObject* referrer, u4 stringIdx) 2744 typedef StringObject* (*vmHelper)(const ClassObject*, u4); 2745 vmHelper funcPtr = dvmResolveString; 2746 if(gDvm.executionMode == kExecutionModeNcgO1) { 2747 beforeCall("dvmResolveString"); 2748 callFuncPtr((int)funcPtr, "dvmResolveString"); 2749 afterCall("dvmResolveString"); 2750 } else { 2751 callFuncPtr((int)funcPtr, "dvmResolveString"); 2752 } 2753 return 0; 2754 } 2755 //!generate native code to call dvmResolveInstField 2756 2757 //! 2758 int call_dvmResolveInstField() { 2759 //InstField* dvmResolveInstField(const ClassObject* referrer, u4 ifieldIdx) 2760 typedef InstField* (*vmHelper)(const ClassObject*, u4); 2761 vmHelper funcPtr = dvmResolveInstField; 2762 if(gDvm.executionMode == kExecutionModeNcgO1) { 2763 beforeCall("dvmResolveInstField"); 2764 callFuncPtr((int)funcPtr, "dvmResolveInstField"); 2765 afterCall("dvmResolveInstField"); 2766 } else { 2767 callFuncPtr((int)funcPtr, "dvmResolveInstField"); 2768 } 2769 return 0; 2770 } 2771 //!generate native code to call dvmResolveStaticField 2772 2773 //! 2774 int call_dvmResolveStaticField() { 2775 //StaticField* dvmResolveStaticField(const ClassObject* referrer, u4 sfieldIdx) 2776 typedef StaticField* (*vmHelper)(const ClassObject*, u4); 2777 vmHelper funcPtr = dvmResolveStaticField; 2778 if(gDvm.executionMode == kExecutionModeNcgO1) { 2779 beforeCall("dvmResolveStaticField"); 2780 callFuncPtr((int)funcPtr, "dvmResolveStaticField"); 2781 afterCall("dvmResolveStaticField"); 2782 } else { 2783 callFuncPtr((int)funcPtr, "dvmResolveStaticField"); 2784 } 2785 return 0; 2786 } 2787 2788 #define P_GPR_2 PhysicalReg_ECX 2789 /*! 2790 \brief This function is used to resolve a string reference 2791 2792 INPUT: const pool index in %eax 2793 2794 OUTPUT: resolved string in %eax 2795 2796 The registers are hard-coded, 2 physical registers %esi and %edx are used as scratch registers; 2797 It calls a C function dvmResolveString; 2798 The only register that is still live after this function is ebx 2799 */ 2800 int const_string_resolve() { 2801 scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX; 2802 scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 2803 insertLabel(".const_string_resolve", false); 2804 //method stored in glue structure as well as on the interpreted stack 2805 get_glue_method_class(P_GPR_2, true); 2806 load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2807 move_reg_to_mem(OpndSize_32, PhysicalReg_EAX, true, 4, PhysicalReg_ESP, true); 2808 move_reg_to_mem(OpndSize_32, P_GPR_2, true, 0, PhysicalReg_ESP, true); 2809 call_dvmResolveString(); 2810 load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2811 compare_imm_reg( OpndSize_32, 0, PhysicalReg_EAX, true); 2812 conditional_jump(Condition_E, "common_exceptionThrown", false); 2813 x86_return(); 2814 return 0; 2815 } 2816 #undef P_GPR_2 2817 /*! 2818 \brief This function is used to resolve a class 2819 2820 INPUT: const pool index in argument "indexReg" (%eax) 2821 2822 OUTPUT: resolved class in %eax 2823 2824 The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers. 2825 It calls a C function dvmResolveClass; 2826 The only register that is still live after this function is ebx 2827 */ 2828 int resolve_class2( 2829 int startLR/*scratch register*/, bool isPhysical, int indexReg/*const pool index*/, 2830 bool indexPhysical, int thirdArg) { 2831 insertLabel(".class_resolve", false); 2832 scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX; 2833 scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 2834 2835 //push index to stack first, to free indexReg 2836 load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2837 move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true); 2838 get_glue_method_class(startLR, isPhysical); 2839 move_imm_to_mem(OpndSize_32, thirdArg, 8, PhysicalReg_ESP, true); 2840 move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true); 2841 call_dvmResolveClass(); 2842 load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2843 compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 2844 conditional_jump(Condition_E, "common_exceptionThrown", false); 2845 2846 x86_return(); 2847 return 0; 2848 } 2849 /*! 2850 \brief This function is used to resolve a method, and it is called once with %eax for both indexReg and startLR 2851 2852 INPUT: const pool index in argument "indexReg" (%eax) 2853 2854 OUTPUT: resolved method in %eax 2855 2856 The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers. 2857 It calls a C function dvmResolveMethod; 2858 The only register that is still live after this function is ebx 2859 */ 2860 int resolve_method2( 2861 int startLR/*logical register index*/, bool isPhysical, int indexReg/*const pool index*/, 2862 bool indexPhysical, 2863 int thirdArg/*VIRTUAL*/) { 2864 if(thirdArg == METHOD_VIRTUAL) 2865 insertLabel(".virtual_method_resolve", false); 2866 else if(thirdArg == METHOD_DIRECT) 2867 insertLabel(".direct_method_resolve", false); 2868 else if(thirdArg == METHOD_STATIC) 2869 insertLabel(".static_method_resolve", false); 2870 2871 load_effective_addr(-12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2872 move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true); 2873 2874 scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX; 2875 scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 2876 get_glue_method_class(startLR, isPhysical); 2877 2878 move_imm_to_mem(OpndSize_32, thirdArg, 8, PhysicalReg_ESP, true); 2879 move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true); 2880 call_dvmResolveMethod(); 2881 load_effective_addr(12, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2882 compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 2883 conditional_jump(Condition_E, "common_exceptionThrown", false); 2884 2885 x86_return(); 2886 return 0; 2887 } 2888 /*! 2889 \brief This function is used to resolve an instance field 2890 2891 INPUT: const pool index in argument "indexReg" (%eax) 2892 2893 OUTPUT: resolved field in %eax 2894 2895 The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers. 2896 It calls a C function dvmResolveInstField; 2897 The only register that is still live after this function is ebx 2898 */ 2899 int resolve_inst_field2( 2900 int startLR/*logical register index*/, bool isPhysical, 2901 int indexReg/*const pool index*/, bool indexPhysical) { 2902 insertLabel(".inst_field_resolve", false); 2903 scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX; 2904 scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 2905 2906 load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2907 move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true); 2908 //method stored in glue structure as well as interpreted stack 2909 get_glue_method_class(startLR, isPhysical); 2910 move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true); 2911 call_dvmResolveInstField(); 2912 load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2913 compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 2914 conditional_jump(Condition_E, "common_exceptionThrown", false); 2915 2916 x86_return(); 2917 return 0; 2918 } 2919 /*! 2920 \brief This function is used to resolve a static field 2921 2922 INPUT: const pool index in argument "indexReg" (%eax) 2923 2924 OUTPUT: resolved field in %eax 2925 2926 The registers are hard-coded, 3 physical registers (%esi, %edx, startLR:%eax) are used as scratch registers. 2927 It calls a C function dvmResolveStaticField; 2928 The only register that is still live after this function is ebx 2929 */ 2930 int resolve_static_field2( 2931 int startLR/*logical register index*/, bool isPhysical, int indexReg/*const pool index*/, 2932 bool indexPhysical) { 2933 insertLabel(".static_field_resolve", false); 2934 scratchRegs[0] = PhysicalReg_ESI; scratchRegs[1] = PhysicalReg_EDX; 2935 scratchRegs[2] = PhysicalReg_Null; scratchRegs[3] = PhysicalReg_Null; 2936 2937 load_effective_addr(-8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2938 move_reg_to_mem(OpndSize_32, indexReg, indexPhysical, 4, PhysicalReg_ESP, true); 2939 get_glue_method_class(startLR, isPhysical); 2940 move_reg_to_mem(OpndSize_32, startLR, isPhysical, 0, PhysicalReg_ESP, true); 2941 call_dvmResolveStaticField(); 2942 load_effective_addr(8, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2943 compare_imm_reg(OpndSize_32, 0, PhysicalReg_EAX, true); 2944 conditional_jump(Condition_E, "common_exceptionThrown", false); 2945 2946 x86_return(); 2947 return 0; 2948 } 2949 2950 int pushAllRegs() { 2951 load_effective_addr(-28, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2952 move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EAX, true, 24, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1); 2953 move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EBX, true, 20, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1); 2954 move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_ECX, true, 16, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1); 2955 move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EDX, true, 12, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1); 2956 move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_ESI, true, 8, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1); 2957 move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EDI, true, 4, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1); 2958 move_reg_to_mem_noalloc(OpndSize_32, PhysicalReg_EBP, true, 0, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1); 2959 return 0; 2960 } 2961 int popAllRegs() { 2962 move_mem_to_reg_noalloc(OpndSize_32, 24, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EAX, true); 2963 move_mem_to_reg_noalloc(OpndSize_32, 20, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EBX, true); 2964 move_mem_to_reg_noalloc(OpndSize_32, 16, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_ECX, true); 2965 move_mem_to_reg_noalloc(OpndSize_32, 12, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EDX, true); 2966 move_mem_to_reg_noalloc(OpndSize_32, 8, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_ESI, true); 2967 move_mem_to_reg_noalloc(OpndSize_32, 4, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EDI, true); 2968 move_mem_to_reg_noalloc(OpndSize_32, 0, PhysicalReg_ESP, true, MemoryAccess_Unknown, -1, PhysicalReg_EBP, true); 2969 load_effective_addr(28, PhysicalReg_ESP, true, PhysicalReg_ESP, true); 2970 return 0; 2971 } 2972 2973 void dump_nop(int size) { 2974 switch(size) { 2975 case 1: 2976 *stream = 0x90; 2977 break; 2978 case 2: 2979 *stream = 0x66; 2980 *(stream +1) = 0x90; 2981 break; 2982 case 3: 2983 *stream = 0x0f; 2984 *(stream + 1) = 0x1f; 2985 *(stream + 2) = 0x00; 2986 break; 2987 default: 2988 //TODO: add more cases. 2989 break; 2990 } 2991 stream += size; 2992 } 2993