📄 isel.c
字号:
ARMAMode2* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, IRExpr* off, Int bias ){ HReg tmp, tmp2, roff; Int elemSz = sizeofIRType(descr->elemTy); Int nElems = descr->nElems; ARMImm12A imm12a; /* throw out any cases not generated by an x86 front end. In theory there might be a day where we need to handle them -- if we ever run non-x86-guest on x86 host. */ if (nElems != 8 || (elemSz != 1 && elemSz != 8)) vpanic("genGuestArrayOffset(arm host)"); /* Compute off into a reg, %off. Then return: movl %off, %tmp addl $bias, %tmp (if bias != 0) andl %tmp, 7 ... base(%ebp, %tmp, shift) ... */ tmp = newVRegI(env); roff = iselIntExpr_R(env, off); addInstr(env, mk_iMOVsd_RR(roff, tmp)); if (bias != 0) { if ( mk_ARMImm12A( (UInt)bias, &imm12a ) ) { addInstr(env, ARMInstr_DPInstr2(ARMalu_ADD, tmp, tmp, ARMAMode1_I12A( imm12a ))); } else { HReg tmp3 = newVRegI(env); addInstr(env, ARMInstr_Literal( tmp, (UInt)bias )); addInstr(env, ARMInstr_DPInstr2(ARMalu_ADD, tmp, tmp, ARMAMode1_ShlI( tmp3, 0 ))); } } mk_ARMImm12A( (UInt)7, &imm12a ); addInstr(env, ARMInstr_DPInstr2(ARMalu_AND, tmp, tmp, ARMAMode1_I12A( imm12a ))); vassert(elemSz == 1 || elemSz == 8);// CAB: This anywhere near correct?// X86AMode_IRRS: Immediate + Reg1 + (Reg2 << Shift)// return X86AMode_IRRS( descr->base, hregX86_EBP(), tmp, elemSz==8 ? 3 : 0); tmp2 = newVRegI(env); // tmp2 = GET_BP_REG + (tmp << 3|0) addInstr(env, ARMInstr_DPInstr2(ARMalu_ADD, tmp2, GET_BP_REG(), ARMAMode1_ShlI(tmp, elemSz==8 ? 3 : 0))); return ARMAMode2_RI( tmp2, descr->base );}/*---------------------------------------------------------*//*--- ISEL ... ---*//*---------------------------------------------------------*//* --------------------- AMODEs --------------------- *//* Return an AMode which computes the value of the specified expression, possibly also adding insns to the code list as a result.*//* ---------------- Addressing Mode 1 ---------------- */static Bool sane_AMode1 ( ARMAMode1* am ){ switch (am->tag) { default: vpanic("sane_AMode1: unknown arm amode tag"); }}static ARMAMode1* iselIntExpr_AMode1 ( ISelEnv* env, IRExpr* e ){ ARMAMode1* am = iselIntExpr_AMode1_wrk(env, e); vassert(sane_AMode1(am)); return am;}/* DO NOT CALL THIS DIRECTLY ! */static ARMAMode1* iselIntExpr_AMode1_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32); // ARMam1_I12A, /* Imm12A: extended (rotated) immedate */ // ARMam1_ShlI, /* ShlI reg Imm5 */ // ARMam1_ShrI, /* ShrI reg Imm5 */ // ARMam1_SarI, /* SarI reg Imm5 */ // ARMam1_ShlR, /* ShlR reg reg */ // ARMam1_ShrR, /* ShrR reg reg */ // ARMam1_SarR, /* SarR reg reg */ // ALU ops: /* ARMalu_And, ARMalu_Orr, ARMalu_Eor, ARMalu_Bic, // Logic ARMalu_Sub, ARMalu_Rsb, ARMalu_Add, ARMalu_Adc, ARMalu_Sbc, ARMalu_Rsc, // Arith ARMalu_Tst, ARMalu_Teq, ARMalu_Cmp, ARMalu_Cmn, // test ARMalu_Mov, ARMalu_Mvn // Move */ return NULL; }/* ---------------- Addressing Mode 2 ---------------- */static Bool sane_AMode2 ( ARMAMode2* am ){ switch (am->tag) { default: vpanic("sane_AMode2: unknown arm amode tag"); }}static ARMAMode2* iselIntExpr_AMode2_wrk ( ISelEnv* env, IRExpr* e ){ ARMAMode2* am = iselIntExpr_AMode2_wrk(env, e); vassert(sane_AMode2(am)); return am;}/* DO NOT CALL THIS DIRECTLY ! */static ARMAMode2* iselIntExpr_AMode2 ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32); // ARMam2_RI, /* Reg +/- Imm12 */ // ARMam2_RR, /* Reg +/- Reg */ // ARMam2_RRS, /* Reg +/- (Reg << Imm5) */ return NULL; }/* ---------------- Addressing Mode 3 ---------------- */static Bool sane_AMode3 ( ARMAMode3* am ){ switch (am->tag) { default: vpanic("sane_AMode3: unknown arm amode tag"); }}static ARMAMode3* iselIntExpr_AMode3 ( ISelEnv* env, IRExpr* e ){ ARMAMode3* am = iselIntExpr_AMode3_wrk(env, e); vassert(sane_AMode3(am)); return am;}/* DO NOT CALL THIS DIRECTLY ! */static ARMAMode3* iselIntExpr_AMode3_wrk ( ISelEnv* env, IRExpr* e ){ IRType ty = typeOfIRExpr(env->type_env,e); vassert(ty == Ity_I32); // ARMam3_RI, /* Reg +/- Imm8 */ // ARMam3_RR, /* Reg +/- Reg */ return NULL; }/* ---------------- Branch Destination ---------------- */static ARMBranchDest* iselIntExpr_BD ( ISelEnv* env, IRExpr* e ){ ARMBranchDest* bd = iselIntExpr_BD_wrk(env, e); /* sanity checks ... */ switch (bd->tag) { case ARMbdImm: return bd; case ARMbdReg: vassert(hregClass(bd->ARMbd.Reg.reg) == HRcInt32);// vassert(hregIsVirtual(bd->ARMbd.Reg.reg)); // CAB ? return bd; default: vpanic("iselIntExpr_BD: unknown arm BD tag"); }}/* DO NOT CALL THIS DIRECTLY ! */static ARMBranchDest* iselIntExpr_BD_wrk ( ISelEnv* env, IRExpr* e ){ /* ARMbdImm, ARMbdReg */ return NULL;}/* --------------------- CONDCODE --------------------- *//* Generate code to evaluated a bit-typed expression, returning the condition code which would correspond when the expression would notionally have returned 1. */static ARMCondCode iselCondCode ( ISelEnv* env, IRExpr* e ){ /* Uh, there's nothing we can sanity check here, unfortunately. */ return iselCondCode_wrk(env, e);}/* DO NOT CALL THIS DIRECTLY ! */static ARMCondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ){#if 0 MatchInfo mi; DECLARE_PATTERN(p_32to1); DECLARE_PATTERN(p_1Uto32_then_32to1);#endif return 0;}static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ){ return iselIntExpr_R_wrk(env, e);}/* DO NOT CALL THIS DIRECTLY ! */static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ){ return 0;}/*---------------------------------------------------------*//*--- ISEL: Statements ---*//*---------------------------------------------------------*/static void iselStmt ( ISelEnv* env, IRStmt* stmt ){ if (vex_traceflags & VEX_TRACE_VCODE) { vex_printf("\n-- "); ppIRStmt(stmt); vex_printf("\n"); } switch (stmt->tag) { /* --------- STORE --------- */ /* little-endian write to memory */ case Ist_Store: { HReg reg; IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr); IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data); IREndness end = stmt->Ist.Store.end; if (tya != Ity_I32 || end != Iend_LE) goto stmt_fail; reg = iselIntExpr_R(env, stmt->Ist.Store.data); if (tyd == Ity_I8) { ARMAMode2* am2 = iselIntExpr_AMode2(env, stmt->Ist.Store.addr); addInstr(env, ARMInstr_StoreB(reg,am2)); return; } if (tyd == Ity_I16) { ARMAMode3* am3 = iselIntExpr_AMode3(env, stmt->Ist.Store.addr); addInstr(env, ARMInstr_StoreH(reg,am3)); return; } if (tyd == Ity_I32) { ARMAMode2* am2 = iselIntExpr_AMode2(env, stmt->Ist.Store.addr); addInstr(env, ARMInstr_StoreW(reg,am2)); return; } } /* --------- PUT --------- */ /* write guest state, fixed offset */ case Ist_Put: { IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Put.data); HReg reg = iselIntExpr_R(env, stmt->Ist.Put.data); // CAB: This anywhere near right?! if (tyd == Ity_I32) { ARMAMode2* am2 = ARMAMode2_RI(GET_BP_REG(), stmt->Ist.Put.offset); addInstr(env, ARMInstr_StoreW(reg, am2)); return; } if (tyd == Ity_I16) { ARMAMode3* am3 = ARMAMode3_RI(GET_BP_REG(), stmt->Ist.Put.offset); addInstr(env, ARMInstr_StoreH(reg, am3)); return; } if (tyd == Ity_I8) { ARMAMode2* am2 = ARMAMode2_RI(GET_BP_REG(), stmt->Ist.Put.offset); addInstr(env, ARMInstr_StoreB(reg, am2)); return; }// CAB: Ity_I32, Ity_I16 ? break; } /* --------- Indexed PUT --------- */ /* write guest state, run-time offset */ case Ist_PutI: { ARMAMode2* am2 = genGuestArrayOffset( env, stmt->Ist.PutI.descr, stmt->Ist.PutI.ix, stmt->Ist.PutI.bias ); IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data); if (tyd == Ity_I8) { HReg reg = iselIntExpr_R(env, stmt->Ist.PutI.data); addInstr(env, ARMInstr_StoreB(reg, am2)); return; }// CAB: Ity_I32, Ity_I16 ? break; } /* --------- TMP --------- */ /* assign value to temporary */ case Ist_Tmp: { IRTemp tmp = stmt->Ist.Tmp.tmp; IRType ty = typeOfIRTemp(env->type_env, tmp); if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) { ARMAMode1* am = iselIntExpr_AMode1(env, stmt->Ist.Tmp.data); HReg dst = lookupIRTemp(env, tmp); addInstr(env, ARMInstr_DPInstr1(ARMalu_MOV,dst,am)); return; }// CAB: Ity_I1 ? break; } /* --------- Call to DIRTY helper --------- */ /* call complex ("dirty") helper function */ case Ist_Dirty: { //IRType retty; IRDirty* d = stmt->Ist.Dirty.details; Bool passBBP = False; if (d->nFxState == 0) vassert(!d->needsBBP); passBBP = toBool(d->nFxState > 0 && d->needsBBP); /* Marshal args, do the call, clear stack. */ doHelperCall( env, passBBP, d->guard, d->cee, d->args ); /* Now figure out what to do with the returned value, if any. */ if (d->tmp == IRTemp_INVALID) /* No return value. Nothing to do. */ return; //retty = typeOfIRTemp(env->type_env, d->tmp);// CAB: ? if (retty == Ity_I64) {#if 0 if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) { /* The returned value is in %eax. Park it in the register associated with tmp. */ HReg dst = lookupIRTemp(env, d->tmp); addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dst) ); return; }#endif break; } /* --------- EXIT --------- */ /* conditional exit from BB */ case Ist_Exit: { ARMBranchDest* dst; ARMCondCode cc; if (stmt->Ist.Exit.dst->tag != Ico_U32) vpanic("isel_arm: Ist_Exit: dst is not a 32-bit value"); // CAB: Where does jumpkind fit in ? // stmt->Ist.Exit.jk dst = iselIntExpr_BD(env, IRExpr_Const(stmt->Ist.Exit.dst)); cc = iselCondCode(env,stmt->Ist.Exit.guard); addInstr(env, ARMInstr_Branch(cc, dst)); return; } default: break; } stmt_fail: ppIRStmt(stmt); vpanic("iselStmt");}/*---------------------------------------------------------*//*--- ISEL: Basic block terminators (Nexts) ---*//*---------------------------------------------------------*/static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ){ ARMBranchDest* bd; if (vex_traceflags & VEX_TRACE_VCODE) { vex_printf("\n-- goto {"); ppIRJumpKind(jk); vex_printf("} "); ppIRExpr(next); vex_printf("\n"); } bd = iselIntExpr_BD(env, next); // CAB: jk ? addInstr( env, ARMInstr_Branch(ARMccAL, bd) );}/*---------------------------------------------------------*//*--- Insn selector top-level ---*//*---------------------------------------------------------*//* Translate an entire BB to arm code. */HInstrArray* iselBB_ARM ( IRBB* bb ){ Int i, j; /* Make up an initial environment to use. */ ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv)); env->vreg_ctr = 0; /* Set up output code array. */ env->code = newHInstrArray(); /* Copy BB's type env. */ env->type_env = bb->tyenv; /* Make up an IRTemp -> virtual HReg mapping. This doesn't change as we go along. */ env->n_vregmap = bb->tyenv->types_used; env->vregmap = LibVEX_Alloc(env->n_vregmap * sizeof(HReg)); /* For each IR temporary, allocate a 32bit virtual register. */ j = 0; for (i = 0; i < env->n_vregmap; i++) { env->vregmap[i] = mkHReg(j++, HRcInt32, True); } env->vreg_ctr = j; /* Ok, finally we can iterate over the statements. */ for (i = 0; i < bb->stmts_used; i++) if (bb->stmts[i]) iselStmt(env,bb->stmts[i]); iselNext(env,bb->next,bb->jumpkind); /* record the number of vregs we used. */ env->code->n_vregs = env->vreg_ctr; return env->code;}/*---------------------------------------------------------------*//*--- end host-x86/isel.c ---*//*---------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -