ir: Implement GetGEFlags, SetGEFlags

This commit is contained in:
MerryMage 2016-11-23 19:44:27 +00:00
parent e7d02a5439
commit b6f7b8babd
6 changed files with 48 additions and 0 deletions

View file

@ -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);

View file

@ -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, {});
} }

View file

@ -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);

View file

@ -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:

View file

@ -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, )

View file

@ -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 = {};