diff options
| author | ptitSeb <sebastien.chev@gmail.com> | 2021-03-03 20:57:16 +0100 |
|---|---|---|
| committer | ptitSeb <sebastien.chev@gmail.com> | 2021-03-03 20:57:16 +0100 |
| commit | 12c8d4340b89bbe96123d145f0868528de102b7a (patch) | |
| tree | 654bf700096e9e19b37bc9a895cc8d20fee0a092 | |
| parent | 8ecc312f387818dbc39665e209157ec1b4c23f36 (diff) | |
| download | box64-12c8d4340b89bbe96123d145f0868528de102b7a.tar.gz box64-12c8d4340b89bbe96123d145f0868528de102b7a.zip | |
Some work on Mod/RM 64bits decoding (with RIP relative addressing)
| -rwxr-xr-x | src/emu/x64emu.c | 3 | ||||
| -rwxr-xr-x | src/emu/x64emu_private.h | 4 | ||||
| -rwxr-xr-x | src/emu/x64run.c | 60 | ||||
| -rwxr-xr-x | src/emu/x64run_private.c | 4 | ||||
| -rwxr-xr-x | src/emu/x64run_private.h | 287 |
5 files changed, 191 insertions, 167 deletions
diff --git a/src/emu/x64emu.c b/src/emu/x64emu.c index f691d780..20b187b2 100755 --- a/src/emu/x64emu.c +++ b/src/emu/x64emu.c @@ -58,9 +58,10 @@ static void internalX64Setup(x64emu_t* emu, box64context_t *context, uintptr_t s { emu->context = context; // setup cpu helpers - for (int i=0; i<8; ++i) + for (int i=0; i<16; ++i) emu->sbiidx[i] = &emu->regs[i]; emu->sbiidx[4] = &emu->zero; + emu->sbiidx[12] = &emu->zero; emu->x86emu_parity_tab = x86emu_parity_tab; emu->eflags.x32 = 0x202; // default flags? // own stack? diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h index 9b007014..ed2413f8 100755 --- a/src/emu/x64emu_private.h +++ b/src/emu/x64emu_private.h @@ -42,7 +42,7 @@ typedef struct x64emu_s { // mmx mmx_regs_t mmx[8]; // sse - sse_regs_t xmm[8]; + sse_regs_t xmm[16]; uint32_t mxcsr; // defered flags defered_flags_t df; @@ -69,7 +69,7 @@ typedef struct x64emu_s { box64context_t *context; // cpu helpers reg64_t zero; - reg64_t *sbiidx[8]; + reg64_t *sbiidx[16]; // scratch stack, used for alignement of double and 64bits ints on arm. 200 elements should be enough uint64_t scratch[200]; // local stack, do be deleted when emu is freed diff --git a/src/emu/x64run.c b/src/emu/x64run.c index 23c3a7b5..eba4c2d1 100755 --- a/src/emu/x64run.c +++ b/src/emu/x64run.c @@ -40,25 +40,26 @@ int Run(x64emu_t *emu, int step) uint64_t tmp64u, tmp64u2, tmp64u3; int32_t tmp32s, tmp32s2; int64_t tmp64s, tmp64s2; - uintptr_t ip; double d; float f; int64_t ll; sse_regs_t *opex, eax1; mmx_regs_t *opem, eam1; - int rexw, rexb, rexr, rexx; + rex_t rex; if(emu->quit) return 0; //ref opcode: http://ref.x64asm.net/geek32.html#xA1 printf_log(LOG_DEBUG, "Run X86 (%p), RIP=%p, Stack=%p\n", emu, (void*)R_RIP, emu->context->stack); -#define F8 *(uint8_t*)(ip++) -#define F8S *(int8_t*)(ip++) -#define F16 *(uint16_t*)(ip+=2, ip-2) -#define F32 *(uint32_t*)(ip+=4, ip-4) -#define F32S *(int32_t*)(ip+=4, ip-4) -#define PK(a) *(uint8_t*)(ip+a) +#define F8 *(uint8_t*)(R_RIP++) +#define F8S *(int8_t*)(R_RIP++) +#define F16 *(uint16_t*)(R_RIP+=2, R_RIP-2) +#define F32 *(uint32_t*)(R_RIP+=4, R_RIP-4) +#define F32S *(int32_t*)(R_RIP+=4, R_RIP-4) +#define F64 *(uint64_t*)(R_RIP+=8, R_RIP-8) +#define F64S *(int64_t*)(R_RIP+=8, R_RIP-8) +#define PK(a) *(uint8_t*)(R_RIP+a) #ifdef DYNAREC #define STEP if(step) goto stepout; #else @@ -66,45 +67,54 @@ int Run(x64emu_t *emu, int step) #endif x64emurun: - ip = R_RIP; //#include "modrm.h" while(1) { #ifdef HAVE_TRACE - __builtin_prefetch((void*)ip, 0, 0); + __builtin_prefetch((void*)R_RIP, 0, 0); emu->prev2_ip = emu->prev_ip; emu->prev_ip = R_RIP; - R_RIP=ip; if(my_context->dec && ( (trace_end == 0) - || ((ip >= trace_start) && (ip < trace_end))) ) - PrintTrace(emu, ip, 0); + || ((R_RIP >= trace_start) && (R_RIP < trace_end))) ) + PrintTrace(emu, R_RIP, 0); #endif opcode = F8; if(opcode>=0x40 && opcode<=0x4f) { - // REX ! - rexb = (opcode&0x1); - rexx = (opcode>>1)&1; - rexr = (opcode>>2)&1; - rexw = (opcode>>2)&1; + rex.rex = opcode; opcode = F8; - } else { - rexx = rexr = rexw = rexb = 0; - } + } else + rex.rex = 0; + switch(opcode) { + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + case 0x48: + case 0x49: + case 0x4A: + case 0x4B: + case 0x4C: + case 0x4D: + case 0x4E: + case 0x4F: /* Another REX */ + --R_RIP; + break; + default: - emu->old_ip = R_RIP; - R_RIP = ip; UnimpOpcode(emu); goto fini; } } #ifdef DYNAREC stepout: - emu->old_ip = R_RIP; - R_RIP = ip; return 0; #endif diff --git a/src/emu/x64run_private.c b/src/emu/x64run_private.c index 5ceae0a3..ab3938d0 100755 --- a/src/emu/x64run_private.c +++ b/src/emu/x64run_private.c @@ -24,8 +24,8 @@ #endif #include "x64tls.h" -#define PARITY2(x) (((emu->x64emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) -#define PARITY(x) (PARITY2((x)>>32)^PARITY2((x)&0xffffffff)) +#define PARITY32(x) (((emu->x64emu_parity_tab[(x) / 32] >> ((x) % 32)) & 1) == 0) +#define PARITY64(x) (PARITY64((x)>>32)^PARITY64((x)&0xffffffff)) #define XOR2(x) (((x) ^ ((x)>>1)) & 0x1) int32_t EXPORT my___libc_start_main(x64emu_t* emu, int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end)) diff --git a/src/emu/x64run_private.h b/src/emu/x64run_private.h index 21c7f722..7fb668f7 100755 --- a/src/emu/x64run_private.h +++ b/src/emu/x64run_private.h @@ -6,6 +6,17 @@ #include "x64emu_private.h" typedef struct x64emu_s x64emu_t; +typedef union rex_s { + uint8_t rex; + struct { + unsigned int b:1; + unsigned int x:1; + unsigned int r:1; + unsigned int w:1; + unsigned int s:4; + }; +} rex_t; + static inline uint8_t Fetch8(x64emu_t *emu) {return *(uint8_t*)(R_RIP++);} static inline int8_t Fetch8s(x64emu_t *emu) {return *(int8_t*)(R_RIP++);} static inline uint16_t Fetch16(x64emu_t *emu) @@ -62,144 +73,146 @@ static inline void Push(x64emu_t *emu, uint64_t v) // the op code definition can be found here: http://ref.x86asm.net/geek32.html -//static inline reg32_t* GetECommon(x64emu_t* emu, uint32_t m) -//{ -// if (m<=7) { -// if(m==0x4) { -// uint8_t sib = Fetch8(emu); -// uintptr_t base = ((sib&0x7)==5)?Fetch32(emu):(emu->regs[(sib&0x7)].dword[0]); // base -// base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); -// return (reg32_t*)base; -// } else if (m==0x5) { //disp32 -// return (reg32_t*)Fetch32(emu); -// } -// return (reg32_t*)(emu->regs[m].dword[0]); -// } else { -// uintptr_t base; -// if((m&7)==4) { -// uint8_t sib = Fetch8(emu); -// base = emu->regs[(sib&0x7)].dword[0]; // base -// base += (emu->sbiidx[(sib>>3)&7]->sdword[0] << (sib>>6)); -// } else { -// base = emu->regs[(m&0x7)].dword[0]; -// } -// base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu); -// return (reg32_t*)base; -// } -//} - -//static inline reg32_t* GetEb(x64emu_t *emu, uint32_t v) -//{ -// uint32_t m = v&0xC7; // filter Eb -// if(m>=0xC0) { -// int lowhigh = (m&4)>>2; -// return (reg32_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //? -// } else return GetECommon(emu, m); -//} - -//static inline reg32_t* GetEd(x64emu_t *emu, uint32_t v) -//{ -// uint32_t m = v&0xC7; // filter Ed -// if(m>=0xC0) { -// return &emu->regs[(m&0x07)]; -// } else return GetECommon(emu, m); -//} +static inline reg64_t* GetECommon(x64emu_t* emu, rex_t rex, uint8_t m) +{ + if (m<=7) { + if(m==0x4) { + uint8_t sib = Fetch8(emu); + uintptr_t base = ((sib&0x7)==5)?Fetch32(emu):(emu->regs[(sib&0x7)].q[0]+(rex.b<<4)); // base + base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<4)]->sq[0] << (sib>>6)); + return (reg64_t*)base; + } else if (m==0x5) { //disp32 + uintptr_t base = Fetch32(emu); + return (reg64_t*)(base+R_RIP); + } + return (reg64_t*)(emu->regs[m].q[0]+(rex.b<<4)); + } else { + uintptr_t base; + if((m&7)==4) { + uint8_t sib = Fetch8(emu); + base = emu->regs[(sib&0x7)+(rex.b<<4)].q[0]; // base + base += (emu->sbiidx[((sib>>3)&7)+(rex.x<<4)]->sq[0] << (sib>>6)); + } else { + base = emu->regs[(m&0x7)+(rex.b<<4)].q[0]; + } + base+=(m&0x80)?Fetch32s(emu):Fetch8s(emu); + return (reg64_t*)base; + } +} + +static inline reg64_t* GetEb(x64emu_t *emu, rex_t rex, uint8_t v) +{ + // rex ignored here + uint8_t m = v&0xC7; // filter Eb + if(m>=0xC0) { + int lowhigh = (m&4)>>2; + return (reg64_t *)(((char*)(&emu->regs[(m&0x03)]))+lowhigh); //? + } else return GetECommon(emu, rex, m); +} + +static inline reg64_t* GetEd(x64emu_t *emu, rex_t rex, uint8_t v) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &emu->regs[(m&0x07)+(rex.b<<4)]; + } else return GetECommon(emu, rex, m); +} #define GetEw GetEd -//static inline reg32_t* GetEw16(x64emu_t *emu, uint32_t v) -//{ -// uint32_t m = v&0xC7; // filter Ed -// if(m>=0xC0) { -// return &emu->regs[(m&0x07)]; -// } else { -// uint32_t base = 0; -// switch(m&7) { -// case 0: base = R_BX+R_SI; break; -// case 1: base = R_BX+R_DI; break; -// case 2: base = R_BP+R_SI; break; -// case 3: base = R_BP+R_DI; break; -// case 4: base = R_SI; break; -// case 5: base = R_DI; break; -// case 6: base = R_BP; break; -// case 7: base = R_BX; break; -// } -// switch((m>>6)&3) { -// case 0: if(m==6) base = Fetch16(emu); break; -// case 1: base += Fetch8s(emu); break; -// case 2: base += Fetch16s(emu); break; -// // case 3 is C0..C7, already dealt with -// } -// return (reg32_t*)base; -// } -//} - -//static inline reg32_t* GetEw16off(x64emu_t *emu, uint32_t v, uintptr_t offset) -//{ -// uint32_t m = v&0xC7; // filter Ed -// if(m>=0xC0) { -// return &emu->regs[(m&0x07)]; -// } else { -// uint32_t base = 0; -// switch(m&7) { -// case 0: base = R_BX+R_SI; break; -// case 1: base = R_BX+R_DI; break; -// case 2: base = R_BP+R_SI; break; -// case 3: base = R_BP+R_DI; break; -// case 4: base = R_SI; break; -// case 5: base = R_DI; break; -// case 6: base = R_BP; break; -// case 7: base = R_BX; break; -// } -// switch((m>>6)&3) { -// case 0: if(m==6) base = Fetch16(emu); break; -// case 1: base += Fetch8s(emu); break; -// case 2: base += Fetch16s(emu); break; -// // case 3 is C0..C7, already dealt with -// } -// return (reg32_t*)(base+offset); -// } -//} - -//static inline mmx_regs_t* GetEm(x64emu_t *emu, uint32_t v) -//{ -// uint32_t m = v&0xC7; // filter Ed -// if(m>=0xC0) { -// return &emu->mmx[m&0x07]; -// } else return (mmx_regs_t*)GetECommon(emu, m); -//} - -//static inline sse_regs_t* GetEx(x64emu_t *emu, uint32_t v) -//{ -// uint32_t m = v&0xC7; // filter Ed -// if(m>=0xC0) { -// return &emu->xmm[m&0x07]; -// } else return (sse_regs_t*)GetECommon(emu, m); -//} - - -//static inline reg32_t* GetG(x64emu_t *emu, uint32_t v) -//{ -// return &emu->regs[((v&0x38)>>3)]; -//} - -//static inline reg32_t* GetGb(x64emu_t *emu, uint32_t v) -//{ -// uint8_t m = (v&0x38)>>3; -// return (reg32_t*)&emu->regs[m&3].byte[m>>2]; -//} - -//static inline mmx_regs_t* GetGm(x64emu_t *emu, uint32_t v) -//{ -// uint8_t m = (v&0x38)>>3; -// return &emu->mmx[m&7]; -//} - -//static inline sse_regs_t* GetGx(x64emu_t *emu, uint32_t v) -//{ -// uint8_t m = (v&0x38)>>3; -// return &emu->xmm[m&7]; -//} +static inline reg64_t* GetEw16(x64emu_t *emu, rex_t rex, uint8_t v) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &emu->regs[(m&0x07)]; + } else { + uintptr_t base = 0; + switch(m&7) { + case 0: base = R_BX+R_SI; break; + case 1: base = R_BX+R_DI; break; + case 2: base = R_BP+R_SI; break; + case 3: base = R_BP+R_DI; break; + case 4: base = R_SI; break; + case 5: base = R_DI; break; + case 6: base = R_BP; break; + case 7: base = R_BX; break; + } + switch((m>>6)&3) { + case 0: if(m==6) base = Fetch16(emu); break; + case 1: base += Fetch8s(emu); break; + case 2: base += Fetch16s(emu); break; + // case 3 is C0..C7, already dealt with + } + return (reg64_t*)base; + } +} + +static inline reg64_t* GetEw16off(x64emu_t *emu, rex_t rex, uint8_t v, uintptr_t offset) +{ + uint32_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &emu->regs[(m&0x07)]; + } else { + uint32_t base = 0; + switch(m&7) { + case 0: base = R_BX+R_SI; break; + case 1: base = R_BX+R_DI; break; + case 2: base = R_BP+R_SI; break; + case 3: base = R_BP+R_DI; break; + case 4: base = R_SI; break; + case 5: base = R_DI; break; + case 6: base = R_BP; break; + case 7: base = R_BX; break; + } + switch((m>>6)&3) { + case 0: if(m==6) base = Fetch16(emu); break; + case 1: base += Fetch8s(emu); break; + case 2: base += Fetch16s(emu); break; + // case 3 is C0..C7, already dealt with + } + return (reg64_t*)(base+offset); + } +} + +static inline mmx_regs_t* GetEm(x64emu_t *emu, rex_t rex, uint8_t v) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &emu->mmx[m&0x07]; + } else return (mmx_regs_t*)GetECommon(emu, rex, m); +} + +static inline sse_regs_t* GetEx(x64emu_t *emu, rex_t rex, uint8_t v) +{ + uint8_t m = v&0xC7; // filter Ed + if(m>=0xC0) { + return &emu->xmm[(m&0x07)+(rex.b<<4)]; + } else return (sse_regs_t*)GetECommon(emu, rex, m); +} + + +static inline reg64_t* GetG(x64emu_t *emu, rex_t rex, uint8_t v) +{ + return &emu->regs[((v&0x38)>>3)+(rex.r<<4)]; +} + +static inline reg64_t* GetGb(x64emu_t *emu, rex_t rex, uint8_t v) +{ + uint8_t m = (v&0x38)>>3; + return (reg64_t*)&emu->regs[m&3].byte[m>>2]; +} + +static inline mmx_regs_t* GetGm(x64emu_t *emu, rex_t rex, uint8_t v) +{ + uint8_t m = (v&0x38)>>3; + return &emu->mmx[m&7]; +} + +static inline sse_regs_t* GetGx(x64emu_t *emu, rex_t rex, uint8_t v) +{ + uint8_t m = (v&0x38)>>3; + return &emu->xmm[(m&7)+(rex.r<<4)]; +} //void UpdateFlags(x64emu_t *emu); @@ -217,11 +230,11 @@ static inline void Push(x64emu_t *emu, uint64_t v) //void RunLock(x64emu_t *emu); //void RunLock66(x64emu_t *emu); -//void x86Syscall(x64emu_t *emu); +void x86Syscall(x64emu_t *emu); //void x86Int3(x64emu_t* emu); //x64emu_t* x64emu_fork(x64emu_t* e, int forktype); -//uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg); +uintptr_t GetSegmentBaseEmu(x64emu_t* emu, int seg); #define GetGSBaseEmu(emu) GetSegmentBaseEmu(emu, _GS) #define GetFSBaseEmu(emu) GetSegmentBaseEmu(emu, _FS) #define GetESBaseEmu(emu) GetSegmentBaseEmu(emu, _ES) |