dmnt-cheat: add clear to save/restore reg

This commit is contained in:
Michael Scire 2019-04-05 14:16:07 -07:00
parent 2f1f56307d
commit c7ffcad74e
2 changed files with 47 additions and 22 deletions

View file

@ -192,13 +192,13 @@ void DmntCheatVm::LogOpcode(const CheatVmOpcode *opcode) {
this->LogToDebugFile("Opcode: Save or Restore Register\n");
this->LogToDebugFile("Dst Idx: %x\n", opcode->save_restore_reg.dst_index);
this->LogToDebugFile("Src Idx: %x\n", opcode->save_restore_reg.src_index);
this->LogToDebugFile("Is Save: %d\n", opcode->save_restore_reg.is_save);
this->LogToDebugFile("Op Type: %d\n", opcode->save_restore_reg.op_type);
break;
case CheatVmOpcodeType_SaveRestoreRegisterMask:
this->LogToDebugFile("Opcode: Save or Restore Register Mask\n");
this->LogToDebugFile("Is Save: %d\n", opcode->save_restore_regmask.is_save);
this->LogToDebugFile("Op Type: %d\n", opcode->save_restore_regmask.op_type);
for (size_t i = 0; i < NumRegisters; i++) {
this->LogToDebugFile("Act[%02x]: %d\n", i, opcode->save_restore_regmask.should_save_or_restore[i]);
this->LogToDebugFile("Act[%02x]: %d\n", i, opcode->save_restore_regmask.should_operate[i]);
}
break;
default:
@ -481,22 +481,22 @@ bool DmntCheatVm::DecodeNextOpcode(CheatVmOpcode *out) {
/* C1 = opcode 0xC1 */
/* D = destination index. */
/* S = source index. */
/* x = 1 if saving a register, 0 if restoring a register. */
/* x = 2 if clearing saved value, 1 if saving a register, 0 if restoring a register. */
/* NOTE: If we add more save slots later, current encoding is backwards compatible. */
opcode.save_restore_reg.dst_index = (first_dword >> 16) & 0xF;
opcode.save_restore_reg.src_index = (first_dword >> 8) & 0xF;
opcode.save_restore_reg.is_save = ((first_dword >> 4) & 0xF) != 0;
opcode.save_restore_reg.op_type = (SaveRestoreRegisterOpType)((first_dword >> 4) & 0xF);
}
break;
case CheatVmOpcodeType_SaveRestoreRegisterMask:
{
/* C2x0XXXX */
/* C2 = opcode 0xC2 */
/* x = 1 if saving, 0 if restoring. */
/* x = 2 if clearing saved value, 1 if saving, 0 if restoring. */
/* X = 16-bit bitmask, bit i --> save or restore register i. */
opcode.save_restore_regmask.is_save = ((first_dword >> 20) & 0xF) != 0;
opcode.save_restore_regmask.op_type = (SaveRestoreRegisterOpType)((first_dword >> 20) & 0xF);
for (size_t i = 0; i < NumRegisters; i++) {
opcode.save_restore_regmask.should_save_or_restore[i] = (first_dword & (1u << i)) != 0;
opcode.save_restore_regmask.should_operate[i] = (first_dword & (1u << i)) != 0;
}
}
break;
@ -1009,25 +1009,44 @@ void DmntCheatVm::Execute(const CheatProcessMetadata *metadata) {
break;
case CheatVmOpcodeType_SaveRestoreRegister:
/* Save or restore a register. */
if (cur_opcode.save_restore_reg.is_save) {
this->saved_values[cur_opcode.save_restore_reg.dst_index] = this->registers[cur_opcode.save_restore_reg.src_index];
} else {
this->registers[cur_opcode.save_restore_reg.dst_index] = this->saved_values[cur_opcode.save_restore_reg.src_index];
switch (cur_opcode.save_restore_reg.op_type) {
case SaveRestoreRegisterOpType_Clear:
this->saved_values[cur_opcode.save_restore_reg.dst_index] = 0ul;
break;
case SaveRestoreRegisterOpType_Save:
this->saved_values[cur_opcode.save_restore_reg.dst_index] = this->registers[cur_opcode.save_restore_reg.src_index];
break;
case SaveRestoreRegisterOpType_Restore:
default:
this->registers[cur_opcode.save_restore_reg.dst_index] = this->saved_values[cur_opcode.save_restore_reg.src_index];
break;
}
break;
case CheatVmOpcodeType_SaveRestoreRegisterMask:
/* Save or restore register mask. */
if (cur_opcode.save_restore_reg.op_type == SaveRestoreRegisterOpType_Clear) {
for (size_t i = 0; i < NumRegisters; i++) {
if (cur_opcode.save_restore_regmask.should_operate[i]) {
this->saved_values[i] = 0;
}
}
break;
}
u64 *src;
u64 *dst;
if (cur_opcode.save_restore_regmask.is_save) {
src = this->registers;
dst = this->saved_values;
} else {
src = this->registers;
dst = this->saved_values;
switch (cur_opcode.save_restore_regmask.op_type) {
case SaveRestoreRegisterOpType_Save:
src = this->registers;
dst = this->saved_values;
break;
case SaveRestoreRegisterOpType_Restore:
default:
src = this->registers;
dst = this->saved_values;
break;
}
for (size_t i = 0; i < NumRegisters; i++) {
if (cur_opcode.save_restore_regmask.should_save_or_restore[i]) {
if (cur_opcode.save_restore_regmask.should_operate[i]) {
dst[i] = src[i];
}
}

View file

@ -95,6 +95,12 @@ enum CompareRegisterValueType : u32 {
CompareRegisterValueType_OtherRegister = 5,
};
enum SaveRestoreRegisterOpType : u32 {
SaveRestoreRegisterOpType_Restore = 0,
SaveRestoreRegisterOpType_Save = 1,
SaveRestoreRegisterOpType_Clear = 2,
};
union VmInt {
u8 bit8;
u16 bit16;
@ -196,12 +202,12 @@ struct BeginRegisterConditionalOpcode {
struct SaveRestoreRegisterOpcode {
u32 dst_index;
u32 src_index;
bool is_save;
SaveRestoreRegisterOpType op_type;
};
struct SaveRestoreRegisterMaskOpcode {
bool is_save;
bool should_save_or_restore[0x10];
SaveRestoreRegisterOpType op_type;
bool should_operate[0x10];
};
struct CheatVmOpcode {