📄 hdefs.c
字号:
default: vpanic("getRegUsage_X86Instr:Call:regparms"); } /* Finally, there is the issue that the insn trashes a register because the literal target address has to be loaded into a register. Fortunately, for the 0/1/2 regparm case, we can use EAX, EDX and ECX respectively, so this does not cause any further damage. For the 3-regparm case, we'll have to choose another register arbitrarily -- since A, D and C are used for parameters -- and so we might as well choose EDI. */ if (i->Xin.Call.regparms == 3) addHRegUse(u, HRmWrite, hregX86_EDI()); /* Upshot of this is that the assembler really must observe the here-stated convention of which register to use as an address temporary, depending on the regparmness: 0==EAX, 1==EDX, 2==ECX, 3==EDI. */ return; case Xin_Goto: addRegUsage_X86RI(u, i->Xin.Goto.dst); addHRegUse(u, HRmWrite, hregX86_EAX()); /* used for next guest addr */ addHRegUse(u, HRmWrite, hregX86_EDX()); /* used for dispatcher addr */ if (i->Xin.Goto.jk != Ijk_Boring && i->Xin.Goto.jk != Ijk_Call && i->Xin.Goto.jk != Ijk_Ret) /* note, this is irrelevant since ebp is not actually available to the allocator. But still .. */ addHRegUse(u, HRmWrite, hregX86_EBP()); return; case Xin_CMov32: addRegUsage_X86RM(u, i->Xin.CMov32.src, HRmRead); addHRegUse(u, HRmModify, i->Xin.CMov32.dst); return; case Xin_LoadEX: addRegUsage_X86AMode(u, i->Xin.LoadEX.src); addHRegUse(u, HRmWrite, i->Xin.LoadEX.dst); return; case Xin_Store: addHRegUse(u, HRmRead, i->Xin.Store.src); addRegUsage_X86AMode(u, i->Xin.Store.dst); return; case Xin_Set32: addHRegUse(u, HRmWrite, i->Xin.Set32.dst); return; case Xin_Bsfr32: addHRegUse(u, HRmRead, i->Xin.Bsfr32.src); addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst); return; case Xin_MFence: return; case Xin_FpUnary: addHRegUse(u, HRmRead, i->Xin.FpUnary.src); addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst); return; case Xin_FpBinary: addHRegUse(u, HRmRead, i->Xin.FpBinary.srcL); addHRegUse(u, HRmRead, i->Xin.FpBinary.srcR); addHRegUse(u, HRmWrite, i->Xin.FpBinary.dst); return; case Xin_FpLdSt: addRegUsage_X86AMode(u, i->Xin.FpLdSt.addr); addHRegUse(u, i->Xin.FpLdSt.isLoad ? HRmWrite : HRmRead, i->Xin.FpLdSt.reg); return; case Xin_FpLdStI: addRegUsage_X86AMode(u, i->Xin.FpLdStI.addr); addHRegUse(u, i->Xin.FpLdStI.isLoad ? HRmWrite : HRmRead, i->Xin.FpLdStI.reg); return; case Xin_Fp64to32: addHRegUse(u, HRmRead, i->Xin.Fp64to32.src); addHRegUse(u, HRmWrite, i->Xin.Fp64to32.dst); return; case Xin_FpCMov: addHRegUse(u, HRmRead, i->Xin.FpCMov.src); addHRegUse(u, HRmModify, i->Xin.FpCMov.dst); return; case Xin_FpLdCW: addRegUsage_X86AMode(u, i->Xin.FpLdCW.addr); return; case Xin_FpStSW_AX: addHRegUse(u, HRmWrite, hregX86_EAX()); return; case Xin_FpCmp: addHRegUse(u, HRmRead, i->Xin.FpCmp.srcL); addHRegUse(u, HRmRead, i->Xin.FpCmp.srcR); addHRegUse(u, HRmWrite, i->Xin.FpCmp.dst); addHRegUse(u, HRmWrite, hregX86_EAX()); return; case Xin_SseLdSt: addRegUsage_X86AMode(u, i->Xin.SseLdSt.addr); addHRegUse(u, i->Xin.SseLdSt.isLoad ? HRmWrite : HRmRead, i->Xin.SseLdSt.reg); return; case Xin_SseLdzLO: addRegUsage_X86AMode(u, i->Xin.SseLdzLO.addr); addHRegUse(u, HRmWrite, i->Xin.SseLdzLO.reg); return; case Xin_SseConst: addHRegUse(u, HRmWrite, i->Xin.SseConst.dst); return; case Xin_Sse32Fx4: vassert(i->Xin.Sse32Fx4.op != Xsse_MOV); unary = toBool( i->Xin.Sse32Fx4.op == Xsse_RCPF || i->Xin.Sse32Fx4.op == Xsse_RSQRTF || i->Xin.Sse32Fx4.op == Xsse_SQRTF ); addHRegUse(u, HRmRead, i->Xin.Sse32Fx4.src); addHRegUse(u, unary ? HRmWrite : HRmModify, i->Xin.Sse32Fx4.dst); return; case Xin_Sse32FLo: vassert(i->Xin.Sse32FLo.op != Xsse_MOV); unary = toBool( i->Xin.Sse32FLo.op == Xsse_RCPF || i->Xin.Sse32FLo.op == Xsse_RSQRTF || i->Xin.Sse32FLo.op == Xsse_SQRTF ); addHRegUse(u, HRmRead, i->Xin.Sse32FLo.src); addHRegUse(u, unary ? HRmWrite : HRmModify, i->Xin.Sse32FLo.dst); return; case Xin_Sse64Fx2: vassert(i->Xin.Sse64Fx2.op != Xsse_MOV); unary = toBool( i->Xin.Sse64Fx2.op == Xsse_RCPF || i->Xin.Sse64Fx2.op == Xsse_RSQRTF || i->Xin.Sse64Fx2.op == Xsse_SQRTF ); addHRegUse(u, HRmRead, i->Xin.Sse64Fx2.src); addHRegUse(u, unary ? HRmWrite : HRmModify, i->Xin.Sse64Fx2.dst); return; case Xin_Sse64FLo: vassert(i->Xin.Sse64FLo.op != Xsse_MOV); unary = toBool( i->Xin.Sse64FLo.op == Xsse_RCPF || i->Xin.Sse64FLo.op == Xsse_RSQRTF || i->Xin.Sse64FLo.op == Xsse_SQRTF ); addHRegUse(u, HRmRead, i->Xin.Sse64FLo.src); addHRegUse(u, unary ? HRmWrite : HRmModify, i->Xin.Sse64FLo.dst); return; case Xin_SseReRg: if (i->Xin.SseReRg.op == Xsse_XOR && i->Xin.SseReRg.src == i->Xin.SseReRg.dst) { /* reg-alloc needs to understand 'xor r,r' as a write of r */ /* (as opposed to a rite of passage :-) */ addHRegUse(u, HRmWrite, i->Xin.SseReRg.dst); } else { addHRegUse(u, HRmRead, i->Xin.SseReRg.src); addHRegUse(u, i->Xin.SseReRg.op == Xsse_MOV ? HRmWrite : HRmModify, i->Xin.SseReRg.dst); } return; case Xin_SseCMov: addHRegUse(u, HRmRead, i->Xin.SseCMov.src); addHRegUse(u, HRmModify, i->Xin.SseCMov.dst); return; case Xin_SseShuf: addHRegUse(u, HRmRead, i->Xin.SseShuf.src); addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst); return; default: ppX86Instr(i, False); vpanic("getRegUsage_X86Instr"); }}/* local helper */static void mapReg( HRegRemap* m, HReg* r ){ *r = lookupHRegRemap(m, *r);}void mapRegs_X86Instr ( HRegRemap* m, X86Instr* i, Bool mode64 ){ vassert(mode64 == False); switch (i->tag) { case Xin_Alu32R: mapRegs_X86RMI(m, i->Xin.Alu32R.src); mapReg(m, &i->Xin.Alu32R.dst); return; case Xin_Alu32M: mapRegs_X86RI(m, i->Xin.Alu32M.src); mapRegs_X86AMode(m, i->Xin.Alu32M.dst); return; case Xin_Sh32: mapReg(m, &i->Xin.Sh32.dst); return; case Xin_Test32: mapReg(m, &i->Xin.Test32.dst); return; case Xin_Unary32: mapReg(m, &i->Xin.Unary32.dst); return; case Xin_MulL: mapRegs_X86RM(m, i->Xin.MulL.src); return; case Xin_Div: mapRegs_X86RM(m, i->Xin.Div.src); return; case Xin_Sh3232: mapReg(m, &i->Xin.Sh3232.src); mapReg(m, &i->Xin.Sh3232.dst); return; case Xin_Push: mapRegs_X86RMI(m, i->Xin.Push.src); return; case Xin_Call: return; case Xin_Goto: mapRegs_X86RI(m, i->Xin.Goto.dst); return; case Xin_CMov32: mapRegs_X86RM(m, i->Xin.CMov32.src); mapReg(m, &i->Xin.CMov32.dst); return; case Xin_LoadEX: mapRegs_X86AMode(m, i->Xin.LoadEX.src); mapReg(m, &i->Xin.LoadEX.dst); return; case Xin_Store: mapReg(m, &i->Xin.Store.src); mapRegs_X86AMode(m, i->Xin.Store.dst); return; case Xin_Set32: mapReg(m, &i->Xin.Set32.dst); return; case Xin_Bsfr32: mapReg(m, &i->Xin.Bsfr32.src); mapReg(m, &i->Xin.Bsfr32.dst); return; case Xin_MFence: return; case Xin_FpUnary: mapReg(m, &i->Xin.FpUnary.src); mapReg(m, &i->Xin.FpUnary.dst); return; case Xin_FpBinary: mapReg(m, &i->Xin.FpBinary.srcL); mapReg(m, &i->Xin.FpBinary.srcR); mapReg(m, &i->Xin.FpBinary.dst); return; case Xin_FpLdSt: mapRegs_X86AMode(m, i->Xin.FpLdSt.addr); mapReg(m, &i->Xin.FpLdSt.reg); return; case Xin_FpLdStI: mapRegs_X86AMode(m, i->Xin.FpLdStI.addr); mapReg(m, &i->Xin.FpLdStI.reg); return; case Xin_Fp64to32: mapReg(m, &i->Xin.Fp64to32.src); mapReg(m, &i->Xin.Fp64to32.dst); return; case Xin_FpCMov: mapReg(m, &i->Xin.FpCMov.src); mapReg(m, &i->Xin.FpCMov.dst); return; case Xin_FpLdCW: mapRegs_X86AMode(m, i->Xin.FpLdCW.addr); return; case Xin_FpStSW_AX: return; case Xin_FpCmp: mapReg(m, &i->Xin.FpCmp.srcL); mapReg(m, &i->Xin.FpCmp.srcR); mapReg(m, &i->Xin.FpCmp.dst); return; case Xin_SseConst: mapReg(m, &i->Xin.SseConst.dst); return; case Xin_SseLdSt: mapReg(m, &i->Xin.SseLdSt.reg); mapRegs_X86AMode(m, i->Xin.SseLdSt.addr); break; case Xin_SseLdzLO: mapReg(m, &i->Xin.SseLdzLO.reg); mapRegs_X86AMode(m, i->Xin.SseLdzLO.addr); break; case Xin_Sse32Fx4: mapReg(m, &i->Xin.Sse32Fx4.src); mapReg(m, &i->Xin.Sse32Fx4.dst); return; case Xin_Sse32FLo: mapReg(m, &i->Xin.Sse32FLo.src); mapReg(m, &i->Xin.Sse32FLo.dst); return; case Xin_Sse64Fx2: mapReg(m, &i->Xin.Sse64Fx2.src); mapReg(m, &i->Xin.Sse64Fx2.dst); return; case Xin_Sse64FLo: mapReg(m, &i->Xin.Sse64FLo.src); mapReg(m, &i->Xin.Sse64FLo.dst); return; case Xin_SseReRg: mapReg(m, &i->Xin.SseReRg.src); mapReg(m, &i->Xin.SseReRg.dst); return; case Xin_SseCMov: mapReg(m, &i->Xin.SseCMov.src); mapReg(m, &i->Xin.SseCMov.dst); return; case Xin_SseShuf: mapReg(m, &i->Xin.SseShuf.src); mapReg(m, &i->Xin.SseShuf.dst); return; default: ppX86Instr(i, mode64); vpanic("mapRegs_X86Instr"); }}/* Figure out if i represents a reg-reg move, and if so assign the source and destination to *src and *dst. If in doubt say No. Used by the register allocator to do move coalescing. */Bool isMove_X86Instr ( X86Instr* i, HReg* src, HReg* dst ){ /* Moves between integer regs */ if (i->tag == Xin_Alu32R) { if (i->Xin.Alu32R.op != Xalu_MOV) return False; if (i->Xin.Alu32R.src->tag != Xrmi_Reg) return False; *src = i->Xin.Alu32R.src->Xrmi.Reg.reg; *dst = i->Xin.Alu32R.dst; return True; } /* Moves between FP regs */ if (i->tag == Xin_FpUnary) { if (i->Xin.FpUnary.op != Xfp_MOV) return False; *src = i->Xin.FpUnary.src; *dst = i->Xin.FpUnary.dst; return True; } if (i->tag == Xin_SseReRg) { if (i->Xin.SseReRg.op != Xsse_MOV) return False; *src = i->Xin.SseReRg.src; *dst = i->Xin.SseReRg.dst; return True; } return False;}/* Generate x86 spill/reload instructions under the direction of the register allocator. Note it's critical these don't write the condition codes. */X86Instr* genSpill_X86 ( HReg rreg, Int offsetB, Bool mode64 ){ X86AMode* am; vassert(offsetB >= 0); vassert(!hregIsVirtual(rreg)); vassert(mode64 == False); am = X86AMode_IR(offsetB, hregX86_EBP()); switch (hregClass(rreg)) { case HRcInt32: return X86Instr_Alu32M ( Xalu_MOV, X86RI_Reg(rreg), am ); case HRcFlt64: return X86Instr_FpLdSt ( False/*store*/, 8, rreg, am ); case HRcVec128: return X86Instr_SseLdSt ( False/*store*/, rreg, am ); default: ppHRegClass(hregClass(rreg)); vpanic("genSpill_X86: unimplemented regclass"); }}X86Instr* genReload_X86 ( HReg rreg, Int offsetB, Bool mode64 ){ X86AMode* am; vassert(offsetB >= 0); vassert(!hregIsVirtual(rreg)); vassert(mode64 == False); am = X86AMode_IR(offsetB, hregX86_EBP()); switch (hregClass(rreg)) { case HRcInt32: return X86Instr_Alu32R ( Xalu_MOV, X86RMI_Mem(am), rreg ); case HRcFlt64: return X86Instr_FpLdSt ( True/*load*/, 8, rreg, am ); case HRcVec128: return X86Instr_SseLdSt ( True/*load*/, rreg, am ); default: ppHRegClass(hregClass(rreg)); vpanic("genReload_X86: unimplemented regclass"); }}/* --------- The x86 assembler (bleh.) --------- */static UChar iregNo ( HReg r ){ UInt n; vassert(hregClass(r) == HRcInt32); vassert(!hregIsVirtual(r)); n = hregNumber(r); vassert(n <= 7); return toUChar(n);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -