|
From: <sv...@va...> - 2011-05-29 09:34:11
|
Author: sewardj
Date: 2011-05-29 10:29:18 +0100 (Sun, 29 May 2011)
New Revision: 2155
Log:
x86 and amd64 back ends: when generating transfers back to the
dispatcher, generate a jump either to the unassisted (GSP unchanged,
the common case) or assisted (GSP changed, request some action before
continuing) dispatcher. This removes two instructions per dispatch
for the common case. Changes for all other targets are interface-only
changes due to change in type of the emit_XXInstr functions.
Modified:
trunk/priv/host_amd64_defs.c
trunk/priv/host_amd64_defs.h
trunk/priv/host_arm_defs.c
trunk/priv/host_arm_defs.h
trunk/priv/host_ppc_defs.c
trunk/priv/host_ppc_defs.h
trunk/priv/host_s390_defs.c
trunk/priv/host_s390_defs.h
trunk/priv/host_x86_defs.c
trunk/priv/host_x86_defs.h
trunk/priv/main_main.c
trunk/pub/libvex.h
Modified: trunk/priv/host_amd64_defs.c
===================================================================
--- trunk/priv/host_amd64_defs.c 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_amd64_defs.c 2011-05-29 09:29:18 UTC (rev 2155)
@@ -2303,7 +2303,9 @@
imperative to emit position-independent code. */
Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr* i,
- Bool mode64, void* dispatch )
+ Bool mode64,
+ void* dispatch_unassisted,
+ void* dispatch_assisted )
{
UInt /*irno,*/ opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
UInt xtra;
@@ -2716,7 +2718,11 @@
goto done;
}
- case Ain_Goto:
+ case Ain_Goto: {
+ void* dispatch_to_use = NULL;
+ vassert(dispatch_unassisted != NULL);
+ vassert(dispatch_assisted != NULL);
+
/* Use ptmp for backpatching conditional jumps. */
ptmp = NULL;
@@ -2732,7 +2738,10 @@
/* If a non-boring, set %rbp (the guest state pointer)
appropriately. Since these numbers are all small positive
integers, we can get away with "movl $N, %ebp" rather than
- the longer "movq $N, %rbp". */
+ the longer "movq $N, %rbp". Also, decide which dispatcher we
+ need to use. */
+ dispatch_to_use = dispatch_assisted;
+
/* movl $magic_number, %ebp */
switch (i->Ain.Goto.jk) {
case Ijk_ClientReq:
@@ -2771,6 +2780,7 @@
case Ijk_Ret:
case Ijk_Call:
case Ijk_Boring:
+ dispatch_to_use = dispatch_unassisted;
break;
default:
ppIRJumpKind(i->Ain.Goto.jk);
@@ -2798,19 +2808,18 @@
after the load of %rax since %rdx might be carrying the value
destined for %rax immediately prior to this Ain_Goto. */
vassert(sizeof(ULong) == sizeof(void*));
- vassert(dispatch != NULL);
- if (fitsIn32Bits(Ptr_to_ULong(dispatch))) {
+ if (fitsIn32Bits(Ptr_to_ULong(dispatch_to_use))) {
/* movl sign-extend(imm32), %rdx */
*p++ = 0x48;
*p++ = 0xC7;
*p++ = 0xC2;
- p = emit32(p, (UInt)Ptr_to_ULong(dispatch));
+ p = emit32(p, (UInt)Ptr_to_ULong(dispatch_to_use));
} else {
/* movabsq $imm64, %rdx */
*p++ = 0x48;
*p++ = 0xBA;
- p = emit64(p, Ptr_to_ULong(dispatch));
+ p = emit64(p, Ptr_to_ULong(dispatch_to_use));
}
/* jmp *%rdx */
*p++ = 0xFF;
@@ -2823,6 +2832,7 @@
*ptmp = toUChar(delta-1);
}
goto done;
+ }
case Ain_CMov64:
vassert(i->Ain.CMov64.cond != Acc_ALWAYS);
Modified: trunk/priv/host_amd64_defs.h
===================================================================
--- trunk/priv/host_amd64_defs.h 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_amd64_defs.h 2011-05-29 09:29:18 UTC (rev 2155)
@@ -734,7 +734,9 @@
extern void mapRegs_AMD64Instr ( HRegRemap*, AMD64Instr*, Bool );
extern Bool isMove_AMD64Instr ( AMD64Instr*, HReg*, HReg* );
extern Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr*,
- Bool, void* dispatch );
+ Bool,
+ void* dispatch_unassisted,
+ void* dispatch_assisted );
extern void genSpill_AMD64 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
Modified: trunk/priv/host_arm_defs.c
===================================================================
--- trunk/priv/host_arm_defs.c 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_arm_defs.c 2011-05-29 09:29:18 UTC (rev 2155)
@@ -2672,14 +2672,13 @@
Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr* i,
- Bool mode64, void* dispatch )
+ Bool mode64,
+ void* dispatch_unassisted, void* dispatch_assisted )
{
UInt* p = (UInt*)buf;
vassert(nbuf >= 32);
vassert(mode64 == False);
vassert(0 == (((HWord)buf) & 3));
- /* since we branch to lr(r13) to get back to dispatch: */
- vassert(dispatch == NULL);
switch (i->tag) {
case ARMin_Alu: {
@@ -2867,6 +2866,9 @@
ARMCondCode cond = i->ARMin.Goto.cond;
UInt rnext = iregNo(i->ARMin.Goto.gnext);
Int trc = -1;
+ /* since we branch to lr(r13) to get back to dispatch: */
+ vassert(dispatch_unassisted == NULL);
+ vassert(dispatch_assisted == NULL);
switch (jk) {
case Ijk_Ret: case Ijk_Call: case Ijk_Boring:
break; /* no need to set GST in these common cases */
Modified: trunk/priv/host_arm_defs.h
===================================================================
--- trunk/priv/host_arm_defs.h 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_arm_defs.h 2011-05-29 09:29:18 UTC (rev 2155)
@@ -960,7 +960,9 @@
extern void mapRegs_ARMInstr ( HRegRemap*, ARMInstr*, Bool );
extern Bool isMove_ARMInstr ( ARMInstr*, HReg*, HReg* );
extern Int emit_ARMInstr ( UChar* buf, Int nbuf, ARMInstr*,
- Bool, void* dispatch );
+ Bool,
+ void* dispatch_unassisted,
+ void* dispatch_assisted );
extern void genSpill_ARM ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
Modified: trunk/priv/host_ppc_defs.c
===================================================================
--- trunk/priv/host_ppc_defs.c 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_ppc_defs.c 2011-05-29 09:29:18 UTC (rev 2155)
@@ -2653,7 +2653,8 @@
code and back.
*/
Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr* i,
- Bool mode64, void* dispatch )
+ Bool mode64,
+ void* dispatch_unassisted, void* dispatch_assisted )
{
UChar* p = &buf[0];
UChar* ptmp = p;
@@ -3042,7 +3043,8 @@
UInt r_dst;
ULong imm_dst;
- vassert(dispatch == NULL);
+ vassert(dispatch_unassisted == NULL);
+ vassert(dispatch_assisted == NULL);
/* First off, if this is conditional, create a conditional
jump over the rest of it. */
Modified: trunk/priv/host_ppc_defs.h
===================================================================
--- trunk/priv/host_ppc_defs.h 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_ppc_defs.h 2011-05-29 09:29:18 UTC (rev 2155)
@@ -847,7 +847,9 @@
extern void mapRegs_PPCInstr ( HRegRemap*, PPCInstr* , Bool mode64);
extern Bool isMove_PPCInstr ( PPCInstr*, HReg*, HReg* );
extern Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr*,
- Bool mode64, void* dispatch );
+ Bool mode64,
+ void* dispatch_unassisted,
+ void* dispatch_assisted );
extern void genSpill_PPC ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offsetB, Bool mode64 );
Modified: trunk/priv/host_s390_defs.c
===================================================================
--- trunk/priv/host_s390_defs.c 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_s390_defs.c 2011-05-29 09:29:18 UTC (rev 2155)
@@ -7021,7 +7021,8 @@
Int
emit_S390Instr(UChar *buf, Int nbuf, struct s390_insn *insn,
- Bool mode64, void *dispatch)
+ Bool mode64,
+ void *dispatch_unassisted, void *dispatch_assisted)
{
UChar *end;
@@ -7087,6 +7088,8 @@
break;
case S390_INSN_BRANCH:
+ vassert(dispatch_unassisted == NULL);
+ vassert(dispatch_assisted == NULL);
end = s390_insn_branch_emit(buf, insn);
break;
Modified: trunk/priv/host_s390_defs.h
===================================================================
--- trunk/priv/host_s390_defs.h 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_s390_defs.h 2011-05-29 09:29:18 UTC (rev 2155)
@@ -474,7 +474,8 @@
void getRegUsage_S390Instr( HRegUsage *, struct s390_insn *, Bool );
void mapRegs_S390Instr ( HRegRemap *, struct s390_insn *, Bool );
Bool isMove_S390Instr ( struct s390_insn *, HReg *, HReg * );
-Int emit_S390Instr ( UChar *, Int, struct s390_insn *, Bool, void * );
+Int emit_S390Instr ( UChar *, Int, struct s390_insn *, Bool,
+ void *, void * );
void getAllocableRegs_S390( Int *, HReg **, Bool );
void genSpill_S390 ( HInstr **, HInstr **, HReg , Int , Bool );
void genReload_S390 ( HInstr **, HInstr **, HReg , Int , Bool );
Modified: trunk/priv/host_x86_defs.c
===================================================================
--- trunk/priv/host_x86_defs.c 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_x86_defs.c 2011-05-29 09:29:18 UTC (rev 2155)
@@ -1989,7 +1989,9 @@
imperative to emit position-independent code. */
Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i,
- Bool mode64, void* dispatch )
+ Bool mode64,
+ void* dispatch_unassisted,
+ void* dispatch_assisted )
{
UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
@@ -2304,7 +2306,11 @@
*p++ = toUChar(0xD0 + irno);
goto done;
- case Xin_Goto:
+ case Xin_Goto: {
+ void* dispatch_to_use = NULL;
+ vassert(dispatch_unassisted != NULL);
+ vassert(dispatch_assisted != NULL);
+
/* Use ptmp for backpatching conditional jumps. */
ptmp = NULL;
@@ -2318,7 +2324,10 @@
}
/* If a non-boring, set %ebp (the guest state pointer)
- appropriately. */
+ appropriately. Also, decide which dispatcher we need to
+ use. */
+ dispatch_to_use = dispatch_assisted;
+
/* movl $magic_number, %ebp */
switch (i->Xin.Goto.jk) {
case Ijk_ClientReq:
@@ -2363,6 +2372,7 @@
case Ijk_Ret:
case Ijk_Call:
case Ijk_Boring:
+ dispatch_to_use = dispatch_unassisted;
break;
default:
ppIRJumpKind(i->Xin.Goto.jk);
@@ -2387,10 +2397,10 @@
after the load of %eax since %edx might be carrying the value
destined for %eax immediately prior to this Xin_Goto. */
vassert(sizeof(UInt) == sizeof(void*));
- vassert(dispatch != NULL);
+ vassert(dispatch_to_use != NULL);
/* movl $imm32, %edx */
*p++ = 0xBA;
- p = emit32(p, (UInt)Ptr_to_ULong(dispatch));
+ p = emit32(p, (UInt)Ptr_to_ULong(dispatch_to_use));
/* jmp *%edx */
*p++ = 0xFF;
@@ -2403,6 +2413,7 @@
*ptmp = toUChar(delta-1);
}
goto done;
+ }
case Xin_CMov32:
vassert(i->Xin.CMov32.cond != Xcc_ALWAYS);
Modified: trunk/priv/host_x86_defs.h
===================================================================
--- trunk/priv/host_x86_defs.h 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/host_x86_defs.h 2011-05-29 09:29:18 UTC (rev 2155)
@@ -673,7 +673,9 @@
extern void mapRegs_X86Instr ( HRegRemap*, X86Instr*, Bool );
extern Bool isMove_X86Instr ( X86Instr*, HReg*, HReg* );
extern Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr*,
- Bool, void* dispatch );
+ Bool,
+ void* dispatch_unassisted,
+ void* dispatch_assisted );
extern void genSpill_X86 ( /*OUT*/HInstr** i1, /*OUT*/HInstr** i2,
HReg rreg, Int offset, Bool );
Modified: trunk/priv/main_main.c
===================================================================
--- trunk/priv/main_main.c 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/priv/main_main.c 2011-05-29 09:29:18 UTC (rev 2155)
@@ -185,7 +185,7 @@
void (*ppReg) ( HReg );
HInstrArray* (*iselSB) ( IRSB*, VexArch, VexArchInfo*,
VexAbiInfo* );
- Int (*emit) ( UChar*, Int, HInstr*, Bool, void* );
+ Int (*emit) ( UChar*, Int, HInstr*, Bool, void*, void* );
IRExpr* (*specHelper) ( HChar*, IRExpr**, IRStmt**, Int );
Bool (*preciseMemExnsFn) ( Int, Int );
@@ -252,11 +252,14 @@
ppInstr = (void(*)(HInstr*, Bool)) ppX86Instr;
ppReg = (void(*)(HReg)) ppHRegX86;
iselSB = iselSB_X86;
- emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_X86Instr;
+ emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+ emit_X86Instr;
host_is_bigendian = False;
host_word_type = Ity_I32;
vassert(are_valid_hwcaps(VexArchX86, vta->archinfo_host.hwcaps));
- vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
+ /* jump-to-dispatcher scheme */
+ vassert(vta->dispatch_unassisted != NULL);
+ vassert(vta->dispatch_assisted != NULL);
break;
case VexArchAMD64:
@@ -274,11 +277,14 @@
ppInstr = (void(*)(HInstr*, Bool)) ppAMD64Instr;
ppReg = (void(*)(HReg)) ppHRegAMD64;
iselSB = iselSB_AMD64;
- emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_AMD64Instr;
+ emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+ emit_AMD64Instr;
host_is_bigendian = False;
host_word_type = Ity_I64;
vassert(are_valid_hwcaps(VexArchAMD64, vta->archinfo_host.hwcaps));
- vassert(vta->dispatch != NULL); /* jump-to-dispatcher scheme */
+ /* jump-to-dispatcher scheme */
+ vassert(vta->dispatch_unassisted != NULL);
+ vassert(vta->dispatch_assisted != NULL);
break;
case VexArchPPC32:
@@ -293,11 +299,14 @@
ppInstr = (void(*)(HInstr*,Bool)) ppPPCInstr;
ppReg = (void(*)(HReg)) ppHRegPPC;
iselSB = iselSB_PPC;
- emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
+ emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+ emit_PPCInstr;
host_is_bigendian = True;
host_word_type = Ity_I32;
vassert(are_valid_hwcaps(VexArchPPC32, vta->archinfo_host.hwcaps));
- vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+ /* return-to-dispatcher scheme */
+ vassert(vta->dispatch_unassisted == NULL);
+ vassert(vta->dispatch_assisted == NULL);
break;
case VexArchPPC64:
@@ -312,11 +321,14 @@
ppInstr = (void(*)(HInstr*, Bool)) ppPPCInstr;
ppReg = (void(*)(HReg)) ppHRegPPC;
iselSB = iselSB_PPC;
- emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_PPCInstr;
+ emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+ emit_PPCInstr;
host_is_bigendian = True;
host_word_type = Ity_I64;
vassert(are_valid_hwcaps(VexArchPPC64, vta->archinfo_host.hwcaps));
- vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+ /* return-to-dispatcher scheme */
+ vassert(vta->dispatch_unassisted == NULL);
+ vassert(vta->dispatch_assisted == NULL);
break;
case VexArchS390X:
@@ -331,11 +343,14 @@
ppInstr = (void(*)(HInstr*, Bool)) ppS390Instr;
ppReg = (void(*)(HReg)) ppHRegS390;
iselSB = iselSB_S390;
- emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_S390Instr;
+ emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+ emit_S390Instr;
host_is_bigendian = True;
host_word_type = Ity_I64;
vassert(are_valid_hwcaps(VexArchS390X, vta->archinfo_host.hwcaps));
- vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+ /* return-to-dispatcher scheme */
+ vassert(vta->dispatch_unassisted == NULL);
+ vassert(vta->dispatch_assisted == NULL);
break;
case VexArchARM:
@@ -350,11 +365,14 @@
ppInstr = (void(*)(HInstr*, Bool)) ppARMInstr;
ppReg = (void(*)(HReg)) ppHRegARM;
iselSB = iselSB_ARM;
- emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*)) emit_ARMInstr;
+ emit = (Int(*)(UChar*,Int,HInstr*,Bool,void*,void*))
+ emit_ARMInstr;
host_is_bigendian = False;
host_word_type = Ity_I32;
vassert(are_valid_hwcaps(VexArchARM, vta->archinfo_host.hwcaps));
- vassert(vta->dispatch == NULL); /* return-to-dispatcher scheme */
+ vassert(vta->dispatch_unassisted == NULL);
+ vassert(vta->dispatch_assisted == NULL);
+ /* return-to-dispatcher scheme */
break;
default:
@@ -683,7 +701,7 @@
vex_printf("\n");
}
j = (*emit)( insn_bytes, sizeof insn_bytes, rcode->arr[i], mode64,
- vta->dispatch );
+ vta->dispatch_unassisted, vta->dispatch_assisted );
if (vex_traceflags & VEX_TRACE_ASM) {
for (k = 0; k < j; k++)
if (insn_bytes[k] < 16)
Modified: trunk/pub/libvex.h
===================================================================
--- trunk/pub/libvex.h 2011-05-28 11:06:14 UTC (rev 2154)
+++ trunk/pub/libvex.h 2011-05-29 09:29:18 UTC (rev 2155)
@@ -552,8 +552,8 @@
/* IN: debug: trace vex activity at various points */
Int traceflags;
- /* IN: address of the dispatcher entry point. Describes the
- place where generated code should jump to at the end of each
+ /* IN: address of the dispatcher entry points. Describes the
+ places where generated code should jump to at the end of each
bb.
At the end of each translation, the next guest address is
@@ -567,19 +567,26 @@
control; caller supplies this) in the following way:
- On host archs which lack a link register (x86, amd64), by a
- jump to the host address specified in 'dispatcher', which
- must be non-NULL.
+ jump to the host address specified in
+ 'dispatcher_assisted', if the guest state pointer has been
+ changed so as to request some action before the next block
+ is run, or 'dispatcher_unassisted' (the fast path), in
+ which it is assumed that the guest state pointer is
+ unchanged and we wish to continue directly with the next
+ translation. Both of these must be non-NULL.
- On host archs which have a link register (ppc32, ppc64), by
a branch to the link register (which is guaranteed to be
unchanged from whatever it was at entry to the
- translation). 'dispatch' must be NULL.
+ translation). 'dispatch_assisted' and
+ 'dispatch_unassisted' must be NULL.
The aim is to get back and forth between translations and the
dispatcher without creating memory traffic to store return
addresses.
*/
- void* dispatch;
+ void* dispatch_unassisted;
+ void* dispatch_assisted;
}
VexTranslateArgs;
|