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:
Julian Seward
2004-11-22 19:01:47 +00:00
parent 454ab569fe
commit b3498dd85c
24 changed files with 710 additions and 16784 deletions

View File

@@ -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.

View File

@@ -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 );
/*====================================================================*/

View File

@@ -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