📄 jitemitter_cpu.c
字号:
/* condCodes */#define ARM_MAKE_CONDCODE_BITS(cond) ((CVMUint32)((CVMUint32)(cond) << 28))/* Support for emitting ARM mode 1 operands: */#define ROTATE_RIGHT_32BIT(value, rotateValue) \ ((((CVMUint32)(value)) >> (rotateValue)) | \ (((CVMUint32)(value)) << (32 - (rotateValue))))#define ROTATE_LEFT_32BIT(value, rotateValue) \ ((((CVMUint32)(value)) << (rotateValue)) | \ (((CVMUint32)(value)) >> (32 - (rotateValue))))#ifdef CVM_TRACE_JITstatic const char* const conditions[] = { "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};/* Purpose: Returns the name of the specified opcode. */static const char *getOpcodeName(CVMInt32 opcode){ const char *name = NULL; switch(opcode) { case CVMCPU_LDR32_OPCODE: name = "ldr"; break; case CVMCPU_STR32_OPCODE: name = "str"; break; case CVMCPU_LDR16U_OPCODE: name = "ldrh"; break; case CVMCPU_LDR16_OPCODE: name = "ldrsh"; break; case CVMCPU_STR16_OPCODE: name = "strh"; break; case CVMCPU_LDR8U_OPCODE: name = "ldrb"; break; case CVMCPU_LDR8_OPCODE: name = "ldrsb"; break; case CVMCPU_STR8_OPCODE: name = "strb"; break; case CVMCPU_ADD_OPCODE: name = "add"; break; case ARM_ADC_OPCODE: name = "adc"; break; case CVMCPU_SUB_OPCODE: name = "sub"; break; case ARM_SBC_OPCODE: name = "sbc"; break; case ARM_RSB_OPCODE: name = "rsb"; break; case ARM_RSC_OPCODE: name = "rsc"; break; case CVMCPU_AND_OPCODE: name = "and"; break; case CVMCPU_OR_OPCODE: name = "orr"; break; case CVMCPU_XOR_OPCODE: name = "eor"; break; case CVMCPU_BIC_OPCODE: name = "bic"; break; case CVMCPU_MOV_OPCODE: name = "mov"; break; case ARM_MVN_OPCODE: name = "mvn"; break; case CVMCPU_CMP_OPCODE: name = "cmp"; break; case CVMCPU_CMN_OPCODE: name = "cmn"; break; case CVMCPU_FADD_OPCODE: name = "fadds"; break; case CVMCPU_FSUB_OPCODE: name = "fsubs"; break; case CVMCPU_FMUL_OPCODE: name = "fmuls"; break; case CVMCPU_FDIV_OPCODE: name = "fdivs"; break; case CVMCPU_DADD_OPCODE: name = "faddd"; break; case CVMCPU_DSUB_OPCODE: name = "fsubd"; break; case CVMCPU_DMUL_OPCODE: name = "fmuld"; break; case CVMCPU_DDIV_OPCODE: name = "fdivd"; break; case CVMCPU_FLDR32_OPCODE: name = "flds"; break; case CVMCPU_FLDR64_OPCODE: name = "fldd"; break; case CVMCPU_FSTR32_OPCODE: name = "fsts"; break; case CVMCPU_FSTR64_OPCODE: name = "fstd"; break; case CVMARM_FLDRM32_OPCODE: name = "fldms"; break; case CVMARM_FLDRM64_OPCODE: name = "fldmd"; break; case CVMARM_FSTRM32_OPCODE: name = "fstms"; break; case CVMARM_FSTRM64_OPCODE: name = "fstmd"; break; case CVMCPU_FNEG_OPCODE: name = "fnegs"; break; case CVMCPU_DNEG_OPCODE: name = "fnegd"; break; case CVMARM_F2I_OPCODE: name = "fsitos"; break; case CVMARM_I2F_OPCODE: name = "ftosizs"; break; case CVMARM_D2I_OPCODE: name = "ftosizd"; break; case CVMARM_I2D_OPCODE: name = "fsitod"; break; case CVMARM_F2D_OPCODE: name = "fcvtds"; break; case CVMARM_D2F_OPCODE: name = "fcvtsd"; break; case CVMCPU_FMOV_OPCODE: name = "fcpys"; break; case CVMCPU_DMOV_OPCODE: name = "fcpyd"; break; case CVMARM_MOVFA_OPCODE: name = "fmsr"; break; case CVMARM_MOVAF_OPCODE: name = "fmrs"; break; case CVMARM_MOVDA_OPCODE: name = "fmdrr"; break; case CVMARM_MOVAD_OPCODE: name = "fmrrd"; break; case CVMARM_MOVSA_OPCODE: name = "fmxr"; break; case CVMARM_MOVAS_OPCODE: name = "fmrx"; break; case CVMCPU_FCMP_OPCODE: name = "fcmps"; break; case CVMARM_FCMPES_OPCODE: name = "fcmpes"; break; case CVMCPU_DCMP_OPCODE: name = "fcmpd"; break; case CVMARM_DCMPED_OPCODE: name = "fcmped"; break; case CVMARM_FMSTAT_OPCODE: name = "fmstat"; break; default: CVMconsolePrintf("Unknown opcode 0x%08x", opcode); CVMassert(CVM_FALSE); /* Unknown opcode name */ } return name;}#endif/* Purpose: Encodes a large ARM mode1 constant using rotate right if possible.*//* Returns: CVM_TRUE is possible, else returns CVM_FALSE. */CVMBool CVMARMmode1EncodeImmediate(CVMUint32 value, CVMUint32 *baseValue, CVMUint32 *rotateValue){ CVMUint32 rotate; CVMUint32 base; CVMUint32 result; /* Check for the likely and easy case first: */ if (value < 256) { if (baseValue != NULL) { CVMassert(rotateValue != NULL); *baseValue = value; *rotateValue = 0; } return CVM_TRUE; } /* Try to encode the constant with each of the 16 possible rotation values: */ for (rotate = 2; rotate < 32; rotate += 2) { base = ROTATE_LEFT_32BIT(value, rotate) & 0xFF; result = ROTATE_RIGHT_32BIT(base, rotate); if (result == value) { if (baseValue != NULL) { CVMassert(rotateValue != NULL); *baseValue = base; *rotateValue = rotate / 2; } return CVM_TRUE; /* Successfully encoded it. */ } } return CVM_FALSE; /* Not able to encode it. */}/* * Functions that assists in tracing generated code as assembler output. */#ifdef CVM_TRACE_JIT#ifdef CVMCPU_HAS_CP_REG#define ARM_CP_REGNAME "rCP"#else#define ARM_CP_REGNAME "v7"#endif#if defined(CVMJIT_TRAP_BASED_GC_CHECKS) && \ !defined(CVMCPU_HAS_VOLATILE_GC_REG)#define ARM_GC_REGNAME "rGC"#else#define ARM_GC_REGNAME "v8"#endifstatic const char *const regNames[] = { "a1", "a2", "a3", "a4", "rJFP", "rJSP", "v3", "v4", "v5", "v6", ARM_CP_REGNAME, ARM_GC_REGNAME, "ip", "sp", "lr", "pc"};static const char*shiftname(int shiftop){ switch (shiftop){ case CVMCPU_SLL_OPCODE: return "LSL"; case CVMCPU_SRL_OPCODE: return "LSR"; case CVMCPU_SRA_OPCODE: return "ASR"; default: return "???"; }}static voidformatMode1(char* buf, CVMCPUALURhsToken token){ CVMARMALURhsType type = 0; int constValue = 0; int r1RegID = 0; int r2RegID = 0; int shiftOp = 0; if ((token & 0x0e000000) == CVMARM_MODE1_CONSTANT) { int base = token & 0xff; int rotate = (token >> 7) & 0x1e; type = CVMARM_ALURHS_CONSTANT; constValue = ROTATE_RIGHT_32BIT(base, rotate); } else { shiftOp = token & 0x60; r1RegID = token &0xf; if ((token & 0x0e000090) == CVMARM_MODE1_SHIFT_REGISTER) { type = CVMARM_ALURHS_SHIFT_BY_REGISTER; r2RegID = (token >> 8) & 0x1f; } else { type = CVMARM_ALURHS_SHIFT_BY_CONSTANT; constValue = (token >> 7) & 0xf; } } switch(type){ case CVMARM_ALURHS_CONSTANT: sprintf(buf, "#%d", constValue); break; case CVMARM_ALURHS_SHIFT_BY_CONSTANT: { sprintf(buf, "%s %s #%d", regNames[r1RegID], shiftname(shiftOp), constValue); break; } case CVMARM_ALURHS_SHIFT_BY_REGISTER: sprintf(buf,"%s %s %s", regNames[r1RegID], shiftname(shiftOp), regNames[r2RegID]); break; }}/* Purpose: Dumps the content of an ARM mode 2 operand. */voiddumpMode2Instruction(CVMJITCompilationContext *con, CVMUint32 instruction, CVMCPUCondCode condCode){ int opcode = instruction & 0x0c500000; int destreg = (instruction >> 12) & 0xF; int basereg = (instruction >> 16) & 0xF; CVMBool offsetIsToBeAdded = (instruction & ARM_LOADSTORE_ADDOFFSET); CVMBool isPreIndex = (instruction & ARM_LOADSTORE_PREINDEX); CVMassert(opcode == CVMCPU_LDR32_OPCODE || opcode == CVMCPU_STR32_OPCODE || opcode == CVMCPU_STR8_OPCODE); CVMconsolePrintf(" %s%s %s, [%s", getOpcodeName(opcode), conditions[condCode], regNames[destreg], regNames[basereg]); if (isPreIndex) { CVMconsolePrintf(", "); } else { CVMconsolePrintf("], "); } if (instruction & ARM_LOADSTORE_REGISTER_OFFSET) { int offsetreg = instruction & 0xF; int shiftImmediate = (instruction >> 7) & 0x1F; int shiftOp = instruction & (0x3 << 5); CVMconsolePrintf("%c%s", (offsetIsToBeAdded?'+':'-'), regNames[offsetreg]); if (shiftImmediate != 0) { CVMconsolePrintf(", %s #%d", shiftname(shiftOp), shiftImmediate); } } else { CVMUint32 immediateValue = instruction & 0xFFF; CVMconsolePrintf("#%c%d", (offsetIsToBeAdded?'+':'-'), immediateValue); } if (isPreIndex) { CVMconsolePrintf("]"); } if (instruction & ARM_LOADSTORE_WRITEBACK) { CVMconsolePrintf("!"); }}/* Purpose: Dumps the content of an ARM mode 5 operand. */voiddumpMode5Instruction(CVMJITCompilationContext *con, CVMUint32 instruction, CVMCPUCondCode condCode){#ifdef CVM_JIT_USE_FP_HARDWARE int opcode, destreg, basereg; int P, U, W, L; int type, size, offset, puw; /* VFP load/store addressing modes */ enum { unindexed = 2, increment, negativeOffset, decrement, positiveOffset }; opcode = instruction & 0x0FF00F00; destreg = (instruction >> 12) & 0xF; destreg = ((instruction >> 22) & 0x1) | destreg << 1; basereg = (instruction >> 16) & 0xF; P = (instruction >> 24) & 0x1; U = (instruction >> 23) & 0x1; W = (instruction >> 21) & 0x1; L = (instruction >> 20) & 0x1; type = (instruction >> 8) & 0xF; size = (instruction & 0xFF) + destreg; offset = instruction & 0x000000FF; puw = P << 2 | U << 1 | W; switch (puw) { case unindexed: case increment: case decrement: { CVMconsolePrintf(" f%sm", (L ? "ld" : "st")); if (basereg == CVMARM_sp) { CVMconsolePrintf("%c", L == P ? 'e' : 'f'); CVMconsolePrintf("%c", L == U ? 'd' : 'a'); } else { CVMconsolePrintf("%c", L == P ? 'i' : 'd'); CVMconsolePrintf("%c", L == U ? 'b' : 'a'); } CVMconsolePrintf("%c", type == 0xA ? 's' : 'd'); CVMconsolePrintf("%s %s", conditions[condCode], regNames[basereg]); if (W) { CVMconsolePrintf("!"); } CVMconsolePrintf(", {"); CVMconsolePrintf("%%f%d", destreg); destreg += (type == 0xA ? 1:2); while (destreg < size) { CVMconsolePrintf(", "); CVMconsolePrintf("%%f%d", destreg); destreg += (type == 0xA ? 1:2); } CVMconsolePrintf("}"); break; } case negativeOffset: case positiveOffset: { CVMconsolePrintf(" f%s%c%s %%f%d, [%s, ", (L ? "ld" : "st"), (type == 0xA ? 's' : 'd'), conditions[condCode], destreg, regNames[basereg]); CVMconsolePrintf("#%c%d", (U ? '+' : '-'), offset); CVMconsolePrintf("]"); break; } default: { CVMconsolePrintf("Unknown opcode 0x%08x", opcode); CVMassert(CVM_FALSE); /* Unknown opcode name */ } }#endif /* CVM_JIT_USE_FP_HARDWARE */}static voidprintPC(CVMJITCompilationContext* con){#ifdef IAI_CODE_SCHEDULER_SCORE_BOARD CVMconsolePrintf("0x%8.8x\t%d \t%d:", CVMJITcbufGetPhysicalPC(con) - 4, CVMJITcbufGetLogicalPC(con) - 4, CVMJITcbufGetLogicalInstructionPC(con));#else CVMconsolePrintf("0x%8.8x\t%d:", CVMJITcbufGetPhysicalPC(con) - 4, CVMJITcbufGetLogicalPC(con) - 4);#endif /*IAI_CODE_SCHEDULER_SCORE_BOARD*/}#endif /* CVM_TRACE_JIT */static voidemitInstruction(CVMJITCompilationContext* con, CVMUint32 instruction){#if 0 CVMtraceJITCodegen(("0x%8.8x\t", instruction));#endif#ifdef IAI_CODE_SCHEDULER_SCORE_BOARD CVMJITcsCalcInstructionPos(con); CVMJITcbufEmitPC(con, CVMJITcbufGetLogicalInstructionPC(con), instruction); CVMJITcsPrepareForNextInstruction(con);#else CVMJITcbufEmit(con, instruction);#endif /*IAI_CODE_SCHEDULER_SCORE_BOARD*/}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -