mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-11 22:08:14 +00:00
Merge in enough changes from the old Vex tree to make stage2 link, at
least. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3061
This commit is contained in:
@@ -35,22 +35,19 @@
|
||||
Basic types
|
||||
------------------------------------------------------------------ */
|
||||
|
||||
#include "libvex_basictypes.h"
|
||||
|
||||
/* VEX defines Char, UChar, Short, UShort, Int, UInt, Long, ULong,
|
||||
Addr32, Addr64, HWord, HChar, Bool, False and True. */
|
||||
|
||||
// By choosing the right types, we can get these right for 32-bit and 64-bit
|
||||
// platforms without having to do any conditional compilation or anything.
|
||||
//
|
||||
// Size in bits on: 32-bit archs 64-bit archs
|
||||
// ------------ ------------
|
||||
typedef unsigned char UChar; // 8 8
|
||||
typedef unsigned short UShort; // 16 16
|
||||
typedef unsigned int UInt; // 32 32
|
||||
typedef unsigned long UWord; // 32 64
|
||||
typedef unsigned long long ULong; // 64 64
|
||||
|
||||
typedef signed char Char; // 8 8
|
||||
typedef signed short Short; // 16 16
|
||||
typedef signed int Int; // 32 32
|
||||
typedef signed long Word; // 32 64
|
||||
typedef signed long long Long; // 64 64
|
||||
|
||||
typedef UWord Addr; // 32 64
|
||||
|
||||
@@ -59,9 +56,6 @@ typedef Word SSizeT; // 32 64
|
||||
|
||||
typedef Word OffT; // 32 64
|
||||
|
||||
typedef UChar Bool; // 8 8
|
||||
#define False ((Bool)0)
|
||||
#define True ((Bool)1)
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
Where to send bug reports to.
|
||||
|
||||
@@ -39,6 +39,9 @@
|
||||
#include "tool_arch.h" // arch-specific tool stuff
|
||||
#include "vki.h"
|
||||
|
||||
#include "libvex.h"
|
||||
#include "libvex_ir.h"
|
||||
|
||||
/*====================================================================*/
|
||||
/*=== Build options and table sizes. ===*/
|
||||
/*====================================================================*/
|
||||
@@ -572,627 +575,10 @@ extern void VG_(cpuid) ( UInt eax,
|
||||
UInt *eax_ret, UInt *ebx_ret,
|
||||
UInt *ecx_ret, UInt *edx_ret );
|
||||
|
||||
/*====================================================================*/
|
||||
/*=== UCode definition ===*/
|
||||
/*====================================================================*/
|
||||
|
||||
/* Tags which describe what operands are. Must fit into 4 bits, which
|
||||
they clearly do. */
|
||||
typedef
|
||||
enum { TempReg =0, /* virtual temp-reg */
|
||||
ArchReg =1, /* simulated integer reg */
|
||||
ArchRegS =2, /* simulated segment reg */
|
||||
RealReg =3, /* real machine's real reg */
|
||||
SpillNo =4, /* spill slot location */
|
||||
Literal =5, /* literal; .lit32 field has actual value */
|
||||
Lit16 =6, /* literal; .val[123] field has actual value */
|
||||
NoValue =7 /* operand not in use */
|
||||
}
|
||||
Tag;
|
||||
|
||||
/* Invalid register numbers (can't be negative) */
|
||||
#define INVALID_TEMPREG 999999999
|
||||
#define INVALID_REALREG 999999999
|
||||
|
||||
/* Microinstruction opcodes. */
|
||||
typedef
|
||||
enum {
|
||||
NOP, /* Null op */
|
||||
|
||||
LOCK, /* Indicate the existence of a LOCK prefix (functionally NOP) */
|
||||
|
||||
/* Moving values around */
|
||||
GET, PUT, /* simulated register <--> TempReg */
|
||||
GETF, PUTF, /* simulated %eflags <--> TempReg */
|
||||
LOAD, STORE, /* memory <--> TempReg */
|
||||
MOV, /* TempReg <--> TempReg */
|
||||
CMOV, /* Used for cmpxchg and cmov */
|
||||
|
||||
/* Arithmetic/logical ops */
|
||||
MUL, UMUL, /* Multiply */
|
||||
ADD, ADC, SUB, SBB, /* Add/subtract (w/wo carry) */
|
||||
AND, OR, XOR, NOT, /* Boolean ops */
|
||||
SHL, SHR, SAR, ROL, ROR, RCL, RCR, /* Shift/rotate (w/wo carry) */
|
||||
NEG, /* Negate */
|
||||
INC, DEC, /* Increment/decrement */
|
||||
BSWAP, /* Big-endian <--> little-endian */
|
||||
CC2VAL, /* Condition code --> 0 or 1 */
|
||||
WIDEN, /* Signed or unsigned widening */
|
||||
|
||||
/* Conditional or unconditional jump */
|
||||
JMP,
|
||||
|
||||
/* FPU ops */
|
||||
FPU, /* Doesn't touch memory */
|
||||
FPU_R, FPU_W, /* Reads/writes memory */
|
||||
|
||||
/* ------------ MMX ops ------------ */
|
||||
/* In this and the SSE encoding, bytes at higher addresses are
|
||||
held in bits [7:0] in these 16-bit words. I guess this means
|
||||
it is a big-endian encoding. */
|
||||
|
||||
/* 1 byte, no memrefs, no iregdefs, copy exactly to the
|
||||
output. Held in val1[7:0]. */
|
||||
MMX1,
|
||||
|
||||
/* 2 bytes, no memrefs, no iregdefs, copy exactly to the
|
||||
output. Held in val1[15:0]. */
|
||||
MMX2,
|
||||
|
||||
/* 3 bytes, no memrefs, no iregdefs, copy exactly to the
|
||||
output. Held in val1[15:0] and val2[7:0]. */
|
||||
MMX3,
|
||||
|
||||
/* 2 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:mod mmxreg r/m.
|
||||
Held in val1[15:0], and mod and rm are to be replaced
|
||||
at codegen time by a reference to the Temp/RealReg holding
|
||||
the address. Arg2 holds this Temp/Real Reg.
|
||||
Transfer is always at size 8.
|
||||
*/
|
||||
MMX2_MemRd,
|
||||
MMX2_MemWr,
|
||||
|
||||
/* 3 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:mod mmxreg r/m:bbbbbbbb
|
||||
Held in val1[15:0] and val2[7:0], and mod and rm are to be
|
||||
replaced at codegen time by a reference to the Temp/RealReg
|
||||
holding the address. Arg2 holds this Temp/Real Reg.
|
||||
Transfer is always at size 8.
|
||||
*/
|
||||
MMX2a1_MemRd,
|
||||
|
||||
/* 2 bytes, reads/writes an integer ("E") register. Insns of the form
|
||||
bbbbbbbb:11 mmxreg ireg.
|
||||
Held in val1[15:0], and ireg is to be replaced
|
||||
at codegen time by a reference to the relevant RealReg.
|
||||
Transfer is always at size 4. Arg2 holds this Temp/Real Reg.
|
||||
*/
|
||||
MMX2_ERegRd,
|
||||
MMX2_ERegWr,
|
||||
|
||||
/* ------------ SSE/SSE2 ops ------------ */
|
||||
/* In the following:
|
||||
|
||||
a digit N indicates the next N bytes are to be copied exactly
|
||||
to the output.
|
||||
|
||||
'a' indicates a mod-xmmreg-rm byte, where the mod-rm part is
|
||||
to be replaced at codegen time to a Temp/RealReg holding the
|
||||
address.
|
||||
|
||||
'e' indicates a byte of the form '11 xmmreg ireg', where ireg
|
||||
is read or written, and is to be replaced at codegen time by
|
||||
a reference to the relevant RealReg. 'e' because it's the E
|
||||
reg in Intel encoding parlance.
|
||||
|
||||
'g' indicates a byte of the form '11 ireg xmmreg', where ireg
|
||||
is read or written, and is to be replaced at codegen time by
|
||||
a reference to the relevant RealReg. 'g' because it's called
|
||||
G in Intel parlance. */
|
||||
|
||||
/* 3 bytes, no memrefs, no iregdefs, copy exactly to the
|
||||
output. Held in val1[15:0] and val2[7:0]. */
|
||||
SSE3,
|
||||
|
||||
/* 3 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:mod mmxreg r/m.
|
||||
Held in val1[15:0] and val2[7:0], and mod and rm are to be
|
||||
replaced at codegen time by a reference to the Temp/RealReg
|
||||
holding the address. Arg3 holds this Temp/Real Reg.
|
||||
Transfer is usually, but not always, at size 16. */
|
||||
SSE2a_MemRd,
|
||||
SSE2a_MemWr,
|
||||
|
||||
/* 4 bytes, writes an integer register. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:11 ireg bbb.
|
||||
Held in val1[15:0] and val2[7:0], and ireg is to be replaced
|
||||
at codegen time by a reference to the relevant RealReg.
|
||||
Transfer is always at size 4. Arg3 holds this Temp/Real Reg.
|
||||
*/
|
||||
SSE2g_RegWr,
|
||||
|
||||
/* 5 bytes, writes an integer register. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:11 ireg bbb :bbbbbbbb. Held in
|
||||
val1[15:0] and val2[7:0] and lit32[7:0], and ireg is to be
|
||||
replaced at codegen time by a reference to the relevant
|
||||
RealReg. Transfer is always at size 4. Arg3 holds this
|
||||
Temp/Real Reg.
|
||||
*/
|
||||
SSE2g1_RegWr,
|
||||
|
||||
/* 5 bytes, reads an integer register. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:11 bbb ireg :bbbbbbbb. Held in
|
||||
val1[15:0] and val2[7:0] and lit32[7:0], and ireg is to be
|
||||
replaced at codegen time by a reference to the relevant
|
||||
RealReg. Transfer is always at size 4. Arg3 holds this
|
||||
Temp/Real Reg.
|
||||
*/
|
||||
SSE2e1_RegRd,
|
||||
|
||||
/* 4 bytes, no memrefs, no iregdefs, copy exactly to the
|
||||
output. Held in val1[15:0] and val2[15:0]. */
|
||||
SSE4,
|
||||
|
||||
/* 4 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb:mod mmxreg r/m.
|
||||
Held in val1[15:0] and val2[15:0], and mod and rm are to be
|
||||
replaced at codegen time by a reference to the Temp/RealReg
|
||||
holding the address. Arg3 holds this Temp/Real Reg.
|
||||
Transfer is at stated size. */
|
||||
SSE3a_MemRd,
|
||||
SSE3a_MemWr,
|
||||
|
||||
/* 4 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:mod mmxreg r/m:bbbbbbbb
|
||||
Held in val1[15:0] and val2[15:0], and mod and rm are to be
|
||||
replaced at codegen time by a reference to the Temp/RealReg
|
||||
holding the address. Arg3 holds this Temp/Real Reg.
|
||||
Transfer is at stated size. */
|
||||
SSE2a1_MemRd,
|
||||
|
||||
/* 4 bytes, writes an integer register. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb:11 ireg bbb.
|
||||
Held in val1[15:0] and val2[15:0], and ireg is to be replaced
|
||||
at codegen time by a reference to the relevant RealReg.
|
||||
Transfer is always at size 4. Arg3 holds this Temp/Real Reg.
|
||||
*/
|
||||
SSE3g_RegWr,
|
||||
|
||||
/* 5 bytes, writes an integer register. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb: 11 ireg bbb :bbbbbbbb. Held in
|
||||
val1[15:0] and val2[15:0] and lit32[7:0], and ireg is to be
|
||||
replaced at codegen time by a reference to the relevant
|
||||
RealReg. Transfer is always at size 4. Arg3 holds this
|
||||
Temp/Real Reg.
|
||||
*/
|
||||
SSE3g1_RegWr,
|
||||
|
||||
/* 4 bytes, reads an integer register. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb:11 bbb ireg.
|
||||
Held in val1[15:0] and val2[15:0], and ireg is to be replaced
|
||||
at codegen time by a reference to the relevant RealReg.
|
||||
Transfer is always at size 4. Arg3 holds this Temp/Real Reg.
|
||||
*/
|
||||
SSE3e_RegRd,
|
||||
SSE3e_RegWr, /* variant that writes Ereg, not reads it */
|
||||
|
||||
/* 5 bytes, reads an integer register. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb: 11 bbb ireg :bbbbbbbb. Held in
|
||||
val1[15:0] and val2[15:0] and lit32[7:0], and ireg is to be
|
||||
replaced at codegen time by a reference to the relevant
|
||||
RealReg. Transfer is always at size 4. Arg3 holds this
|
||||
Temp/Real Reg.
|
||||
*/
|
||||
SSE3e1_RegRd,
|
||||
|
||||
/* 4 bytes, reads memory, writes an integer register, but is
|
||||
nevertheless an SSE insn. The insn is of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb:mod ireg rm where mod indicates
|
||||
memory (ie is not 11b) and ireg is the int reg written. The
|
||||
first 4 bytes are held in lit32[31:0] since there is
|
||||
insufficient space elsewhere. mod and rm are to be replaced
|
||||
at codegen time by a reference to the Temp/RealReg holding
|
||||
the address. Arg1 holds this Temp/RealReg. ireg is to be
|
||||
replaced at codegen time by a reference to the relevant
|
||||
RealReg in which the answer is to be written. Arg2 holds
|
||||
this Temp/RealReg. Transfer to the destination reg is always
|
||||
at size 4. However the memory read can be at sizes 4 or 8
|
||||
and so this is what the sz field holds. Note that the 4th
|
||||
byte of the instruction (the modrm byte) is redundant, but we
|
||||
store it anyway so as to be consistent with all other SSE
|
||||
uinstrs.
|
||||
*/
|
||||
SSE3ag_MemRd_RegWr,
|
||||
|
||||
/* 5 bytes, no memrefs, no iregdefs, copy exactly to the
|
||||
output. Held in val1[15:0], val2[15:0] and val3[7:0]. */
|
||||
SSE5,
|
||||
|
||||
/* 5 bytes, reads/writes mem. Insns of the form
|
||||
bbbbbbbb:bbbbbbbb:bbbbbbbb:mod mmxreg r/m:bbbbbbbb
|
||||
Held in val1[15:0], val2[15:0], lit32[7:0].
|
||||
mod and rm are to be replaced at codegen time by a reference
|
||||
to the Temp/RealReg holding the address. Arg3 holds this
|
||||
Temp/Real Reg. Transfer is always at size 16. */
|
||||
SSE3a1_MemRd,
|
||||
|
||||
/* ------------------------ */
|
||||
|
||||
/* Not strictly needed, but improve address calculation translations. */
|
||||
LEA1, /* reg2 := const + reg1 */
|
||||
LEA2, /* reg3 := const + reg1 + reg2 * 1,2,4 or 8 */
|
||||
|
||||
/* Hack for x86 REP insns. Jump to literal if TempReg/RealReg
|
||||
is zero. */
|
||||
JIFZ,
|
||||
|
||||
/* Advance the simulated %eip by some small (< 128) number. */
|
||||
INCEIP,
|
||||
|
||||
/* Dealing with segment registers */
|
||||
GETSEG, PUTSEG, /* simulated segment register <--> TempReg */
|
||||
USESEG, /* (LDT/GDT index, virtual addr) --> linear addr */
|
||||
|
||||
/* Not for translating x86 calls -- only to call helpers */
|
||||
CALLM_S, CALLM_E, /* Mark start/end of CALLM push/pop sequence */
|
||||
PUSH, POP, CLEAR, /* Add/remove/zap args for helpers */
|
||||
CALLM, /* Call assembly-code helper */
|
||||
|
||||
/* Not for translating x86 calls -- only to call C helper functions of
|
||||
up to three arguments (or two if the functions has a return value).
|
||||
Arguments and return value must be word-sized. More arguments can
|
||||
be faked with global variables (eg. use VG_(lit_to_globvar)()).
|
||||
|
||||
Seven possibilities: 'arg[123]' show where args go, 'ret' shows
|
||||
where return value goes (if present).
|
||||
|
||||
CCALL(-, -, - ) void f(void)
|
||||
CCALL(arg1, -, - ) void f(UInt arg1)
|
||||
CCALL(arg1, arg2, - ) void f(UInt arg1, UInt arg2)
|
||||
CCALL(arg1, arg2, arg3) void f(UInt arg1, UInt arg2, UInt arg3)
|
||||
CCALL(-, -, ret ) UInt f(UInt)
|
||||
CCALL(arg1, -, ret ) UInt f(UInt arg1)
|
||||
CCALL(arg1, arg2, ret ) UInt f(UInt arg1, UInt arg2) */
|
||||
CCALL,
|
||||
|
||||
/* This opcode makes it easy for tools that extend UCode to do this to
|
||||
avoid opcode overlap:
|
||||
|
||||
enum { EU_OP1 = DUMMY_FINAL_UOPCODE + 1, ... }
|
||||
|
||||
WARNING: Do not add new opcodes after this one! They can be added
|
||||
before, though. */
|
||||
DUMMY_FINAL_UOPCODE
|
||||
}
|
||||
Opcode;
|
||||
|
||||
|
||||
/* Condition codes, using the Intel encoding. CondAlways is an extra. */
|
||||
typedef
|
||||
enum {
|
||||
CondO = 0, /* overflow */
|
||||
CondNO = 1, /* no overflow */
|
||||
CondB = 2, /* below */
|
||||
CondNB = 3, /* not below */
|
||||
CondZ = 4, /* zero */
|
||||
CondNZ = 5, /* not zero */
|
||||
CondBE = 6, /* below or equal */
|
||||
CondNBE = 7, /* not below or equal */
|
||||
CondS = 8, /* negative */
|
||||
CondNS = 9, /* not negative */
|
||||
CondP = 10, /* parity even */
|
||||
CondNP = 11, /* not parity even */
|
||||
CondL = 12, /* jump less */
|
||||
CondNL = 13, /* not less */
|
||||
CondLE = 14, /* less or equal */
|
||||
CondNLE = 15, /* not less or equal */
|
||||
CondAlways = 16 /* Jump always */
|
||||
}
|
||||
Condcode;
|
||||
|
||||
|
||||
/* Descriptions of additional properties of *unconditional* jumps. */
|
||||
typedef
|
||||
enum {
|
||||
JmpBoring=0, /* boring unconditional jump */
|
||||
JmpCall=1, /* jump due to an x86 call insn */
|
||||
JmpRet=2, /* jump due to an x86 ret insn */
|
||||
JmpSyscall=3, /* do a system call, then jump */
|
||||
JmpClientReq=4,/* do a client request, then jump */
|
||||
JmpYield=5 /* do a yield, then jump */
|
||||
}
|
||||
JmpKind;
|
||||
|
||||
|
||||
/* Flags. User-level code can only read/write O(verflow), S(ign),
|
||||
Z(ero), A(ux-carry), C(arry), P(arity), and may also write
|
||||
D(irection). That's a total of 7 flags. A FlagSet is a bitset,
|
||||
thusly:
|
||||
76543210
|
||||
DOSZACP
|
||||
and bit 7 must always be zero since it is unused.
|
||||
|
||||
Note: these Flag? values are **not** the positions in the actual
|
||||
%eflags register. */
|
||||
|
||||
typedef UChar FlagSet;
|
||||
|
||||
#define FlagD (1<<6)
|
||||
#define FlagO (1<<5)
|
||||
#define FlagS (1<<4)
|
||||
#define FlagZ (1<<3)
|
||||
#define FlagA (1<<2)
|
||||
#define FlagC (1<<1)
|
||||
#define FlagP (1<<0)
|
||||
|
||||
#define FlagsOSZACP (FlagO | FlagS | FlagZ | FlagA | FlagC | FlagP)
|
||||
#define FlagsOSZAP (FlagO | FlagS | FlagZ | FlagA | FlagP)
|
||||
#define FlagsOSZCP (FlagO | FlagS | FlagZ | FlagC | FlagP)
|
||||
#define FlagsOSACP (FlagO | FlagS | FlagA | FlagC | FlagP)
|
||||
#define FlagsSZACP ( FlagS | FlagZ | FlagA | FlagC | FlagP)
|
||||
#define FlagsSZAP ( FlagS | FlagZ | FlagA | FlagP)
|
||||
#define FlagsSZP ( FlagS | FlagZ | FlagP)
|
||||
#define FlagsZCP ( FlagZ | FlagC | FlagP)
|
||||
#define FlagsOC (FlagO | FlagC )
|
||||
#define FlagsAC ( FlagA | FlagC )
|
||||
|
||||
#define FlagsALL (FlagsOSZACP | FlagD)
|
||||
#define FlagsEmpty (FlagSet)0
|
||||
|
||||
|
||||
/* flag positions in eflags */
|
||||
#define EFlagC (1 << 0) /* carry */
|
||||
#define EFlagP (1 << 2) /* parity */
|
||||
#define EFlagA (1 << 4) /* aux carry */
|
||||
#define EFlagZ (1 << 6) /* zero */
|
||||
#define EFlagS (1 << 7) /* sign */
|
||||
#define EFlagD (1 << 10) /* direction */
|
||||
#define EFlagO (1 << 11) /* overflow */
|
||||
#define EFlagID (1 << 21) /* changable if CPUID exists */
|
||||
|
||||
/* Liveness of general purpose registers, useful for code generation.
|
||||
Reg rank order 0..N-1 corresponds to bits 0..N-1, ie. first
|
||||
reg's liveness in bit 0, last reg's in bit N-1. Note that
|
||||
these rankings don't match the Intel register ordering. */
|
||||
typedef UInt RRegSet;
|
||||
|
||||
#define ALL_RREGS_DEAD 0 /* 0000...00b */
|
||||
#define ALL_RREGS_LIVE ((1 << VG_MAX_REALREGS)-1) /* 0011...11b */
|
||||
#define UNIT_RREGSET(rank) (1 << (rank))
|
||||
|
||||
#define IS_RREG_LIVE(rank,rregs_live) (rregs_live & UNIT_RREGSET(rank))
|
||||
#define SET_RREG_LIVENESS(rank,rregs_live,b) \
|
||||
do { RRegSet unit = UNIT_RREGSET(rank); \
|
||||
if (b) rregs_live |= unit; \
|
||||
else rregs_live &= ~unit; \
|
||||
} while(0)
|
||||
|
||||
|
||||
/* A Micro (u)-instruction. */
|
||||
typedef
|
||||
struct {
|
||||
/* word 1 */
|
||||
UInt lit32; /* 32-bit literal */
|
||||
|
||||
/* word 2 */
|
||||
UShort val1; /* first operand */
|
||||
UShort val2; /* second operand */
|
||||
|
||||
/* word 3 */
|
||||
UShort val3; /* third operand */
|
||||
UChar opcode; /* opcode */
|
||||
UShort size; /* data transfer size */
|
||||
|
||||
/* word 4 */
|
||||
FlagSet flags_r; /* :: FlagSet */
|
||||
FlagSet flags_w; /* :: FlagSet */
|
||||
UChar tag1:4; /* first operand tag */
|
||||
UChar tag2:4; /* second operand tag */
|
||||
UChar tag3:4; /* third operand tag */
|
||||
UChar extra4b:4; /* Spare field, used by WIDEN for src
|
||||
-size, and by LEA2 for scale (1,2,4 or 8),
|
||||
and by JMPs for original x86 instr size */
|
||||
|
||||
/* word 5 */
|
||||
UChar cond; /* condition, for jumps */
|
||||
Bool signed_widen:1; /* signed or unsigned WIDEN ? */
|
||||
JmpKind jmpkind:3; /* additional properties of unconditional JMP */
|
||||
|
||||
/* Additional properties for UInstrs that call C functions:
|
||||
- CCALL
|
||||
- PUT (when %ESP is the target)
|
||||
- possibly tool-specific UInstrs
|
||||
*/
|
||||
UChar argc:2; /* Number of args, max 3 */
|
||||
UChar regparms_n:2; /* Number of args passed in registers */
|
||||
Bool has_ret_val:1; /* Function has return value? */
|
||||
|
||||
/* RealReg liveness; only sensical after reg alloc and liveness
|
||||
analysis done. This info is a little bit arch-specific --
|
||||
VG_MAX_REALREGS can vary on different architectures. Note that
|
||||
to use this information requires converting between register ranks
|
||||
and the Intel register numbers, using VG_(realreg_to_rank)()
|
||||
and/or VG_(rank_to_realreg)() */
|
||||
RRegSet regs_live_after:VG_MAX_REALREGS;
|
||||
}
|
||||
UInstr;
|
||||
|
||||
|
||||
typedef
|
||||
struct _UCodeBlock
|
||||
UCodeBlock;
|
||||
|
||||
extern Int VG_(get_num_instrs) (UCodeBlock* cb);
|
||||
extern Int VG_(get_num_temps) (UCodeBlock* cb);
|
||||
|
||||
extern UInstr* VG_(get_instr) (UCodeBlock* cb, Int i);
|
||||
extern UInstr* VG_(get_last_instr) (UCodeBlock* cb);
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/*=== Instrumenting UCode ===*/
|
||||
/*====================================================================*/
|
||||
|
||||
/* Maximum number of registers read or written by a single UInstruction. */
|
||||
#define VG_MAX_REGS_USED 3
|
||||
|
||||
/* Find what this instruction does to its regs, useful for
|
||||
analysis/optimisation passes. `tag' indicates whether we're considering
|
||||
TempRegs (pre-reg-alloc) or RealRegs (post-reg-alloc). `regs' is filled
|
||||
with the affected register numbers, `isWrites' parallels it and indicates
|
||||
if the reg is read or written. If a reg is read and written, it will
|
||||
appear twice in `regs'. `regs' and `isWrites' must be able to fit
|
||||
VG_MAX_REGS_USED elements. */
|
||||
extern Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites );
|
||||
|
||||
|
||||
/* Used to register helper functions to be called from generated code. A
|
||||
limited number of compact helpers can be registered; the code generated
|
||||
to call them is slightly shorter -- so register the mostly frequently
|
||||
called helpers as compact. */
|
||||
extern void VG_(register_compact_helper) ( Addr a );
|
||||
extern void VG_(register_noncompact_helper) ( Addr a );
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Virtual register allocation */
|
||||
|
||||
/* Get a new virtual register */
|
||||
extern Int VG_(get_new_temp) ( UCodeBlock* cb );
|
||||
|
||||
/* Get a new virtual shadow register */
|
||||
extern Int VG_(get_new_shadow) ( UCodeBlock* cb );
|
||||
|
||||
/* Get a virtual register's corresponding virtual shadow register */
|
||||
#define SHADOW(tempreg) ((tempreg)+1)
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Low-level UInstr builders */
|
||||
extern void VG_(new_NOP) ( UInstr* u );
|
||||
extern void VG_(new_UInstr0) ( UCodeBlock* cb, Opcode opcode, Int sz );
|
||||
extern void VG_(new_UInstr1) ( UCodeBlock* cb, Opcode opcode, Int sz,
|
||||
Tag tag1, UInt val1 );
|
||||
extern void VG_(new_UInstr2) ( UCodeBlock* cb, Opcode opcode, Int sz,
|
||||
Tag tag1, UInt val1,
|
||||
Tag tag2, UInt val2 );
|
||||
extern void VG_(new_UInstr3) ( UCodeBlock* cb, Opcode opcode, Int sz,
|
||||
Tag tag1, UInt val1,
|
||||
Tag tag2, UInt val2,
|
||||
Tag tag3, UInt val3 );
|
||||
|
||||
/* Set read/write/undefined flags. Undefined flags are treaten as written,
|
||||
but it's worth keeping them logically distinct. */
|
||||
extern void VG_(set_flag_fields) ( UCodeBlock* cb, FlagSet fr, FlagSet fw,
|
||||
FlagSet fu);
|
||||
extern void VG_(set_lit_field) ( UCodeBlock* cb, UInt lit32 );
|
||||
extern void VG_(set_ccall_fields) ( UCodeBlock* cb, Addr fn, UChar argc,
|
||||
UChar regparms_n, Bool has_ret_val );
|
||||
extern void VG_(set_cond_field) ( UCodeBlock* cb, Condcode code );
|
||||
extern void VG_(set_widen_fields) ( UCodeBlock* cb, UInt szs, Bool is_signed );
|
||||
|
||||
extern void VG_(copy_UInstr) ( UCodeBlock* cb, UInstr* instr );
|
||||
|
||||
extern Bool VG_(any_flag_use)( UInstr* u );
|
||||
|
||||
/* Macro versions of the above; just shorter to type. */
|
||||
#define uInstr0 VG_(new_UInstr0)
|
||||
#define uInstr1 VG_(new_UInstr1)
|
||||
#define uInstr2 VG_(new_UInstr2)
|
||||
#define uInstr3 VG_(new_UInstr3)
|
||||
#define uLiteral VG_(set_lit_field)
|
||||
#define uCCall VG_(set_ccall_fields)
|
||||
#define uCond VG_(set_cond_field)
|
||||
#define uWiden VG_(set_widen_fields)
|
||||
#define uFlagsRWU VG_(set_flag_fields)
|
||||
#define newTemp VG_(get_new_temp)
|
||||
#define newShadow VG_(get_new_shadow)
|
||||
|
||||
/* Refer to `the last instruction stuffed in' (can be lvalue). */
|
||||
#define LAST_UINSTR(cb) (cb)->instrs[(cb)->used-1]
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Higher-level UInstr sequence builders */
|
||||
|
||||
extern void VG_(lit_to_reg) ( UCodeBlock* cb, UInt lit, UInt t );
|
||||
extern UInt VG_(lit_to_newreg) ( UCodeBlock* cb, UInt lit );
|
||||
|
||||
#define CB_F UCodeBlock* cb, Addr f
|
||||
#define EV extern void
|
||||
#define RPn UInt regparms_n
|
||||
|
||||
/* Various CCALL builders, of the form "ccall_<args>_<retval>". 'R'
|
||||
represents a TempReg, 'L' represents a literal, '0' represents nothing
|
||||
(ie. no args, or no return value). */
|
||||
|
||||
EV VG_(ccall_0_0) ( CB_F );
|
||||
|
||||
EV VG_(ccall_R_0) ( CB_F, UInt R1, RPn );
|
||||
EV VG_(ccall_L_0) ( CB_F, UInt L1, RPn );
|
||||
EV VG_(ccall_R_R) ( CB_F, UInt R1, UInt R_ret, RPn );
|
||||
EV VG_(ccall_L_R) ( CB_F, UInt L1, UInt R_ret, RPn );
|
||||
|
||||
EV VG_(ccall_RR_0) ( CB_F, UInt R1, UInt R2, RPn );
|
||||
EV VG_(ccall_RL_0) ( CB_F, UInt R1, UInt RL, RPn );
|
||||
EV VG_(ccall_LR_0) ( CB_F, UInt L1, UInt R2, RPn );
|
||||
EV VG_(ccall_LL_0) ( CB_F, UInt L1, UInt L2, RPn );
|
||||
EV VG_(ccall_RR_R) ( CB_F, UInt R1, UInt R2, UInt R_ret, RPn );
|
||||
EV VG_(ccall_RL_R) ( CB_F, UInt R1, UInt L2, UInt R_ret, RPn );
|
||||
EV VG_(ccall_LR_R) ( CB_F, UInt L1, UInt R2, UInt R_ret, RPn );
|
||||
EV VG_(ccall_LL_R) ( CB_F, UInt L1, UInt L2, UInt R_ret, RPn );
|
||||
|
||||
EV VG_(ccall_RRR_0) ( CB_F, UInt R1, UInt R2, UInt R3, RPn );
|
||||
EV VG_(ccall_RLL_0) ( CB_F, UInt R1, UInt L2, UInt L3, RPn );
|
||||
EV VG_(ccall_LRR_0) ( CB_F, UInt L1, UInt R2, UInt R3, RPn );
|
||||
EV VG_(ccall_LLR_0) ( CB_F, UInt L1, UInt L2, UInt R3, RPn );
|
||||
EV VG_(ccall_LLL_0) ( CB_F, UInt L1, UInt L2, UInt L3, RPn );
|
||||
|
||||
#undef CB_F
|
||||
#undef EV
|
||||
#undef RPn
|
||||
|
||||
/* One way around the 3-arg C function limit is to pass args via global
|
||||
* variables... ugly, but it works. */
|
||||
void VG_(reg_to_globvar)(UCodeBlock* cb, UInt t, UInt* globvar_ptr);
|
||||
void VG_(lit_to_globvar)(UCodeBlock* cb, UInt lit, UInt* globvar_ptr);
|
||||
|
||||
|
||||
/* Old, deprecated versions of some of the helpers (DO NOT USE) */
|
||||
extern void VG_(call_helper_0_0) ( UCodeBlock* cb, Addr f);
|
||||
extern void VG_(call_helper_1_0) ( UCodeBlock* cb, Addr f, UInt arg1,
|
||||
UInt regparms_n);
|
||||
extern void VG_(call_helper_2_0) ( UCodeBlock* cb, Addr f, UInt arg1, UInt arg2,
|
||||
UInt regparms_n);
|
||||
extern void VG_(set_global_var) ( UCodeBlock* cb, Addr globvar_ptr, UInt val);
|
||||
extern void VG_(set_global_var_tempreg) ( UCodeBlock* cb, Addr globvar_ptr,
|
||||
UInt t_val);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Allocating/freeing basic blocks of UCode */
|
||||
extern UCodeBlock* VG_(setup_UCodeBlock) ( UCodeBlock* cb );
|
||||
extern void VG_(free_UCodeBlock) ( UCodeBlock* cb );
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* UCode pretty/ugly printing. Probably only useful to call from a tool
|
||||
if VG_(needs).extended_UCode == True. */
|
||||
|
||||
/* When True, all generated code is/should be printed. */
|
||||
extern Bool VG_(print_codegen);
|
||||
|
||||
/* Pretty/ugly printing functions */
|
||||
extern void VG_(pp_UCodeBlock) ( UCodeBlock* cb, Char* title );
|
||||
extern void VG_(pp_UInstr) ( Int instrNo, UInstr* u );
|
||||
extern void VG_(pp_UInstr_regs) ( Int instrNo, UInstr* u );
|
||||
extern void VG_(up_UInstr) ( Int instrNo, UInstr* u );
|
||||
extern Char* VG_(name_UOpcode) ( Bool upper, Opcode opc );
|
||||
extern Char* VG_(name_UCondcode) ( Condcode cond );
|
||||
extern void VG_(pp_UOperand) ( UInstr* u, Int operandNo,
|
||||
Int sz, Bool parens );
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Accessing archregs and their shadows */
|
||||
/* ToDo: is this still needed ? */
|
||||
extern UInt VG_(get_archreg) ( UInt archreg );
|
||||
extern UInt VG_(get_thread_archreg) ( ThreadId tid, UInt archreg );
|
||||
|
||||
@@ -1205,12 +591,7 @@ extern UInt VG_(get_thread_shadow_archreg) ( ThreadId tid, UInt archreg );
|
||||
extern void VG_(set_thread_shadow_archreg) ( ThreadId tid, UInt archreg,
|
||||
UInt val );
|
||||
|
||||
/*====================================================================*/
|
||||
/*=== Generating x86 code from UCode ===*/
|
||||
/*====================================================================*/
|
||||
|
||||
/* All this only necessary for tools with VG_(needs).extends_UCode == True. */
|
||||
|
||||
/* ToDo: FIX */
|
||||
/* This is the Intel register encoding -- integer regs. */
|
||||
#define R_EAX 0
|
||||
#define R_ECX 1
|
||||
@@ -1221,133 +602,6 @@ extern void VG_(set_thread_shadow_archreg) ( ThreadId tid, UInt archreg,
|
||||
#define R_ESI 6
|
||||
#define R_EDI 7
|
||||
|
||||
#define R_AL (0+R_EAX)
|
||||
#define R_CL (0+R_ECX)
|
||||
#define R_DL (0+R_EDX)
|
||||
#define R_BL (0+R_EBX)
|
||||
#define R_AH (4+R_EAX)
|
||||
#define R_CH (4+R_ECX)
|
||||
#define R_DH (4+R_EDX)
|
||||
#define R_BH (4+R_EBX)
|
||||
|
||||
/* This is the Intel register encoding -- segment regs. */
|
||||
#define R_ES 0
|
||||
#define R_CS 1
|
||||
#define R_SS 2
|
||||
#define R_DS 3
|
||||
#define R_FS 4
|
||||
#define R_GS 5
|
||||
|
||||
/* For pretty printing x86 code */
|
||||
extern const Char* VG_(name_of_mmx_gran) ( UChar gran );
|
||||
extern const Char* VG_(name_of_mmx_reg) ( Int mmxreg );
|
||||
extern const Char* VG_(name_of_seg_reg) ( Int sreg );
|
||||
extern const Char* VG_(name_of_int_reg) ( Int size, Int reg );
|
||||
extern const Char VG_(name_of_int_size) ( Int size );
|
||||
|
||||
/* Shorter macros for convenience */
|
||||
#define nameIReg VG_(name_of_int_reg)
|
||||
#define nameISize VG_(name_of_int_size)
|
||||
#define nameSReg VG_(name_of_seg_reg)
|
||||
#define nameMMXReg VG_(name_of_mmx_reg)
|
||||
#define nameMMXGran VG_(name_of_mmx_gran)
|
||||
#define nameXMMReg VG_(name_of_xmm_reg)
|
||||
|
||||
/* Randomly useful things */
|
||||
extern UInt VG_(extend_s_8to32) ( UInt x );
|
||||
|
||||
/* Code emitters */
|
||||
extern void VG_(emitB) ( UInt b );
|
||||
extern void VG_(emitW) ( UInt w );
|
||||
extern void VG_(emitL) ( UInt l );
|
||||
extern void VG_(new_emit) ( Bool upd_cc, FlagSet uses_flags, FlagSet sets_flags );
|
||||
|
||||
/* Finding offsets */
|
||||
extern Int VG_(helper_offset) ( Addr a );
|
||||
extern Int VG_(shadow_reg_offset) ( Int arch );
|
||||
extern Int VG_(shadow_flags_offset) ( void );
|
||||
|
||||
/* Convert reg ranks <-> Intel register ordering, for using register
|
||||
liveness information. */
|
||||
extern Int VG_(realreg_to_rank) ( Int realreg );
|
||||
extern Int VG_(rank_to_realreg) ( Int rank );
|
||||
|
||||
/* Call a subroutine. Does no argument passing, stack manipulations, etc. */
|
||||
extern void VG_(synth_call) ( Bool ensure_shortform, Int word_offset,
|
||||
Bool upd_cc, FlagSet use_flags, FlagSet set_flags );
|
||||
|
||||
/* For calling C functions -- saves caller save regs, pushes args, calls,
|
||||
clears the stack, restores caller save regs. `fn' must be registered in
|
||||
the baseBlock first. Acceptable tags are RealReg and Literal. Optimises
|
||||
things, eg. by not preserving non-live caller-save registers.
|
||||
|
||||
WARNING: a UInstr should *not* be translated with synth_ccall() followed
|
||||
by some other x86 assembly code; this will invalidate the results of
|
||||
vg_realreg_liveness_analysis() and everything will fall over. */
|
||||
extern void VG_(synth_ccall) ( Addr fn, Int argc, Int regparms_n, UInt argv[],
|
||||
Tag tagv[], Int ret_reg,
|
||||
RRegSet regs_live_before,
|
||||
RRegSet regs_live_after );
|
||||
|
||||
/* Addressing modes */
|
||||
extern void VG_(emit_amode_offregmem_reg)( Int off, Int regmem, Int reg );
|
||||
extern void VG_(emit_amode_ereg_greg) ( Int e_reg, Int g_reg );
|
||||
|
||||
/* v-size (4, or 2 with OSO) insn emitters */
|
||||
extern void VG_(emit_movv_offregmem_reg) ( Int sz, Int off, Int areg, Int reg );
|
||||
extern void VG_(emit_movv_reg_offregmem) ( Int sz, Int reg, Int off, Int areg );
|
||||
extern void VG_(emit_movv_reg_reg) ( Int sz, Int reg1, Int reg2 );
|
||||
extern void VG_(emit_nonshiftopv_lit_reg)( Bool upd_cc, Int sz, Opcode opc, UInt lit,
|
||||
Int reg );
|
||||
extern void VG_(emit_shiftopv_lit_reg) ( Bool upd_cc, Int sz, Opcode opc, UInt lit,
|
||||
Int reg );
|
||||
extern void VG_(emit_nonshiftopv_reg_reg)( Bool upd_cc, Int sz, Opcode opc,
|
||||
Int reg1, Int reg2 );
|
||||
extern void VG_(emit_movv_lit_reg) ( Int sz, UInt lit, Int reg );
|
||||
extern void VG_(emit_unaryopv_reg) ( Bool upd_cc, Int sz, Opcode opc, Int reg );
|
||||
extern void VG_(emit_pushv_reg) ( Int sz, Int reg );
|
||||
extern void VG_(emit_popv_reg) ( Int sz, Int reg );
|
||||
|
||||
extern void VG_(emit_pushl_lit32) ( UInt int32 );
|
||||
extern void VG_(emit_pushl_lit8) ( Int lit8 );
|
||||
extern void VG_(emit_cmpl_zero_reg) ( Bool upd_cc, Int reg );
|
||||
extern void VG_(emit_swapl_reg_EAX) ( Int reg );
|
||||
extern void VG_(emit_movv_lit_offregmem) ( Int sz, UInt lit, Int off,
|
||||
Int memreg );
|
||||
|
||||
/* b-size (1 byte) instruction emitters */
|
||||
extern void VG_(emit_movb_lit_offregmem) ( UInt lit, Int off, Int memreg );
|
||||
extern void VG_(emit_movb_reg_offregmem) ( Int reg, Int off, Int areg );
|
||||
extern void VG_(emit_unaryopb_reg) ( Bool upd_cc, Opcode opc, Int reg );
|
||||
extern void VG_(emit_testb_lit_reg) ( Bool upd_cc, UInt lit, Int reg );
|
||||
|
||||
/* zero-extended load emitters */
|
||||
extern void VG_(emit_movzbl_offregmem_reg) ( Bool bounds, Int off, Int regmem, Int reg );
|
||||
extern void VG_(emit_movzwl_offregmem_reg) ( Bool bounds, Int off, Int areg, Int reg );
|
||||
extern void VG_(emit_movzwl_regmem_reg) ( Bool bounds, Int reg1, Int reg2 );
|
||||
|
||||
/* misc instruction emitters */
|
||||
extern void VG_(emit_call_reg) ( Int reg );
|
||||
extern void VG_(emit_add_lit_to_esp) ( Int lit );
|
||||
extern void VG_(emit_pushal) ( void );
|
||||
extern void VG_(emit_popal) ( void );
|
||||
extern void VG_(emit_AMD_prefetch_reg) ( Int reg );
|
||||
|
||||
/* jump emitters */
|
||||
extern void VG_(init_target) ( Int *tgt );
|
||||
|
||||
extern void VG_(target_back) ( Int *tgt );
|
||||
extern void VG_(target_forward) ( Int *tgt );
|
||||
extern void VG_(emit_target_delta) ( Int *tgt );
|
||||
|
||||
typedef enum {
|
||||
JP_NONE, /* no prediction */
|
||||
JP_TAKEN, /* predict taken */
|
||||
JP_NOT_TAKEN, /* predict not taken */
|
||||
} JumpPred;
|
||||
|
||||
extern void VG_(emit_jcondshort_delta) ( Bool simd_cc, Condcode cond, Int delta, JumpPred );
|
||||
extern void VG_(emit_jcondshort_target)( Bool simd_cc, Condcode cond, Int *tgt, JumpPred );
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
|
||||
@@ -40,98 +40,9 @@
|
||||
|
||||
#define REGPARM(n) __attribute__((regparm(n)))
|
||||
|
||||
// Accessors for the baseBlock
|
||||
#define R_STACK_PTR R_ESP
|
||||
#define R_FRAME_PTR R_EBP
|
||||
|
||||
#define FIRST_ARCH_REG R_EAX
|
||||
#define LAST_ARCH_REG R_EDI
|
||||
|
||||
#define N_ARCH_REGS 8
|
||||
|
||||
#define MIN_INSTR_SIZE 1
|
||||
#define MAX_INSTR_SIZE 16
|
||||
|
||||
/* Total number of integer registers available for allocation -- all of
|
||||
them except %esp (points to Valgrind's stack) and %ebp (permanently
|
||||
points at the baseBlock).
|
||||
|
||||
If you increase this you'll have to also change at least these:
|
||||
- VG_(rank_to_realreg)()
|
||||
- VG_(realreg_to_rank)()
|
||||
- ppRegsLiveness()
|
||||
- the RegsLive type (maybe -- RegsLive type must have more than
|
||||
VG_MAX_REALREGS bits)
|
||||
|
||||
You can decrease it, and performance will drop because more spills will
|
||||
occur. If you decrease it too much, everything will fall over.
|
||||
|
||||
Do not change this unless you really know what you are doing! */
|
||||
#define VG_MAX_REALREGS 6
|
||||
|
||||
|
||||
/*====================================================================*/
|
||||
/*=== Instrumenting UCode ===*/
|
||||
/*====================================================================*/
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Offsets of addresses of helper functions. A "helper" function is one
|
||||
which is called from generated code via CALLM. */
|
||||
|
||||
// XXX: eventually these should be private to the x86 part, not visible to
|
||||
// tools, and the IR should provide a better way than this to see what the
|
||||
// original instruction was.
|
||||
|
||||
extern Int VGOFF_(helper_idiv_64_32);
|
||||
extern Int VGOFF_(helper_div_64_32);
|
||||
extern Int VGOFF_(helper_idiv_32_16);
|
||||
extern Int VGOFF_(helper_div_32_16);
|
||||
extern Int VGOFF_(helper_idiv_16_8);
|
||||
extern Int VGOFF_(helper_div_16_8);
|
||||
|
||||
extern Int VGOFF_(helper_imul_32_64);
|
||||
extern Int VGOFF_(helper_mul_32_64);
|
||||
extern Int VGOFF_(helper_imul_16_32);
|
||||
extern Int VGOFF_(helper_mul_16_32);
|
||||
extern Int VGOFF_(helper_imul_8_16);
|
||||
extern Int VGOFF_(helper_mul_8_16);
|
||||
|
||||
extern Int VGOFF_(helper_CLD);
|
||||
extern Int VGOFF_(helper_STD);
|
||||
extern Int VGOFF_(helper_get_dirflag);
|
||||
|
||||
extern Int VGOFF_(helper_CLC);
|
||||
extern Int VGOFF_(helper_STC);
|
||||
extern Int VGOFF_(helper_CMC);
|
||||
|
||||
extern Int VGOFF_(helper_shldl);
|
||||
extern Int VGOFF_(helper_shldw);
|
||||
extern Int VGOFF_(helper_shrdl);
|
||||
extern Int VGOFF_(helper_shrdw);
|
||||
|
||||
extern Int VGOFF_(helper_RDTSC);
|
||||
extern Int VGOFF_(helper_CPUID);
|
||||
|
||||
extern Int VGOFF_(helper_IN);
|
||||
extern Int VGOFF_(helper_OUT);
|
||||
|
||||
extern Int VGOFF_(helper_bsfw);
|
||||
extern Int VGOFF_(helper_bsfl);
|
||||
extern Int VGOFF_(helper_bsrw);
|
||||
extern Int VGOFF_(helper_bsrl);
|
||||
|
||||
extern Int VGOFF_(helper_fstsw_AX);
|
||||
extern Int VGOFF_(helper_SAHF);
|
||||
extern Int VGOFF_(helper_LAHF);
|
||||
extern Int VGOFF_(helper_DAS);
|
||||
extern Int VGOFF_(helper_DAA);
|
||||
extern Int VGOFF_(helper_AAS);
|
||||
extern Int VGOFF_(helper_AAA);
|
||||
extern Int VGOFF_(helper_AAD);
|
||||
extern Int VGOFF_(helper_AAM);
|
||||
|
||||
extern Int VGOFF_(helper_cmpxchg8b);
|
||||
|
||||
|
||||
#endif // __X86_TOOL_ARCH_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user