能力值:
(RANK:180 )
|
-
-
5 楼
我是想試著改 SSSE3 模擬器 給AMD老CPU用的
我不知道這樣修改對不對
指令部份我用 SSEPlus 模擬的
目前測試是有bug jpg圖片顯示顏色不正常
int ssse3_emu(uint8_t *instruction, x86_saved_state_t *state, int longmode, int kernel_trap)
{
// pointer to the current byte we're working on
uint8_t *bytep = instruction;
int ins_size = 0;
int is_128 = 0, src_higher = 0, dst_higher = 0;
ssp_m128 xmmsrc, xmmdst, xmmres;
ssp_m64 mmsrc,mmdst, mmres;
/** We can get a few prefixes, in any order:
** 66 throws into 128-bit xmm mode.
** 40->4f use higher xmm registers.
**/
if(*bytep == 0x66) {
is_128 = 1;
bytep++;
ins_size++;
}
if((*bytep & 0xF0) == 0x40) {
if(*bytep & 1) src_higher = 1;
if(*bytep & 4) dst_higher = 1;
bytep++;
ins_size++;
}
if(*bytep != 0x0f) return 0;
bytep++;
ins_size++;
/* Two SSSE3 instruction prefixes. */
if((*bytep == 0x38 && bytep[1] != 0x0f) || (*bytep == 0x3a && bytep[1] == 0x0f)) {
uint8_t opcode = bytep[1];
uint8_t *modrm = &bytep[2];
unsigned char imm;
ins_size += 2; // not counting modRM byte or anything after.
if (opcode == 0x0f)
{
if ((bytep[2] > 0x3F) && (bytep[2] < 0x80))
{
imm = bytep[4]; // modrm offset + 2
}
else if ((bytep[2] > 0x7F) && (bytep[2] < 0xC0))
{
imm = bytep[7]; // modrm offset + 5
}
else
{
imm = bytep[3]; // modrm offset + 1
}
}
if(is_128)
{
int consumed = fetchoperands(modrm, src_higher, dst_higher, &xmmsrc, &xmmdst, longmode, state, kernel_trap, 1, ins_size);
ins_size += consumed;
switch(opcode) {
case 0x00: //pshufb128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_shuffle_epi8_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x01: //phaddw128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_hadd_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x02: //phaddd128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_hadd_epi32_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x03: //phaddsw128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_hadds_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x04: //pmaddubsw128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_maddubs_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x05: //phsubw128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_hsub_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x06: //phsubd128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_hsub_epi32_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x07: //phsubsw128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_hsubs_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x08: //psignb128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_sign_epi8_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x09: //psignw128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_sign_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x0A: //psignd128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_sign_epi32_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x0B: //pmulhrsw128(&xmmsrc,&xmmdst,&xmmres); break;
xmmres.i = ssp_mulhrs_epi16_SSSE3 (xmmdst.i, xmmsrc.i); break;
case 0x0F: //palignr128(&xmmsrc,&xmmdst,&xmmres,imm); ins_size++; break;
xmmres.i = ssp_alignr_epi8_SSSE3 (xmmdst.i, xmmsrc.i, imm); ins_size++; break;
case 0x1C: //pabsb128(&xmmsrc,&xmmres); break;
xmmres.i = ssp_abs_epi8_SSSE3 (xmmsrc.i); break;
case 0x1D: //pabsw128(&xmmsrc,&xmmres); break;
xmmres.i = ssp_abs_epi16_SSSE3 (xmmsrc.i); break;
case 0x1E: //pabsd128(&xmmsrc,&xmmres); break;
xmmres.i = ssp_abs_epi32_SSSE3 (xmmsrc.i); break;
default: return 0;
}
storeresult128(*modrm, dst_higher, xmmres);
}
else
{
int consumed = fetchoperands(modrm, src_higher, dst_higher, &mmsrc, &mmdst, longmode, state, kernel_trap, 0, ins_size);
ins_size += consumed;
switch(opcode) {
case 0x00: //pshufb64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_shuffle_pi8_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x01: //phaddw64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_hadd_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x02: //phaddd64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_hadd_pi32_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x03: //phaddsw64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_hadds_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x04: //pmaddubsw64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_maddubs_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x05: //phsubw64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_hsub_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x06: //phsubd64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_hsub_pi32_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x07: //phsubsw64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_hsubs_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x08: //psignb64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_sign_pi8_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x09: //psignw64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_sign_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x0A: //psignd64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_sign_pi32_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x0B: //pmulhrsw64(&mmsrc,&mmdst,&mmres); break;
mmres.m64 = ssp_mulhrs_pi16_SSSE3 (mmdst.m64, mmsrc.m64); break;
case 0x0F: //palignr64(&mmsrc,&mmdst,&mmres, imm); ins_size++; break;
mmres.m64 = ssp_alignr_pi8_SSSE3 (mmdst.m64, mmsrc.m64, imm); ins_size++; break;
case 0x1C: //pabsb64(&mmsrc,&mmres); break;
mmres.m64 = ssp_abs_pi8_SSSE3 (mmsrc.m64); break;
case 0x1D: //pabsw64(&mmsrc,&mmres); break;
mmres.m64 = ssp_abs_pi16_SSSE3 (mmsrc.m64); break;
case 0x1E: //pabsd64(&mmsrc,&mmres); break;
mmres.m64 = ssp_abs_pi32_SSSE3 (mmsrc.m64); break;
default: return 0;
}
storeresult64(*modrm, dst_higher, mmres);
}
} else {
// opcode wasn't handled here
return 0;
}
return ins_size;
}
int fetchoperands(uint8_t *ModRM, unsigned int hsrc, unsigned int hdst, void *src, void *dst, unsigned int longmode, x86_saved_state_t *saved_state, int kernel_trap, int size_128, int ins_size)
{
unsigned int num_src = *ModRM & 0x7;
unsigned int num_dst = (*ModRM >> 3) & 0x7;
unsigned int mod = *ModRM >> 6;
int consumed = 1; //modrm + 1 byte
if(hsrc) num_src += 8;
if(hdst) num_dst += 8;
if(size_128) getxmm((ssp_m128*)dst, num_dst);
else getmm((ssp_m64*)dst, num_dst);
if(mod == 3)
{
if(size_128) getxmm((ssp_m128*)src, num_src);
else getmm((ssp_m64*)src, num_src);
}
// AnV - Implemented 64-bit fetch
else if ((longmode = is_saved_state64(saved_state)))
{
uint64_t address;
// DST is always an XMM register. decode for SRC.
x86_saved_state64_t *r64 = saved_state64(saved_state);
__uint64_t reg_sel[8] = {r64->rax, r64->rcx, r64->rdx,
r64->rbx, r64->isf.rsp, r64->rbp,
r64->rsi, r64->rdi};
if(hsrc) printf("opemu error: high reg ssse\n"); // FIXME
if(num_src == 4)
{
// Special case: SIB byte used TODO fix r8-r15?
uint8_t scale = ModRM[1] >> 6;
uint8_t base = ModRM[1] & 0x7;
uint8_t index = (ModRM[1] >> 3) & 0x7;
consumed++; //modrm mode 2
// meaning of SIB depends on mod
if(mod == 0)
{
if(base == 5) printf("opemu error: mod0 disp32 not implemented\n"); // FIXME
if(index == 4) address = reg_sel[base];
else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
}
else
{
if(index == 4) address = reg_sel[base];
else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
}
}
else
{
address = reg_sel[num_src];
}
if((mod == 0) && (num_src == 5))
{
// RIP-relative dword displacement
// AnV - Warning from cast alignment fix
__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
__int32_t *ModRMCast = (__int32_t *)ModRMVal;
address = *(uint32_t*)&r64->isf.rip + *ModRMCast;
consumed += 4;
//printf("opemu adress rip: %llu \n",address);
}
if(mod == 1)
{
// byte displacement
address +=(int8_t)ModRM[consumed];
consumed++;
//printf("opemu adress byte : %llu \n",address);
}
else if(mod ==2 )
{
// dword displacement. can it be qword?
// AnV - Warning from cast alignment fix
__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
__int32_t *ModRMCast = (__int32_t *)ModRMVal;
address += *ModRMCast;
consumed += 4;
//printf("opemu adress byte : %llu \n",address);
}
// address is good now, do read and store operands.
if(kernel_trap)
{
if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)address;
else ((ssp_m64*)src)->u64 = *(uint64_t *)address;
}
else
{
//printf("xnu: da = %llx, rsp=%llx, rip=%llx\n", address, reg_sel[4], r64->isf.rip);
if(size_128) copyin(address, (char*)& ((ssp_m128*)src)->ui, 16);
else copyin(address, (char*)& ((ssp_m64*)src)->u64, 8);
}
}
// AnV - Implemented 32-bit fetch
else
{
uint32_t address;
// DST is always an XMM register. decode for SRC.
x86_saved_state32_t* r32 = saved_state32(saved_state);
uint32_t reg_sel[8] = {r32->eax, r32->ecx, r32->edx,
r32->ebx, r32->uesp, r32->ebp,
r32->esi, r32->edi};
if(hsrc) printf("opemu error: high reg ssse\n"); // FIXME
if(num_src == 4)
{
/* Special case: SIB byte used TODO fix r8-r15? */
uint8_t scale = ModRM[1] >> 6;
uint8_t base = ModRM[1] & 0x7;
uint8_t index = (ModRM[1] >> 3) & 0x7;
consumed++;
// meaning of SIB depends on mod
if(mod == 0)
{
if(base == 5) printf("opemu error: mod0 disp32 not implemented\n"); // FIXME
if(index == 4) address = reg_sel[base];
else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
}
else
{
if(index == 4) address = reg_sel[base];
else address = reg_sel[base] + (reg_sel[index] * (1<<scale));
}
}
else
{
address = reg_sel[num_src];
}
if((mod == 0) && (num_src == 5))
{
// RIP-relative dword displacement
// AnV - Warning from cast alignment fix
uint64_t ModRMVal = (uint64_t)&ModRM[consumed];
int32_t *ModRMCast = (int32_t *)ModRMVal;
address = r32->eip + *ModRMCast;
consumed += 4;
//address = r32->eip + *((int32_t*)&ModRM[consumed]);
}
if(mod == 1)
{
// byte displacement
//int32_t mods = (int32_t)ModRM[consumed];
//int8_t *Mods = (int8_t*)&mods;
address += (int8_t)ModRM[consumed];
consumed++;
// printf("opemu adress byte : %llu \n",address);
}
else if(mod == 2)
{
// dword displacement. can it be qword?
// AnV - Warning from cast alignment fix
uint64_t ModRMVal = (uint64_t)&ModRM[consumed];
int32_t *ModRMCast = (int32_t *)ModRMVal;
address += *ModRMCast;
consumed += 4;
//address += *((int32_t*)&ModRM[consumed]);
}
// address is good now, do read and store operands.
uint64_t addr = address;
if(kernel_trap)
{
if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)addr;
else ((ssp_m64*)src)->u64 = *(uint64_t *)addr;
}
else
{
//printf("xnu: da = %llx, rsp=%llx, rip=%llx\n", address, reg_sel[4], r32->eip);
if(size_128) copyin(addr, (char*) &((ssp_m128*)src)->ui, 16);
else copyin(addr, (char*) &((ssp_m64*)src)->u64, 8);
}
}
return consumed;
}
void storeresult128(uint8_t ModRM, unsigned int hdst, ssp_m128 res)
{
unsigned int num_dst = (ModRM >> 3) & 0x7;
if(hdst) num_dst += 8;
movxmm(&res, num_dst);
}
void storeresult64(uint8_t ModRM, unsigned int __unused hdst, ssp_m64 res)
{
unsigned int num_dst = (ModRM >> 3) & 0x7;
movmm(&res, num_dst);
}
/* get value from the xmm register i */
void getxmm(ssp_m128 *v, unsigned int i)
{
switch(i) {
case 0:
asm __volatile__ ("movdqu %%xmm0, %0" : "=m" (*v->s8));
break;
case 1:
asm __volatile__ ("movdqu %%xmm1, %0" : "=m" (*v->s8));
break;
case 2:
asm __volatile__ ("movdqu %%xmm2, %0" : "=m" (*v->s8));
break;
case 3:
asm __volatile__ ("movdqu %%xmm3, %0" : "=m" (*v->s8));
break;
case 4:
asm __volatile__ ("movdqu %%xmm4, %0" : "=m" (*v->s8));
break;
case 5:
asm __volatile__ ("movdqu %%xmm5, %0" : "=m" (*v->s8));
break;
case 6:
asm __volatile__ ("movdqu %%xmm6, %0" : "=m" (*v->s8));
break;
case 7:
asm __volatile__ ("movdqu %%xmm7, %0" : "=m" (*v->s8));
break;
#ifdef __x86_64__
case 8:
asm __volatile__ ("movdqu %%xmm8, %0" : "=m" (*v->s8));
break;
case 9:
asm __volatile__ ("movdqu %%xmm9, %0" : "=m" (*v->s8));
break;
case 10:
asm __volatile__ ("movdqu %%xmm10, %0" : "=m" (*v->s8));
break;
case 11:
asm __volatile__ ("movdqu %%xmm11, %0" : "=m" (*v->s8));
break;
case 12:
asm __volatile__ ("movdqu %%xmm12, %0" : "=m" (*v->s8));
break;
case 13:
asm __volatile__ ("movdqu %%xmm13, %0" : "=m" (*v->s8));
break;
case 14:
asm __volatile__ ("movdqu %%xmm14, %0" : "=m" (*v->s8));
break;
case 15:
asm __volatile__ ("movdqu %%xmm15, %0" : "=m" (*v->s8));
break;
#endif
}
}
/* get value from the mm register i */
void getmm(ssp_m64 *v, unsigned int i)
{
switch(i) {
case 0:
asm __volatile__ ("movq %%mm0, %0" : "=m" (*v->s8));
break;
case 1:
asm __volatile__ ("movq %%mm1, %0" : "=m" (*v->s8));
break;
case 2:
asm __volatile__ ("movq %%mm2, %0" : "=m" (*v->s8));
break;
case 3:
asm __volatile__ ("movq %%mm3, %0" : "=m" (*v->s8));
break;
case 4:
asm __volatile__ ("movq %%mm4, %0" : "=m" (*v->s8));
break;
case 5:
asm __volatile__ ("movq %%mm5, %0" : "=m" (*v->s8));
break;
case 6:
asm __volatile__ ("movq %%mm6, %0" : "=m" (*v->s8));
break;
case 7:
asm __volatile__ ("movq %%mm7, %0" : "=m" (*v->s8));
break;
}
}
/* move value over to xmm register i */
void movxmm(ssp_m128 *v, unsigned int i)
{
switch(i) {
case 0:
asm __volatile__ ("movdqu %0, %%xmm0" :: "m" (*v->s8) );
break;
case 1:
asm __volatile__ ("movdqu %0, %%xmm1" :: "m" (*v->s8) );
break;
case 2:
asm __volatile__ ("movdqu %0, %%xmm2" :: "m" (*v->s8) );
break;
case 3:
asm __volatile__ ("movdqu %0, %%xmm3" :: "m" (*v->s8) );
break;
case 4:
asm __volatile__ ("movdqu %0, %%xmm4" :: "m" (*v->s8) );
break;
case 5:
asm __volatile__ ("movdqu %0, %%xmm5" :: "m" (*v->s8) );
break;
case 6:
asm __volatile__ ("movdqu %0, %%xmm6" :: "m" (*v->s8) );
break;
case 7:
asm __volatile__ ("movdqu %0, %%xmm7" :: "m" (*v->s8) );
break;
#ifdef __x86_64__
case 8:
asm __volatile__ ("movdqu %0, %%xmm8" :: "m" (*v->s8) );
break;
case 9:
asm __volatile__ ("movdqu %0, %%xmm9" :: "m" (*v->s8) );
break;
case 10:
asm __volatile__ ("movdqu %0, %%xmm10" :: "m" (*v->s8) );
break;
case 11:
asm __volatile__ ("movdqu %0, %%xmm11" :: "m" (*v->s8) );
break;
case 12:
asm __volatile__ ("movdqu %0, %%xmm12" :: "m" (*v->s8) );
break;
case 13:
asm __volatile__ ("movdqu %0, %%xmm13" :: "m" (*v->s8) );
break;
case 14:
asm __volatile__ ("movdqu %0, %%xmm14" :: "m" (*v->s8) );
break;
case 15:
asm __volatile__ ("movdqu %0, %%xmm15" :: "m" (*v->s8) );
break;
#endif
}
}
/* move value over to mm register i */
void movmm(ssp_m64 *v, unsigned int i)
{
switch(i) {
case 0:
asm __volatile__ ("movq %0, %%mm0" :: "m" (*v->s8) );
break;
case 1:
asm __volatile__ ("movq %0, %%mm1" :: "m" (*v->s8) );
break;
case 2:
asm __volatile__ ("movq %0, %%mm2" :: "m" (*v->s8) );
break;
case 3:
asm __volatile__ ("movq %0, %%mm3" :: "m" (*v->s8) );
break;
case 4:
asm __volatile__ ("movq %0, %%mm4" :: "m" (*v->s8) );
break;
case 5:
asm __volatile__ ("movq %0, %%mm5" :: "m" (*v->s8) );
break;
case 6:
asm __volatile__ ("movq %0, %%mm6" :: "m" (*v->s8) );
break;
case 7:
asm __volatile__ ("movq %0, %%mm7" :: "m" (*v->s8) );
break;
}
}
|
能力值:
(RANK:180 )
|
-
-
12 楼
我重新改寫這個函數 但是我不知道這樣改是不是正確的
我按照我再 IDA Pro 上看到的opcode 為準
這個我有疑問的是 mod 0 - 2 計算 Pointer address 是不是正確的
例如:
//0 1 2 3 4 5 6 7 8
//66 0F 38 01 05 01 02 03 04
//phaddw xmm0, xmmword ptr [cs:04030201h]
offset + 6 的四個byte(字節) 是指標(指針) 的位址(地址)
兩種寫法哪個正確
1.
consumed++;
__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
__int32_t *ModRMCast = (__int32_t *)ModRMVal;
address = *(uint32_t*)&r64->isf.rip + *ModRMCast;
consumed += 3; 2.
consumed++;
address = (uint32_t)ModRM[consumed];
consumed += 3; 最後 address 的數值是 kernel_trap 裡面的 address if(kernel_trap)
{
if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)address;
else ((ssp_m64*)src)->u64 = *(uint64_t *)address;
}
else
{
//printf("xnu: da = %llx, rsp=%llx, rip=%llx\n", address, reg_sel[4], r64->isf.rip);
if(size_128) copyin(address, (char*)& ((ssp_m128*)src)->ui, 16);
else copyin(address, (char*)& ((ssp_m64*)src)->u64, 8);
}
64-bit mode
int operands(uint8_t *ModRM, uint8_t hsrc, uint8_t hdst, void *src, void *dst, unsigned int longmode, x86_saved_state_t *saved_state, int kernel_trap, int size_128, int ins_size)
{
unsigned char num_src = *ModRM & 0x7; // 1 byte + 1
unsigned char num_dst = (*ModRM >> 3) & 0x7; //8 byte + 1
unsigned char mod = *ModRM >> 6; // 40 byte + 1
int consumed = 1; //modrm + 1 byte
if(hsrc) num_src += 8;
if(hdst) num_dst += 8;
if(size_128)
getxmm((ssp_m128*)dst, num_dst);
else
getmm((ssp_m64*)dst, num_dst);
if(mod == 3)
{
if(size_128)
getxmm((ssp_m128*)src, num_src);
else
getmm((ssp_m64*)src, num_src);
}
// AnV - Implemented 64-bit fetch
else if ((longmode = is_saved_state64(saved_state)))
{
uint64_t address;
// DST is always an XMM register. decode for SRC.
x86_saved_state64_t *r64 = saved_state64(saved_state);
__uint64_t reg_sel[8] = {r64->rax, r64->rcx, r64->rdx,
r64->rbx, r64->isf.rsp, r64->rbp,
r64->rsi, r64->rdi};
if(hsrc) printf("opemu error: high reg ssse\n"); // FIXME
if (mod == 0)
{
if (num_src == 4)
{
uint8_t scale = ModRM[1] >> 6; //40 byte + 1
uint8_t base = ModRM[1] & 0x7; //1 byte + 1 reg loop
uint8_t index = (ModRM[1] >> 3) & 0x7; //8 byte + 1 reg loop
if(base == 5)
{
consumed += 2;
//modrm[1] = byte[5]
//0 1 2 3 4 5 6 7 8 9
//66 0F 38 01 04 05 04 03 02 01
//phaddw xmm0, xmmword [ds:0x1020304+rax]
//__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
//__int32_t *ModRMCast = (__int32_t *)ModRMVal;
//address = /* *(uint32_t*)&r64->isf.rip + */ *ModRMCast + reg_sel[index];
address = (uint32_t)ModRM[consumed] + reg_sel[index];
consumed += 3;
}
else
{
if (index == 4)
{
//0 1 2 3 4 5
//66 0F 38 01 04 61
//phaddw xmm0, xmmword [ds:rcx]
address = reg_sel[base];
consumed++;
}
else
{
//0 1 2 3 4 5
//66 0F 38 01 04 44
//phaddw xmm0, xmmword ptr [rsp+rax*2]
address = reg_sel[base] + (reg_sel[index] * (1<<scale));
consumed++;
}
}
}
else if (num_src == 5)
{
consumed++;
//0 1 2 3 4 5 6 7 8
//66 0F 38 01 05 01 02 03 04
//phaddw xmm0, xmmword ptr [cs:04030201h]
__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
__int32_t *ModRMCast = (__int32_t *)ModRMVal;
address = *(uint32_t*)&r64->isf.rip + *ModRMCast;
//address = (uint32_t)ModRM[consumed];
consumed += 3;
}
else
{
//0 1 2 3 4
//66 0F 38 01 03
//phaddw xmm0, xmmword [ds:rbx]
address = reg_sel[num_src];
}
}
if (mod == 1)
{
if(num_src == 4)
{
uint8_t scale = ModRM[1] >> 6; //40 byte + 1
uint8_t base = ModRM[1] & 0x7; //1 byte + 1 reg loop
uint8_t index = (ModRM[1] >> 3) & 0x7; //8 byte + 1 reg loop
if (index == 4)
{
//0 1 2 3 4 5 6
//66 0F 38 01 44 27 80
//phaddw xmm0, xmmword ptr [rdi-80h]
consumed+= 2;
address = reg_sel[base] + (int8_t)ModRM[consumed];
}
else
{
//0 1 2 3 4 5 6
//66 0F 38 01 44 44 80
//phaddw xmm0, xmmword ptr [rsp+rax*2-80h]
consumed+= 2;
address = reg_sel[base] + (reg_sel[index] * (1<<scale)) + (int8_t)ModRM[consumed];
}
}
else
{
//0 1 2 3 4 5
//66 0F 38 01 43 01
//phaddw xmm0, xmmword [ds:rbx+0x1]
consumed++;
address = reg_sel[num_src] + (int8_t)ModRM[consumed];
}
}
if (mod == 2)
{
if(num_src == 4)
{
uint8_t scale = ModRM[1] >> 6; //40 byte + 1
uint8_t base = ModRM[1] & 0x7; //1 byte + 1 reg loop
uint8_t index = (ModRM[1] >> 3) & 0x7; //8 byte + 1 reg loop
if (index == 4)
{
//0 1 2 3 4 5 6 7 8 9
//66 0F 38 01 84 20 04 03 02 01
//phaddw xmm0, xmmword ptr [rax+1020304h]
consumed += 2;
address = reg_sel[base] + (uint32_t)ModRM[consumed];
consumed += 3;
}
else
{
//0 1 2 3 4 5 6 7 8 9
//66 0F 38 01 84 44 04 03 02 01
//phaddw xmm0, xmmword ptr [rsp+rax*2+1020304h]
consumed += 2;
//__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
//__int32_t *ModRMCast = (__int32_t *)ModRMVal;
//address = reg_sel[base] + (reg_sel[index] * (1<<scale)) + /* *(uint32_t*)&r64->isf.rip + */ *ModRMCast;
address = reg_sel[base] + (reg_sel[index] * (1<<scale)) + (uint32_t)ModRM[consumed];
consumed += 3;
}
}
else
{
//0 1 2 3 4 5 6 7 8
//66 0F 38 01 83 01 02 03 04
//phaddw xmm0, xmmword [ds:rbx+0x4030201]
consumed++;
//__uint64_t ModRMVal = (__uint64_t)&ModRM[consumed];
//__int32_t *ModRMCast = (__int32_t *)ModRMVal;
//address = reg_sel[num_src] + /* *(uint32_t*)&r64->isf.rip + */ *ModRMCast;
address = reg_sel[num_src] + (uint32_t)ModRM[consumed];
consumed += 3;
}
}
// address is good now, do read and store operands.
if(kernel_trap)
{
if(size_128) ((ssp_m128*)src)->ui = *(__uint128_t *)address;
else ((ssp_m64*)src)->u64 = *(uint64_t *)address;
}
else
{
//printf("xnu: da = %llx, rsp=%llx, rip=%llx\n", address, reg_sel[4], r64->isf.rip);
if(size_128) copyin(address, (char*)& ((ssp_m128*)src)->ui, 16);
else copyin(address, (char*)& ((ssp_m64*)src)->u64, 8);
}
}
return consumed;
}
|