mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
CMP, TEST instruction support
This commit is contained in:
parent
a19b721c26
commit
63e690ca11
@ -127,6 +127,8 @@ enum x64_op_t : u32
|
|||||||
X64OP_NONE,
|
X64OP_NONE,
|
||||||
X64OP_LOAD, // obtain and put the value into x64 register
|
X64OP_LOAD, // obtain and put the value into x64 register
|
||||||
X64OP_LOAD_BE,
|
X64OP_LOAD_BE,
|
||||||
|
X64OP_LOAD_CMP,
|
||||||
|
X64OP_LOAD_TEST,
|
||||||
X64OP_STORE, // take the value from x64 register or an immediate and use it
|
X64OP_STORE, // take the value from x64 register or an immediate and use it
|
||||||
X64OP_STORE_BE,
|
X64OP_STORE_BE,
|
||||||
X64OP_MOVS,
|
X64OP_MOVS,
|
||||||
@ -433,7 +435,7 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, siz
|
|||||||
case 4: out_op = X64OP_AND; break;
|
case 4: out_op = X64OP_AND; break;
|
||||||
case 5: out_op = X64OP_SUB; break;
|
case 5: out_op = X64OP_SUB; break;
|
||||||
case 6: out_op = X64OP_XOR; break;
|
case 6: out_op = X64OP_XOR; break;
|
||||||
default: out_op = X64OP_NONE; break; // CMP
|
default: out_op = X64OP_LOAD_CMP; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_reg = X64_IMM8;
|
out_reg = X64_IMM8;
|
||||||
@ -452,7 +454,7 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, siz
|
|||||||
case 4: out_op = X64OP_AND; break;
|
case 4: out_op = X64OP_AND; break;
|
||||||
case 5: out_op = X64OP_SUB; break;
|
case 5: out_op = X64OP_SUB; break;
|
||||||
case 6: out_op = X64OP_XOR; break;
|
case 6: out_op = X64OP_XOR; break;
|
||||||
default: out_op = X64OP_NONE; break; // CMP
|
default: out_op = X64OP_LOAD_CMP; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_reg = oso ? X64_IMM16 : X64_IMM32;
|
out_reg = oso ? X64_IMM16 : X64_IMM32;
|
||||||
@ -471,7 +473,7 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, siz
|
|||||||
case 4: out_op = X64OP_AND; break;
|
case 4: out_op = X64OP_AND; break;
|
||||||
case 5: out_op = X64OP_SUB; break;
|
case 5: out_op = X64OP_SUB; break;
|
||||||
case 6: out_op = X64OP_XOR; break;
|
case 6: out_op = X64OP_XOR; break;
|
||||||
default: out_op = X64OP_NONE; break; // CMP
|
default: out_op = X64OP_LOAD_CMP; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
out_reg = X64_IMM8;
|
out_reg = X64_IMM8;
|
||||||
@ -611,6 +613,32 @@ void decode_x64_reg_op(const u8* code, x64_op_t& out_op, x64_reg_t& out_reg, siz
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0xf6:
|
||||||
|
{
|
||||||
|
switch (auto mod_code = get_modRM_reg(code, 0))
|
||||||
|
{
|
||||||
|
case 0: out_op = X64OP_LOAD_TEST; break;
|
||||||
|
default: out_op = X64OP_NONE; break; // TODO...
|
||||||
|
}
|
||||||
|
|
||||||
|
out_reg = X64_IMM8;
|
||||||
|
out_size = 1;
|
||||||
|
out_length += get_modRM_size(code) + 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case 0xf7:
|
||||||
|
{
|
||||||
|
switch (auto mod_code = get_modRM_reg(code, 0))
|
||||||
|
{
|
||||||
|
case 0: out_op = X64OP_LOAD_TEST; break;
|
||||||
|
default: out_op = X64OP_NONE; break; // TODO...
|
||||||
|
}
|
||||||
|
|
||||||
|
out_reg = oso ? X64_IMM16 : X64_IMM32;
|
||||||
|
out_size = get_op_size(rex, oso);
|
||||||
|
out_length += get_modRM_size(code) + (oso ? 2 : 4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out_op = X64OP_NONE;
|
out_op = X64OP_NONE;
|
||||||
@ -990,9 +1018,43 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
|
|||||||
{
|
{
|
||||||
case X64OP_LOAD:
|
case X64OP_LOAD:
|
||||||
case X64OP_LOAD_BE:
|
case X64OP_LOAD_BE:
|
||||||
|
case X64OP_LOAD_CMP:
|
||||||
|
case X64OP_LOAD_TEST:
|
||||||
{
|
{
|
||||||
u32 value;
|
u32 value;
|
||||||
if (is_writing || !thread->read_reg(addr, value) || !put_x64_reg_value(context, reg, d_size, op == X64OP_LOAD ? se_storage<u32>::swap(value) : value))
|
if (is_writing || !thread->read_reg(addr, value))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op != X64OP_LOAD_BE)
|
||||||
|
{
|
||||||
|
value = se_storage<u32>::swap(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op == X64OP_LOAD_CMP)
|
||||||
|
{
|
||||||
|
u64 rvalue;
|
||||||
|
if (!get_x64_reg_value(context, reg, d_size, i_size, rvalue) || !set_x64_cmp_flags(context, d_size, value, rvalue))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op == X64OP_LOAD_TEST)
|
||||||
|
{
|
||||||
|
u64 rvalue;
|
||||||
|
if (!get_x64_reg_value(context, reg, d_size, i_size, rvalue) || !set_x64_cmp_flags(context, d_size, value & rvalue, 0))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!put_x64_reg_value(context, reg, d_size, value))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1003,7 +1065,12 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
|
|||||||
case X64OP_STORE_BE:
|
case X64OP_STORE_BE:
|
||||||
{
|
{
|
||||||
u64 reg_value;
|
u64 reg_value;
|
||||||
if (!is_writing || !get_x64_reg_value(context, reg, d_size, i_size, reg_value) || !thread->write_reg(addr, op == X64OP_STORE ? se_storage<u32>::swap((u32)reg_value) : (u32)reg_value))
|
if (!is_writing || !get_x64_reg_value(context, reg, d_size, i_size, reg_value))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thread->write_reg(addr, op == X64OP_STORE ? se_storage<u32>::swap((u32)reg_value) : (u32)reg_value))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user