mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
X86 SigHandler: Add support for BEXTR instruction
BEXTR is emitted for znver CPUs in recent LLVM.
This commit is contained in:
parent
3947250daa
commit
3cf8c629fa
@ -277,8 +277,11 @@ enum x64_op_t : u32
|
||||
X64OP_ADC, // lock adc [mem], ...
|
||||
X64OP_SUB, // lock sub [mem], ...
|
||||
X64OP_SBB, // lock sbb [mem], ...
|
||||
X64OP_BEXTR,
|
||||
};
|
||||
|
||||
static thread_local x64_reg_t s_tls_reg3{};
|
||||
|
||||
void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz& out_size, usz& out_length)
|
||||
{
|
||||
// simple analysis of x64 code allows to reinterpret MOV or other instructions in any desired way
|
||||
@ -739,10 +742,12 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz
|
||||
const u8 vopm = op1 == 0xc5 ? 1 : op2 & 0x1f;
|
||||
const u8 vop1 = op1 == 0xc5 ? op3 : code[2];
|
||||
const u8 vlen = (opx & 0x4) ? 32 : 16;
|
||||
//const u8 vreg = (~opx >> 3) & 0xf;
|
||||
const u8 vreg = (~opx >> 3) & 0xf;
|
||||
out_length += op1 == 0xc5 ? 2 : 3;
|
||||
code += op1 == 0xc5 ? 2 : 3;
|
||||
|
||||
s_tls_reg3 = x64_reg_t{vreg};
|
||||
|
||||
if (vopm == 0x1) switch (vop1) // Implied leading byte 0x0F
|
||||
{
|
||||
case 0x11:
|
||||
@ -772,6 +777,22 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, usz
|
||||
}
|
||||
}
|
||||
|
||||
if (vopm == 0x2) switch (vop1) // Implied leading bytes 0x0F 0x38
|
||||
{
|
||||
case 0xf7:
|
||||
{
|
||||
if (!repe && !repne && vlen == 16) // BEXTR r32,mem,r32
|
||||
{
|
||||
out_op = X64OP_BEXTR;
|
||||
out_reg = get_modRM_reg_xmm(code, rex);
|
||||
out_size = opx & 0x80 ? 8 : 4;
|
||||
out_length += get_modRM_size(code);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0xc6:
|
||||
@ -1367,6 +1388,37 @@ bool handle_access_violation(u32 addr, bool is_writing, ucontext_t* context) noe
|
||||
|
||||
break;
|
||||
}
|
||||
case X64OP_BEXTR:
|
||||
{
|
||||
u32 value;
|
||||
if (is_writing || !thread->read_reg(addr, value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
value = stx::se_storage<u32>::swap(value);
|
||||
|
||||
u64 ctrl;
|
||||
if (!get_x64_reg_value(context, s_tls_reg3, d_size, i_size, ctrl))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
u8 start = ctrl & 0xff;
|
||||
u8 _len = (ctrl & 0xff00) >> 8;
|
||||
if (_len > 32)
|
||||
_len = 32;
|
||||
if (start > 32)
|
||||
start = 32;
|
||||
value = (u64{value} >> start) & ~(u64{umax} << _len);
|
||||
|
||||
if (!put_x64_reg_value(context, reg, d_size, value) || !set_x64_cmp_flags(context, d_size, value, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case X64OP_STORE:
|
||||
case X64OP_STORE_BE:
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user