mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-06-06 01:13:45 -04:00
[dynarmic,loongarch64] Add minimal toy implementation enough to execute LSLS
This commit is contained in:
parent
16ba4cb997
commit
dab20371a2
5 changed files with 150 additions and 2 deletions
|
|
@ -306,6 +306,8 @@ if ("loongarch64" IN_LIST ARCHITECTURE)
|
|||
backend/loongarch64/emit_context.h
|
||||
backend/loongarch64/emit_loongarch64.cpp
|
||||
backend/loongarch64/emit_loongarch64.h
|
||||
backend/loongarch64/emit_loongarch64_a32.cpp
|
||||
backend/loongarch64/emit_loongarch64_data_processing.cpp
|
||||
backend/loongarch64/a32_address_space.cpp
|
||||
backend/loongarch64/a32_address_space.h
|
||||
backend/loongarch64/a32_interface.cpp
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "common/assert.h"
|
||||
|
||||
#include "dynarmic/backend/loongarch64/a32_jitstate.h"
|
||||
#include "dynarmic/backend/loongarch64/abi.h"
|
||||
#include "dynarmic/backend/loongarch64/emit_loongarch64.h"
|
||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||
|
|
@ -62,8 +63,10 @@ void A32AddressSpace::EmitPrelude() {
|
|||
la_st_d(&cb.as, static_cast<la_gpr_t>(i), LA_SP, static_cast<int32_t>(i * 8));
|
||||
}
|
||||
|
||||
// Jump to block entry (a0)
|
||||
la_jr(&cb.as, LA_A0);
|
||||
// Set up reserved registers and jump to block entry
|
||||
la_move(&cb.as, Xstate, LA_A1); // Xstate = state ptr
|
||||
la_move(&cb.as, Xhalt, LA_A2); // Xhalt = halt reason ptr
|
||||
la_jr(&cb.as, LA_A0); // jump to block_entry
|
||||
|
||||
prelude_info.return_from_run_code = GetCursorPtr<CodePtr>();
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,43 @@ void EmitIR(lagoon_assembler_t&, EmitContext&, IR::Inst*) {
|
|||
ASSERT(false && "Unimplemented opcode");
|
||||
}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::Void>(lagoon_assembler_t&, EmitContext&, IR::Inst*) {}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A32GetRegister>(lagoon_assembler_t&, EmitContext& ctx, IR::Inst* inst);
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A32SetRegister>(lagoon_assembler_t&, EmitContext& ctx, IR::Inst* inst);
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A32SetCpsrNZC>(lagoon_assembler_t&, EmitContext& ctx, IR::Inst* inst);
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::LogicalShiftLeft32>(lagoon_assembler_t&, EmitContext& ctx, IR::Inst* inst);
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::GetCarryFromOp>(lagoon_assembler_t&, EmitContext& ctx, IR::Inst* inst) {
|
||||
ASSERT(ctx.reg_alloc.IsValueLive(inst));
|
||||
}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::GetNZFromOp>(lagoon_assembler_t& as, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
auto Xvalue = ctx.reg_alloc.ReadX(args[0]);
|
||||
auto Xnz = ctx.reg_alloc.WriteX(inst);
|
||||
RegAlloc::Realize(Xvalue, Xnz);
|
||||
|
||||
// Z flag (bit 30): set if value == 0
|
||||
la_sltui(&as, Xnz->index, Xvalue->index, 1);
|
||||
la_slli_d(&as, Xnz->index, Xnz->index, 30);
|
||||
// N flag (bit 31): set if value < 0 (signed)
|
||||
la_slt(&as, Xscratch0, Xvalue->index, LA_ZERO);
|
||||
la_slli_d(&as, Xscratch0, Xscratch0, 31);
|
||||
la_or(&as, Xnz->index, Xnz->index, Xscratch0);
|
||||
}
|
||||
|
||||
EmittedBlockInfo EmitLoongArch64(lagoon_assembler_t& as, IR::Block block, const EmitConfig& emit_conf) {
|
||||
EmittedBlockInfo ebi;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "dynarmic/backend/loongarch64/lagoon_cpp.h"
|
||||
|
||||
#include "dynarmic/backend/loongarch64/a32_jitstate.h"
|
||||
#include "dynarmic/backend/loongarch64/abi.h"
|
||||
#include "dynarmic/backend/loongarch64/emit_context.h"
|
||||
#include "dynarmic/backend/loongarch64/emit_loongarch64.h"
|
||||
#include "dynarmic/backend/loongarch64/reg_alloc.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
|
||||
namespace Dynarmic::Backend::LoongArch64 {
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A32GetRegister>(lagoon_assembler_t& as, EmitContext& ctx, IR::Inst* inst) {
|
||||
const A32::Reg reg = inst->GetArg(0).GetA32RegRef();
|
||||
|
||||
auto Xresult = ctx.reg_alloc.WriteX(inst);
|
||||
RegAlloc::Realize(Xresult);
|
||||
|
||||
la_ld_wu(&as, Xresult->index, Xstate,
|
||||
static_cast<int32_t>(offsetof(A32JitState, regs) + sizeof(u32) * static_cast<size_t>(reg)));
|
||||
}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A32SetRegister>(lagoon_assembler_t& as, EmitContext& ctx, IR::Inst* inst) {
|
||||
const A32::Reg reg = inst->GetArg(0).GetA32RegRef();
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
auto Xvalue = ctx.reg_alloc.ReadX(args[1]);
|
||||
RegAlloc::Realize(Xvalue);
|
||||
|
||||
la_st_w(&as, Xvalue->index, Xstate,
|
||||
static_cast<int32_t>(offsetof(A32JitState, regs) + sizeof(u32) * static_cast<size_t>(reg)));
|
||||
}
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::A32SetCpsrNZC>(lagoon_assembler_t& as, EmitContext& ctx, IR::Inst* inst) {
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
|
||||
ASSERT(!args[0].IsImmediate() && !args[1].IsImmediate());
|
||||
|
||||
auto Xnz = ctx.reg_alloc.ReadX(args[0]);
|
||||
auto Xc = ctx.reg_alloc.ReadX(args[1]);
|
||||
RegAlloc::Realize(Xnz, Xc);
|
||||
|
||||
la_ld_wu(&as, Xscratch0, Xstate, static_cast<int32_t>(offsetof(A32JitState, cpsr_nzcv)));
|
||||
la_load_immediate64(&as, Xscratch1, 0x10000000);
|
||||
la_and(&as, Xscratch0, Xscratch0, Xscratch1);
|
||||
la_or(&as, Xscratch0, Xscratch0, Xnz->index);
|
||||
la_slli_w(&as, Xscratch1, Xc->index, 29);
|
||||
la_or(&as, Xscratch0, Xscratch0, Xscratch1);
|
||||
la_st_w(&as, Xscratch0, Xstate, static_cast<int32_t>(offsetof(A32JitState, cpsr_nzcv)));
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::LoongArch64
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "dynarmic/backend/loongarch64/lagoon_cpp.h"
|
||||
|
||||
#include "dynarmic/backend/loongarch64/abi.h"
|
||||
#include "dynarmic/backend/loongarch64/emit_context.h"
|
||||
#include "dynarmic/backend/loongarch64/emit_loongarch64.h"
|
||||
#include "dynarmic/backend/loongarch64/reg_alloc.h"
|
||||
#include "dynarmic/ir/basic_block.h"
|
||||
#include "dynarmic/ir/microinstruction.h"
|
||||
#include "dynarmic/ir/opcodes.h"
|
||||
|
||||
namespace Dynarmic::Backend::LoongArch64 {
|
||||
|
||||
template<>
|
||||
void EmitIR<IR::Opcode::LogicalShiftLeft32>(lagoon_assembler_t& as, EmitContext& ctx, IR::Inst* inst) {
|
||||
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
|
||||
|
||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
auto& operand_arg = args[0];
|
||||
auto& shift_arg = args[1];
|
||||
auto& carry_arg = args[2];
|
||||
|
||||
ASSERT(carry_inst != nullptr);
|
||||
ASSERT(shift_arg.IsImmediate());
|
||||
|
||||
auto Xresult = ctx.reg_alloc.WriteX(inst);
|
||||
auto Xcarry_out = ctx.reg_alloc.WriteX(carry_inst);
|
||||
auto Xoperand = ctx.reg_alloc.ReadX(operand_arg);
|
||||
auto Xcarry_in = ctx.reg_alloc.ReadX(carry_arg);
|
||||
RegAlloc::Realize(Xresult, Xcarry_out, Xoperand, Xcarry_in);
|
||||
|
||||
const u8 shift = shift_arg.GetImmediateU8();
|
||||
|
||||
if (shift == 0) {
|
||||
la_addi_w(&as, Xresult->index, Xoperand->index, 0);
|
||||
la_addi_w(&as, Xcarry_out->index, Xcarry_in->index, 0);
|
||||
} else if (shift < 32) {
|
||||
la_srli_w(&as, Xcarry_out->index, Xoperand->index, 32 - shift);
|
||||
la_andi(&as, Xcarry_out->index, Xcarry_out->index, 1);
|
||||
la_slli_w(&as, Xresult->index, Xoperand->index, shift);
|
||||
} else if (shift > 32) {
|
||||
la_move(&as, Xresult->index, LA_ZERO);
|
||||
la_move(&as, Xcarry_out->index, LA_ZERO);
|
||||
} else {
|
||||
la_andi(&as, Xcarry_out->index, Xoperand->index, 1);
|
||||
la_move(&as, Xresult->index, LA_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Dynarmic::Backend::LoongArch64
|
||||
Loading…
Add table
Reference in a new issue