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