From 7661987e04aa023690b76eadcf533dc54624791f Mon Sep 17 00:00:00 2001 From: SachinVin Date: Sun, 14 Jul 2019 20:44:55 +0530 Subject: [PATCH] A64 backend: Add Get/SetExtendedRegister and Get/SetGEFlags --- src/backend/A64/a32_emit_a64.cpp | 147 ++++++++++++++++--------------- src/backend/A64/opcodes.inc | 20 ++--- 2 files changed, 85 insertions(+), 82 deletions(-) diff --git a/src/backend/A64/a32_emit_a64.cpp b/src/backend/A64/a32_emit_a64.cpp index 52052038..1bd7f06e 100644 --- a/src/backend/A64/a32_emit_a64.cpp +++ b/src/backend/A64/a32_emit_a64.cpp @@ -42,17 +42,17 @@ static size_t MJitStateReg(A32::Reg reg) { return offsetof(A32JitState, Reg) + sizeof(u32) * static_cast(reg); } -//static size_t MJitStateExtReg(A32::ExtReg reg) { -// if (A32::IsSingleExtReg(reg)) { -// size_t index = static_cast(reg) - static_cast(A32::ExtReg::S0); -// return offsetof(A32JitState, ExtReg) + sizeof(u32) * index; -// } -// if (A32::IsDoubleExtReg(reg)) { -// size_t index = static_cast(reg) - static_cast(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(reg) - static_cast(A32::ExtReg::S0); + return offsetof(A32JitState, ExtReg) + sizeof(u32) * index; + } + if (A32::IsDoubleExtReg(reg)) { + size_t index = static_cast(reg) - static_cast(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(); } diff --git a/src/backend/A64/opcodes.inc b/src/backend/A64/opcodes.inc index af94e903..1723184a 100644 --- a/src/backend/A64/opcodes.inc +++ b/src/backend/A64/opcodes.inc @@ -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 )