📄 jitemitter_cpu.c
字号:
CVMCPUemitBinaryALUConstant(con, CVMCPU_SUB_OPCODE, destRegID, srcRegID, 0, CVMJIT_SETCC); CVMCPUemitLoadConstantConditional(con, destRegID, 1, CVMCPU_COND_NE); break; case CVMCPU_NEG_OPCODE: CVMCPUemitBinaryALUConditional(con, ARM_RSB_OPCODE, destRegID, srcRegID, CVMCPUALURhsTokenConstZero, setcc, condCode); break; default: CVMassert(CVM_FALSE); }}/* Purpose: Emits instructions to do the specified conditional 32 bit ALU operation. */voidCVMCPUemitBinaryALUConditional(CVMJITCompilationContext* con, int opcode, int destRegID, int lhsRegID, CVMCPUALURhsToken rhsToken, CVMBool setcc, CVMCPUCondCode condCode){ CVMassert(opcode == CVMCPU_ADD_OPCODE || opcode == ARM_ADC_OPCODE || opcode == CVMCPU_SUB_OPCODE || opcode == ARM_SBC_OPCODE || opcode == ARM_RSB_OPCODE || opcode == ARM_RSC_OPCODE || opcode == CVMCPU_AND_OPCODE || opcode == CVMCPU_OR_OPCODE || opcode == CVMCPU_XOR_OPCODE || opcode == CVMCPU_BIC_OPCODE); CVMJITcsSetDestRegister(con, destRegID); CVMJITcsPushSourceRegister(con, lhsRegID); CVMJITcsSetCompareInstruction(con, setcc); CVMJITcsSetStatusBinaryALUInstruction(con, opcode); CVMJITcsSetStatusInstruction(con, condCode); emitInstruction(con, ARM_MAKE_CONDCODE_BITS(condCode) | (CVMUint32)opcode | (setcc ? (1 << 20) : 0) | lhsRegID << 16 | destRegID << 12 | rhsToken); CVMtraceJITCodegenExec({ char mode1buf[48]; printPC(con); formatMode1(mode1buf, rhsToken); CVMconsolePrintf(" %s%s%s %s, %s, %s", getOpcodeName(opcode), conditions[condCode], setcc?"s":"", regNames[destRegID], regNames[lhsRegID], mode1buf); }); CVMJITdumpCodegenComments(con);}/* Purpose: Emits instructions to do the specified conditional 32 bit ALU operation. */voidCVMCPUemitBinaryALUConstantConditional(CVMJITCompilationContext* con, int opcode, int destRegID, int lhsRegID, CVMInt32 rhsConstValue, CVMBool setcc, CVMCPUCondCode condCode){ CVMCPUALURhsToken rhsToken; CVMRMResource *rhsRes; if (CVMCPUalurhsIsEncodableAsImmediate(opcode, rhsConstValue)) { rhsRes = NULL; rhsToken = CVMARMalurhsEncodeConstantToken(con, rhsConstValue); } else if ((opcode == CVMCPU_BIC_OPCODE || opcode == CVMCPU_OR_OPCODE || opcode == CVMCPU_XOR_OPCODE || opcode == CVMCPU_ADD_OPCODE || opcode == CVMCPU_SUB_OPCODE) && (rhsConstValue < 0x10000)) { /* If it is a 16-bit BIC, OR, XOR, ADD, or SUB, then emit as two instructions rather than loading a constant. */ emitBinaryALUConstant16Conditional(con, opcode, destRegID, lhsRegID, rhsConstValue, setcc, condCode); return; } else { rhsRes = CVMRMgetResourceForConstant32(CVMRM_INT_REGS(con), CVMRM_ANY_SET, CVMRM_EMPTY_SET, rhsConstValue); rhsToken = CVMARMalurhsEncodeRegisterToken(con, CVMRMgetRegisterNumber(rhsRes)); } CVMCPUemitBinaryALUConditional(con, opcode, destRegID, lhsRegID, rhsToken, setcc, condCode); if (rhsRes != NULL) { CVMRMrelinquishResource(CVMRM_INT_REGS(con), rhsRes); }}/* Purpose: Emits instructions to do the specified shift on a 32 bit operand.*/voidCVMCPUemitShiftByConstant(CVMJITCompilationContext *con, int opcode, int destRegID, int srcRegID, CVMUint32 shiftAmount){#ifdef CVM_DEBUG_ASSERTS if (opcode == CVMCPU_SLL_OPCODE) { CVMassert(shiftAmount < 32); }#endif /* mov rDest, rSrc, SHIFTOPCODE #i */ CVMCPUemitMove(con, CVMCPU_MOV_OPCODE, destRegID, CVMARMalurhsEncodeShiftByConstantToken(con, srcRegID, opcode, shiftAmount), CVMJIT_NOSETCC);}/* Purpose: Emits instructions to do the specified 64 bit unary ALU operation. */voidCVMCPUemitUnaryALU64(CVMJITCompilationContext *con, int opcode, int destRegID, int srcRegID){ switch (opcode) { case CVMCPU_NEG64_OPCODE: CVMCPUemitBinaryALU(con, ARM_RSB_OPCODE, LOREG(destRegID), LOREG(srcRegID), CVMCPUALURhsTokenConstZero, CVMJIT_SETCC); CVMCPUemitBinaryALU(con, ARM_RSC_OPCODE, HIREG(destRegID), HIREG(srcRegID), CVMCPUALURhsTokenConstZero, CVMJIT_NOSETCC); break; default: CVMassert(CVM_FALSE); }}/* Purpose: Emits instructions to do the specified 64 bit ALU operation. */voidCVMCPUemitBinaryALU64(CVMJITCompilationContext *con, int opcode, int destRegID, int lhsRegID, int rhsRegID){ if (opcode == CVMCPU_MUL64_OPCODE) { CVMCPUemitMul(con, ARM_UMULL_OPCODE, HIREG(destRegID), LOREG(lhsRegID), LOREG(rhsRegID), LOREG(destRegID)); CVMCPUemitMul(con, CVMARM_MLA_OPCODE, HIREG(destRegID), HIREG(lhsRegID), LOREG(rhsRegID), HIREG(destRegID)); CVMCPUemitMul(con, CVMARM_MLA_OPCODE, HIREG(destRegID), LOREG(lhsRegID), HIREG(rhsRegID), HIREG(destRegID)); } else { int lowOpcode = ((opcode >> 16) & 0xff) << 20; int highOpcode = ((opcode >> 8) & 0xff) << 20; CVMBool setcc = (opcode & 0xff); CVMCPUemitBinaryALURegister(con, lowOpcode, LOREG(destRegID), LOREG(lhsRegID), LOREG(rhsRegID), setcc); CVMCPUemitBinaryALURegister(con, highOpcode, HIREG(destRegID), HIREG(lhsRegID), HIREG(rhsRegID), CVMJIT_NOSETCC); }}/* Purpose: Loads a 64-bit integer constant into a register. */voidCVMCPUemitLoadLongConstant(CVMJITCompilationContext *con, int regID, CVMJavaVal64 *value){ CVMJavaVal64 val; CVMmemCopy64(val.v, value->v); CVMCPUemitLoadConstant(con, LOREG(regID), (int)val.l); CVMCPUemitLoadConstant(con, HIREG(regID), val.l>>32);}/* Purpose: Emits instructions to compares 2 64 bit integers for the specified condition. Return: The returned condition code may have been transformed by the comparison instructions because the emitter may choose to implement the comparison in a different form. For example, a less than comparison can be implemented as a greater than comparison when the 2 arguments are swapped. The returned condition code indicates the actual comparison operation that was emitted.*/CVMCPUCondCodeCVMCPUemitCompare64(CVMJITCompilationContext *con, int opcode, CVMCPUCondCode condCode, int lhsRegID, int rhsRegID){ CVMRMResource *extra; int t; CVMassert(opcode == CVMCPU_CMP64_OPCODE); /* * == and != are easy. All other cases need to be mapped into * < or >=, which are also "easy". */ switch (condCode){ case CVMCPU_COND_EQ: case CVMCPU_COND_NE: CVMJITcsSetStatusInstruction(con, condCode); CVMCPUemitCompareRegister(con, CVMCPU_CMP_OPCODE, condCode, HIREG(lhsRegID), HIREG(rhsRegID)); CVMARMemitCompareConditional(con, CVMCPU_CMP_OPCODE, LOREG(lhsRegID), CVMARMalurhsEncodeRegisterToken(con, LOREG(rhsRegID)), CVMCPU_COND_EQ); break; case CVMCPU_COND_GT: t = rhsRegID; rhsRegID = lhsRegID; lhsRegID = t; condCode = CVMCPU_COND_LT; goto easyCase; case CVMCPU_COND_LE: t = rhsRegID; rhsRegID = lhsRegID; lhsRegID = t; condCode = CVMCPU_COND_GE; goto easyCase; case CVMCPU_COND_LT: case CVMCPU_COND_GE:easyCase: /* extra is a dummy target for the sbc instruction */ extra = CVMRMgetResource(CVMRM_INT_REGS(con), CVMRM_ANY_SET, CVMRM_EMPTY_SET, 1); CVMCPUemitCompareRegister(con, CVMCPU_CMP_OPCODE, condCode, LOREG(lhsRegID), LOREG(rhsRegID)); CVMJITcsSetDestRegister(con, CVMRMgetRegisterNumber(extra)); CVMCPUemitBinaryALURegister(con, ARM_SBC_OPCODE, CVMRMgetRegisterNumber(extra), HIREG(lhsRegID), HIREG(rhsRegID), CVMJIT_SETCC); CVMRMrelinquishResource(CVMRM_INT_REGS(con), extra); break; default: CVMassert(CVM_FALSE); /* Unsupported condition code. */ } return condCode;}/* Purpose: Emits instructions to convert a 32 bit int into a 64 bit int. */voidCVMCPUemitInt2Long(CVMJITCompilationContext *con, int destRegID, int srcRegID){ CVMCPUemitMoveRegister(con, CVMCPU_MOV_OPCODE, LOREG(destRegID), srcRegID, CVMJIT_NOSETCC); CVMCPUemitShiftByConstant(con, CVMCPU_SRA_OPCODE, HIREG(destRegID), srcRegID, 31);}/* Purpose: Emits instructions to convert a 64 bit int into a 32 bit int. */voidCVMCPUemitLong2Int(CVMJITCompilationContext *con, int destRegID, int srcRegID){ CVMCPUemitMoveRegister(con, CVMCPU_MOV_OPCODE, destRegID, LOREG(srcRegID), CVMJIT_NOSETCC);}voidCVMCPUemitMul( CVMJITCompilationContext* con, int opcode, int destreg, int lhsreg, int rhsreg, int extrareg ) /* MLA "accumulate from" reg and UMULL low reg */{ CVMRMResource* extraregRes = NULL; CVMassert(opcode == CVMCPU_MULL_OPCODE || opcode == CVMCPU_MULH_OPCODE || opcode == ARM_UMULL_OPCODE || opcode == CVMARM_MLA_OPCODE); if (opcode == CVMCPU_MULH_OPCODE) { CVMassert(extrareg == CVMCPU_INVALID_REG); extraregRes = CVMRMgetResource(CVMRM_INT_REGS(con), CVMRM_ANY_SET, CVMRM_EMPTY_SET, 1); /* extrareg needs to be the low word we want to ignore */ extrareg = CVMRMgetRegisterNumber(extraregRes); } if (extrareg == CVMCPU_INVALID_REG) { CVMassert(opcode == CVMCPU_MULL_OPCODE); extrareg = 0; /* extrareg must be 0 for mul */ } else if (opcode == CVMARM_MLA_OPCODE) { CVMJITcsPushSourceRegister(con, extrareg); } else { CVMJITcsSetDestRegister2(con, extrareg); } CVMJITcsSetDestRegister(con, destreg); CVMJITcsPushSourceRegister(con, lhsreg); CVMJITcsPushSourceRegister(con, rhsreg); emitInstruction(con, ARM_MAKE_CONDCODE_BITS(CVMCPU_COND_AL) | (CVMUint32)opcode | destreg << 16 | extrareg << 12 | rhsreg << 8 | lhsreg); CVMtraceJITCodegenExec({ char badcode[20]; const char *opcodename; printPC(con); switch (opcode){ case CVMCPU_MULL_OPCODE: CVMconsolePrintf(" mul %s, %s, %s", regNames[destreg], regNames[lhsreg], regNames[rhsreg]); goto doneTracingMul; case CVMARM_MLA_OPCODE: CVMconsolePrintf(" mla %s, %s, %s, %s", regNames[destreg], regNames[lhsreg], regNames[rhsreg], regNames[extrareg]); goto doneTracingMul; case CVMCPU_MULH_OPCODE: opcodename = "smull"; break; case ARM_UMULL_OPCODE: opcodename = "umull"; break; default: sprintf(badcode, "Unknown(%08x)", opcode); opcodename = badcode; break; } CVMconsolePrintf(" %s %s, %s, %s, %s", opcodename, regNames[extrareg], regNames[destreg], regNames[lhsreg], regNames[rhsreg]);doneTracingMul: (void)0; }); CVMJITdumpCodegenComments(con); if (extraregRes != NULL) { CVMRMrelinquishResource(CVMRM_INT_REGS(con), extraregRes); }}voidCVMCPUemitMoveConditional(CVMJITCompilationContext* con, int opcode, int destRegID, CVMCPUALURhsToken srcToken, CVMBool setcc, CVMCPUCondCode condCode){ CVMassert(opcode == CVMCPU_MOV_OPCODE || opcode == ARM_MVN_OPCODE || opcode == CVMCPU_FMOV_OPCODE || opcode == CVMCPU_DMOV_OPCODE);#ifdef CVM_JIT_USE_FP_HARDWARE if (opcode == CVMCPU_FMOV_OPCODE || opcode == CVMCPU_DMOV_OPCODE) { emitInstruction(con, ARM_MAKE_CONDCODE_BITS(condCode) | (CVMUint32)opcode | (destRegID & 0x01) << 22 | (destRegID >> 1) << 12 | (srcToken & 0x01) << 5 | (srcToken >> 1)); CVMtraceJITCodegenExec({ char mode1buf[48]; formatMode1(mode1buf, srcToken); printPC(con); CVMconsolePrintf(" %s%s %%f%d, %%f%d", getOpcodeName(opcode), conditions[condCode], destRegID, srcToken); }); } else#endif { CVMJITcsSetCompareInstruction(con, setcc); CVMJITcsSetStatusInstruction(con, condCode); CVMJITcsSetDestRegister(con, destRegID); emitInstruction(con, ARM_MAKE_CONDCODE_BITS(condCode) | (setcc ? (1 << 20) : 0) | (CVMUint32)opcode | destRegID << 12 | srcToken); CVMtraceJITCodegenExec({ char mode1buf[48]; formatMode1(mode1buf, srcToken); printPC(con); CVMconsolePrintf(" %s%s%s %s, %s", getOpcodeName(opcode), conditions[condCode], setcc?"s":"", regNames[destRegID], mode1buf); }); } CVMJITdumpCodegenComments(con);}static voidCVMARMemitCompareConditional(CVMJITCompilationContext* con, int opcode, int lhsRegID, CVMCPUALURhsToken rhsToken, CVMCPUCondCode condCode){ CVMassert(opcode == CVMCPU_CMP_OPCODE || opcode == CVMCPU_CMN_OPCODE); CVMJITcsPushSourceRegister(con, lhsRegID); CVMJITcsSetCompareInstruction(con, CVM_TRUE); emitInstruction(con, ARM_MAKE_CONDCODE_BITS(condCode) |
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -