CPU: Add additional instruction decoder helpers
This commit is contained in:
parent
9fd1d606d7
commit
e044858953
|
@ -64,7 +64,41 @@ TickCount GetICacheFillTicks(VirtualMemoryAddress address);
|
||||||
u32 FillICache(VirtualMemoryAddress address);
|
u32 FillICache(VirtualMemoryAddress address);
|
||||||
void CheckAndUpdateICacheTags(u32 line_count, TickCount uncached_ticks);
|
void CheckAndUpdateICacheTags(u32 line_count, TickCount uncached_ticks);
|
||||||
|
|
||||||
// defined in cpu_memory.cpp - memory access functions which return false if an exception was thrown.
|
ALWAYS_INLINE Segment GetSegmentForAddress(VirtualMemoryAddress address)
|
||||||
|
{
|
||||||
|
switch ((address >> 29))
|
||||||
|
{
|
||||||
|
case 0x00: // KUSEG 0M-512M
|
||||||
|
case 0x01: // KUSEG 512M-1024M
|
||||||
|
case 0x02: // KUSEG 1024M-1536M
|
||||||
|
case 0x03: // KUSEG 1536M-2048M
|
||||||
|
return Segment::KUSEG;
|
||||||
|
|
||||||
|
case 0x04: // KSEG0 - physical memory cached
|
||||||
|
return Segment::KSEG0;
|
||||||
|
|
||||||
|
case 0x05: // KSEG1 - physical memory uncached
|
||||||
|
return Segment::KSEG1;
|
||||||
|
|
||||||
|
case 0x06: // KSEG2
|
||||||
|
case 0x07: // KSEG2
|
||||||
|
default:
|
||||||
|
return Segment::KSEG2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE PhysicalMemoryAddress VirtualAddressToPhysical(VirtualMemoryAddress address)
|
||||||
|
{
|
||||||
|
return (address & PHYSICAL_MEMORY_ADDRESS_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE VirtualMemoryAddress PhysicalAddressToVirtual(PhysicalMemoryAddress address, Segment segment)
|
||||||
|
{
|
||||||
|
static constexpr std::array<VirtualMemoryAddress, 4> bases = {{0x00000000, 0x80000000, 0xA0000000, 0xE0000000}};
|
||||||
|
return bases[static_cast<u32>(segment)] | address;
|
||||||
|
}
|
||||||
|
|
||||||
|
// defined in bus.cpp - memory access functions which return false if an exception was thrown.
|
||||||
bool FetchInstruction();
|
bool FetchInstruction();
|
||||||
bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value);
|
bool SafeReadInstruction(VirtualMemoryAddress addr, u32* value);
|
||||||
bool ReadMemoryByte(VirtualMemoryAddress addr, u8* value);
|
bool ReadMemoryByte(VirtualMemoryAddress addr, u8* value);
|
||||||
|
|
|
@ -119,6 +119,24 @@ u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsCallInstruction(const Instruction& instruction)
|
||||||
|
{
|
||||||
|
return (instruction.op == InstructionOp::funct && instruction.r.funct == InstructionFunct::jalr) ||
|
||||||
|
(instruction.op == InstructionOp::jal);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsReturnInstruction(const Instruction& instruction)
|
||||||
|
{
|
||||||
|
if (instruction.op != InstructionOp::funct)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// j(al)r ra
|
||||||
|
if (instruction.r.funct == InstructionFunct::jr || instruction.r.funct == InstructionFunct::jalr)
|
||||||
|
return (instruction.r.rs == Reg::ra);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsMemoryLoadInstruction(const Instruction& instruction)
|
bool IsMemoryLoadInstruction(const Instruction& instruction)
|
||||||
{
|
{
|
||||||
switch (instruction.op)
|
switch (instruction.op)
|
||||||
|
@ -159,6 +177,33 @@ bool IsMemoryStoreInstruction(const Instruction& instruction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<VirtualMemoryAddress> GetLoadStoreEffectiveAddress(const Instruction& instruction, const Registers* regs)
|
||||||
|
{
|
||||||
|
switch (instruction.op)
|
||||||
|
{
|
||||||
|
case InstructionOp::lb:
|
||||||
|
case InstructionOp::lh:
|
||||||
|
case InstructionOp::lw:
|
||||||
|
case InstructionOp::lbu:
|
||||||
|
case InstructionOp::lhu:
|
||||||
|
case InstructionOp::lwc2:
|
||||||
|
case InstructionOp::sb:
|
||||||
|
case InstructionOp::sh:
|
||||||
|
case InstructionOp::sw:
|
||||||
|
case InstructionOp::swc2:
|
||||||
|
return (regs->r[static_cast<u32>(instruction.i.rs.GetValue())] + instruction.i.imm_sext32());
|
||||||
|
|
||||||
|
case InstructionOp::lwl:
|
||||||
|
case InstructionOp::lwr:
|
||||||
|
case InstructionOp::swl:
|
||||||
|
case InstructionOp::swr:
|
||||||
|
return (regs->r[static_cast<u32>(instruction.i.rs.GetValue())] + instruction.i.imm_sext32()) & ~UINT32_C(3);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool InstructionHasLoadDelay(const Instruction& instruction)
|
bool InstructionHasLoadDelay(const Instruction& instruction)
|
||||||
{
|
{
|
||||||
switch (instruction.op)
|
switch (instruction.op)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/bitfield.h"
|
#include "common/bitfield.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace CPU {
|
namespace CPU {
|
||||||
|
|
||||||
|
@ -14,6 +15,14 @@ enum : u32
|
||||||
INSTRUCTION_SIZE = sizeof(u32)
|
INSTRUCTION_SIZE = sizeof(u32)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Segment
|
||||||
|
{
|
||||||
|
KUSEG, // virtual memory
|
||||||
|
KSEG0, // physical memory cached
|
||||||
|
KSEG1, // physical memory uncached
|
||||||
|
KSEG2
|
||||||
|
};
|
||||||
|
|
||||||
enum class Reg : u8
|
enum class Reg : u8
|
||||||
{
|
{
|
||||||
zero,
|
zero,
|
||||||
|
@ -215,6 +224,8 @@ bool IsBranchInstruction(const Instruction& instruction);
|
||||||
bool IsUnconditionalBranchInstruction(const Instruction& instruction);
|
bool IsUnconditionalBranchInstruction(const Instruction& instruction);
|
||||||
bool IsDirectBranchInstruction(const Instruction& instruction);
|
bool IsDirectBranchInstruction(const Instruction& instruction);
|
||||||
u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_pc);
|
u32 GetBranchInstructionTarget(const Instruction& instruction, u32 instruction_pc);
|
||||||
|
bool IsCallInstruction(const Instruction& instruction);
|
||||||
|
bool IsReturnInstruction(const Instruction& instruction);
|
||||||
bool IsMemoryLoadInstruction(const Instruction& instruction);
|
bool IsMemoryLoadInstruction(const Instruction& instruction);
|
||||||
bool IsMemoryStoreInstruction(const Instruction& instruction);
|
bool IsMemoryStoreInstruction(const Instruction& instruction);
|
||||||
bool InstructionHasLoadDelay(const Instruction& instruction);
|
bool InstructionHasLoadDelay(const Instruction& instruction);
|
||||||
|
@ -272,6 +283,9 @@ struct Registers
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::optional<VirtualMemoryAddress> GetLoadStoreEffectiveAddress(const Instruction& instruction,
|
||||||
|
const Registers* regs);
|
||||||
|
|
||||||
enum class Cop0Reg : u8
|
enum class Cop0Reg : u8
|
||||||
{
|
{
|
||||||
BPC = 3,
|
BPC = 3,
|
||||||
|
|
Loading…
Reference in New Issue