ir: Implement GetGEFlags, SetGEFlags
This commit is contained in:
parent
e7d02a5439
commit
b6f7b8babd
6 changed files with 48 additions and 0 deletions
|
@ -278,6 +278,31 @@ void EmitX64::EmitOrQFlag(IR::Block&, IR::Inst* inst) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitGetGEFlags(IR::Block&, IR::Inst* inst) {
|
||||||
|
Xbyak::Reg32 result = reg_alloc.DefGpr(inst).cvt32();
|
||||||
|
code->mov(result, MJitStateCpsr());
|
||||||
|
code->shr(result, 16);
|
||||||
|
code->and_(result, 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitX64::EmitSetGEFlags(IR::Block&, IR::Inst* inst) {
|
||||||
|
constexpr size_t flag_bit = 16;
|
||||||
|
constexpr u32 flag_mask = 0xFu << flag_bit;
|
||||||
|
IR::Value arg = inst->GetArg(0);
|
||||||
|
if (arg.IsImmediate()) {
|
||||||
|
u32 imm = (arg.GetU32() << flag_bit) & flag_mask;
|
||||||
|
code->and_(MJitStateCpsr(), ~flag_mask);
|
||||||
|
code->or_(MJitStateCpsr(), imm);
|
||||||
|
} else {
|
||||||
|
Xbyak::Reg32 to_store = reg_alloc.UseScratchGpr(arg).cvt32();
|
||||||
|
|
||||||
|
code->shl(to_store, flag_bit);
|
||||||
|
code->and_(to_store, flag_mask);
|
||||||
|
code->and_(MJitStateCpsr(), ~flag_mask);
|
||||||
|
code->or_(MJitStateCpsr(), to_store);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmitX64::EmitBXWritePC(IR::Block&, IR::Inst* inst) {
|
void EmitX64::EmitBXWritePC(IR::Block&, IR::Inst* inst) {
|
||||||
const u32 T_bit = 1 << 5;
|
const u32 T_bit = 1 << 5;
|
||||||
auto arg = inst->GetArg(0);
|
auto arg = inst->GetArg(0);
|
||||||
|
|
|
@ -137,6 +137,14 @@ void IREmitter::OrQFlag(const Value& value) {
|
||||||
Inst(Opcode::OrQFlag, {value});
|
Inst(Opcode::OrQFlag, {value});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value IREmitter::GetGEFlags() {
|
||||||
|
return Inst(Opcode::GetGEFlags, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
void IREmitter::SetGEFlags(const Value& value) {
|
||||||
|
Inst(Opcode::SetGEFlags, {value});
|
||||||
|
}
|
||||||
|
|
||||||
Value IREmitter::GetFpscr() {
|
Value IREmitter::GetFpscr() {
|
||||||
return Inst(Opcode::GetFpscr, {});
|
return Inst(Opcode::GetFpscr, {});
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,8 @@ public:
|
||||||
void SetCFlag(const Value& value);
|
void SetCFlag(const Value& value);
|
||||||
void SetVFlag(const Value& value);
|
void SetVFlag(const Value& value);
|
||||||
void OrQFlag(const Value& value);
|
void OrQFlag(const Value& value);
|
||||||
|
Value GetGEFlags();
|
||||||
|
void SetGEFlags(const Value& value);
|
||||||
|
|
||||||
Value GetFpscr();
|
Value GetFpscr();
|
||||||
void SetFpscr(const Value& new_fpscr);
|
void SetFpscr(const Value& new_fpscr);
|
||||||
|
|
|
@ -99,6 +99,7 @@ bool Inst::ReadsFromCPSR() const {
|
||||||
case Opcode::GetZFlag:
|
case Opcode::GetZFlag:
|
||||||
case Opcode::GetCFlag:
|
case Opcode::GetCFlag:
|
||||||
case Opcode::GetVFlag:
|
case Opcode::GetVFlag:
|
||||||
|
case Opcode::GetGEFlags:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -114,6 +115,7 @@ bool Inst::WritesToCPSR() const {
|
||||||
case Opcode::SetCFlag:
|
case Opcode::SetCFlag:
|
||||||
case Opcode::SetVFlag:
|
case Opcode::SetVFlag:
|
||||||
case Opcode::OrQFlag:
|
case Opcode::OrQFlag:
|
||||||
|
case Opcode::SetGEFlags:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -21,6 +21,8 @@ OPCODE(SetCFlag, T::Void, T::U1
|
||||||
OPCODE(GetVFlag, T::U1, )
|
OPCODE(GetVFlag, T::U1, )
|
||||||
OPCODE(SetVFlag, T::Void, T::U1 )
|
OPCODE(SetVFlag, T::Void, T::U1 )
|
||||||
OPCODE(OrQFlag, T::Void, T::U1 )
|
OPCODE(OrQFlag, T::Void, T::U1 )
|
||||||
|
OPCODE(GetGEFlags, T::U32, )
|
||||||
|
OPCODE(SetGEFlags, T::Void, T::U32 )
|
||||||
OPCODE(BXWritePC, T::Void, T::U32 )
|
OPCODE(BXWritePC, T::Void, T::U32 )
|
||||||
OPCODE(CallSupervisor, T::Void, T::U32 )
|
OPCODE(CallSupervisor, T::Void, T::U32 )
|
||||||
OPCODE(GetFpscr, T::U32, )
|
OPCODE(GetFpscr, T::U32, )
|
||||||
|
|
|
@ -30,6 +30,7 @@ void GetSetElimination(IR::Block& block) {
|
||||||
RegisterInfo z;
|
RegisterInfo z;
|
||||||
RegisterInfo c;
|
RegisterInfo c;
|
||||||
RegisterInfo v;
|
RegisterInfo v;
|
||||||
|
RegisterInfo ge;
|
||||||
} cpsr_info;
|
} cpsr_info;
|
||||||
|
|
||||||
const auto do_set = [&block](RegisterInfo& info, IR::Value value, Iterator set_inst) {
|
const auto do_set = [&block](RegisterInfo& info, IR::Value value, Iterator set_inst) {
|
||||||
|
@ -146,6 +147,14 @@ void GetSetElimination(IR::Block& block) {
|
||||||
do_get(cpsr_info.v, inst);
|
do_get(cpsr_info.v, inst);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case IR::Opcode::SetGEFlags: {
|
||||||
|
do_set(cpsr_info.ge, inst->GetArg(0), inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case IR::Opcode::GetGEFlags: {
|
||||||
|
do_get(cpsr_info.ge, inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
if (inst->ReadsFromCPSR() || inst->WritesToCPSR()) {
|
if (inst->ReadsFromCPSR() || inst->WritesToCPSR()) {
|
||||||
cpsr_info = {};
|
cpsr_info = {};
|
||||||
|
|
Loading…
Reference in a new issue