A64 backend: Add Get/SetExtendedRegister and Get/SetGEFlags

This commit is contained in:
SachinVin 2019-07-14 20:44:55 +05:30 committed by xperia64
parent eacc261010
commit 83ef2b7070
2 changed files with 85 additions and 82 deletions

View File

@ -42,17 +42,17 @@ static size_t MJitStateReg(A32::Reg reg) {
return offsetof(A32JitState, Reg) + sizeof(u32) * static_cast<size_t>(reg);
}
//static size_t MJitStateExtReg(A32::ExtReg reg) {
// if (A32::IsSingleExtReg(reg)) {
// size_t index = static_cast<size_t>(reg) - static_cast<size_t>(A32::ExtReg::S0);
// return offsetof(A32JitState, ExtReg) + sizeof(u32) * index;
// }
// if (A32::IsDoubleExtReg(reg)) {
// size_t index = static_cast<size_t>(reg) - static_cast<size_t>(A32::ExtReg::D0);
// return offsetof(A32JitState, ExtReg) + sizeof(u64) * index;
// }
// ASSERT_MSG(false, "Should never happen.");
//}
static size_t MJitStateExtReg(A32::ExtReg reg) {
if (A32::IsSingleExtReg(reg)) {
size_t index = static_cast<size_t>(reg) - static_cast<size_t>(A32::ExtReg::S0);
return offsetof(A32JitState, ExtReg) + sizeof(u32) * index;
}
if (A32::IsDoubleExtReg(reg)) {
size_t index = static_cast<size_t>(reg) - static_cast<size_t>(A32::ExtReg::D0);
return offsetof(A32JitState, ExtReg) + sizeof(u64) * index;
}
ASSERT_MSG(false, "Should never happen.");
}
A32EmitContext::A32EmitContext(RegAlloc& reg_alloc, IR::Block& block) : EmitContext(reg_alloc, block) {}
@ -330,61 +330,62 @@ void A32EmitA64::EmitA32GetRegister(A32EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.DefineValue(inst, result);
}
//void A32EmitA64::EmitA32GetExtendedRegister32(A32EmitContext& ctx, IR::Inst* inst) {
// A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
// ASSERT(A32::IsSingleExtReg(reg));
//
// Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
// code.movss(result, MJitStateExtReg(reg));
// ctx.reg_alloc.DefineValue(inst, result);
//}
//
//void A32EmitA64::EmitA32GetExtendedRegister64(A32EmitContext& ctx, IR::Inst* inst) {
// A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
// ASSERT(A32::IsDoubleExtReg(reg));
//
// Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
// code.movsd(result, MJitStateExtReg(reg));
// ctx.reg_alloc.DefineValue(inst, result);
//}
void A32EmitA64::EmitA32GetExtendedRegister32(A32EmitContext& ctx, IR::Inst* inst) {
A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
ASSERT(A32::IsSingleExtReg(reg));
ARM64Reg result = ctx.reg_alloc.ScratchFpr();
code.fp_emitter.LDR(32, INDEX_UNSIGNED, result, X28, MJitStateExtReg(reg));
ctx.reg_alloc.DefineValue(inst, result);
}
void A32EmitA64::EmitA32GetExtendedRegister64(A32EmitContext& ctx, IR::Inst* inst) {
A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
ASSERT(A32::IsDoubleExtReg(reg));
ARM64Reg result = ctx.reg_alloc.ScratchFpr();
code.fp_emitter.LDR(64, INDEX_UNSIGNED, result, X28, MJitStateExtReg(reg));
ctx.reg_alloc.DefineValue(inst, result);
}
void A32EmitA64::EmitA32SetRegister(A32EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
A32::Reg reg = inst->GetArg(0).GetA32RegRef();
if (args[1].IsInFpr()) {
Arm64Gen::ARM64Reg to_store = ctx.reg_alloc.UseFpr(args[1]);
code.fp_emitter.STR(sizeof(u32), INDEX_UNSIGNED, to_store, X28, MJitStateReg(reg));
code.fp_emitter.STR(32, INDEX_UNSIGNED, to_store, X28, MJitStateReg(reg));
} else {
Arm64Gen::ARM64Reg to_store = DecodeReg(ctx.reg_alloc.UseGpr(args[1]));
code.STR(INDEX_UNSIGNED, to_store, X28, MJitStateReg(reg));
}
}
//void A32EmitA64::EmitA32SetExtendedRegister32(A32EmitContext& ctx, IR::Inst* inst) {
// auto args = ctx.reg_alloc.GetArgumentInfo(inst);
// A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
// ASSERT(A32::IsSingleExtReg(reg));
// if (args[1].IsInXmm()) {
// Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[1]);
// code.movss(MJitStateExtReg(reg), to_store);
// } else {
// Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(args[1]).cvt32();
// code.mov(MJitStateExtReg(reg), to_store);
// }
//}
//
//void A32EmitA64::EmitA32SetExtendedRegister64(A32EmitContext& ctx, IR::Inst* inst) {
// auto args = ctx.reg_alloc.GetArgumentInfo(inst);
// A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
// ASSERT(A32::IsDoubleExtReg(reg));
// if (args[1].IsInXmm()) {
// Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[1]);
// code.movsd(MJitStateExtReg(reg), to_store);
// } else {
// Xbyak::Reg64 to_store = ctx.reg_alloc.UseGpr(args[1]);
// code.mov(MJitStateExtReg(reg), to_store);
// }
//}
void A32EmitA64::EmitA32SetExtendedRegister32(A32EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
ASSERT(A32::IsSingleExtReg(reg));
if (args[1].IsInFpr()) {
ARM64Reg to_store = ctx.reg_alloc.UseFpr(args[1]);
code.fp_emitter.STR(32, INDEX_UNSIGNED, to_store, X28, MJitStateExtReg(reg));
} else {
ARM64Reg to_store = DecodeReg(ctx.reg_alloc.UseGpr(args[1]));
code.STR(INDEX_UNSIGNED, to_store, X28, MJitStateExtReg(reg));
}
}
void A32EmitA64::EmitA32SetExtendedRegister64(A32EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
A32::ExtReg reg = inst->GetArg(0).GetA32ExtRegRef();
ASSERT(A32::IsDoubleExtReg(reg));
if (args[1].IsInFpr()) {
ARM64Reg to_store = ctx.reg_alloc.UseFpr(args[1]);
code.fp_emitter.STR(64, INDEX_UNSIGNED, to_store, X28, MJitStateExtReg(reg));
}
else {
ARM64Reg to_store = ctx.reg_alloc.UseGpr(args[1]);
code.STR(INDEX_UNSIGNED, to_store, X28, MJitStateExtReg(reg));
}
}
static u32 GetCpsrImpl(A32JitState* jit_state) {
return jit_state->Cpsr();
@ -620,24 +621,23 @@ void A32EmitA64::EmitA32OrQFlag(A32EmitContext& ctx, IR::Inst* inst) {
}
}
//void A32EmitA64::EmitA32GetGEFlags(A32EmitContext& ctx, IR::Inst* inst) {
// Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
// code.movd(result, dword[r15 + offsetof(A32JitState, CPSR_ge)]);
// ctx.reg_alloc.DefineValue(inst, result);
//}
//
//void A32EmitA64::EmitA32SetGEFlags(A32EmitContext& ctx, IR::Inst* inst) {
// auto args = ctx.reg_alloc.GetArgumentInfo(inst);
// ASSERT(!args[0].IsImmediate());
//
// if (args[0].IsInXmm()) {
// Xbyak::Xmm to_store = ctx.reg_alloc.UseXmm(args[0]);
// code.movd(dword[r15 + offsetof(A32JitState, CPSR_ge)], to_store);
// } else {
// Xbyak::Reg32 to_store = ctx.reg_alloc.UseGpr(args[0]).cvt32();
// code.mov(dword[r15 + offsetof(A32JitState, CPSR_ge)], to_store);
// }
//}
void A32EmitA64::EmitA32GetGEFlags(A32EmitContext& ctx, IR::Inst* inst) {
ARM64Reg result = EncodeRegToSingle(ctx.reg_alloc.ScratchFpr());
code.LDR(INDEX_UNSIGNED, result, X28, offsetof(A32JitState, CPSR_ge));
ctx.reg_alloc.DefineValue(inst, result);
}
void A32EmitA64::EmitA32SetGEFlags(A32EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ASSERT(!args[0].IsImmediate());
ARM64Reg to_store = INVALID_REG;
if (args[0].IsInFpr()) {
to_store = EncodeRegToSingle(ctx.reg_alloc.UseFpr(args[0]));
} else {
to_store = DecodeReg(ctx.reg_alloc.UseGpr(args[0]));
}
code.STR(INDEX_UNSIGNED, to_store, X28, offsetof(A32JitState, CPSR_ge));
}
void A32EmitA64::EmitA32SetGEFlagsCompressed(A32EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -1314,6 +1314,9 @@ void A32EmitA64::EmitTerminalImpl(IR::Term::LinkBlock terminal, IR::LocationDesc
code.STR(INDEX_UNSIGNED, DecodeReg(code.ABI_SCRATCH1), X28, MJitStateReg(A32::Reg::PC));
PushRSBHelper(X1, X2, terminal.next);
code.ForceReturnFromRunCode();
//Todo: find a better/generic place to FlushIcache when switching between
// far code and near code
code.FlushIcache();
code.SwitchToNearCode();
}

View File

@ -6,11 +6,11 @@ OPCODE(Breakpoint, Void,
// A32 Context getters/setters
A32OPC(GetRegister, U32, A32Reg )
//A32OPC(GetExtendedRegister32, U32, A32ExtReg )
//A32OPC(GetExtendedRegister64, U64, A32ExtReg )
A32OPC(GetExtendedRegister32, U32, A32ExtReg )
A32OPC(GetExtendedRegister64, U64, A32ExtReg )
A32OPC(SetRegister, Void, A32Reg, U32 )
//A32OPC(SetExtendedRegister32, Void, A32ExtReg, U32 )
//A32OPC(SetExtendedRegister64, Void, A32ExtReg, U64 )
A32OPC(SetExtendedRegister32, Void, A32ExtReg, U32 )
A32OPC(SetExtendedRegister64, Void, A32ExtReg, U64 )
A32OPC(GetCpsr, U32, )
A32OPC(SetCpsr, Void, U32 )
A32OPC(SetCpsrNZCV, Void, U32 )
@ -24,16 +24,16 @@ A32OPC(SetCFlag, Void, U1
A32OPC(GetVFlag, U1, )
A32OPC(SetVFlag, Void, U1 )
A32OPC(OrQFlag, Void, U1 )
//A32OPC(GetGEFlags, U32, )
//A32OPC(SetGEFlags, Void, U32 )
A32OPC(GetGEFlags, U32, )
A32OPC(SetGEFlags, Void, U32 )
A32OPC(SetGEFlagsCompressed, Void, U32 )
A32OPC(BXWritePC, Void, U32 )
A32OPC(CallSupervisor, Void, U32 )
A32OPC(ExceptionRaised, Void, U32, U64 )
//A32OPC(GetFpscr, U32, )
//A32OPC(SetFpscr, Void, U32, )
//A32OPC(GetFpscrNZCV, U32, )
//A32OPC(SetFpscrNZCV, Void, NZCV )
A32OPC(GetFpscr, U32, )
A32OPC(SetFpscr, Void, U32, )
A32OPC(GetFpscrNZCV, U32, )
A32OPC(SetFpscrNZCV, Void, NZCV )
// A64 Context getters/setters
//A64OPC(SetCheckBit, Void, U1 )