mirror of
https://github.com/ApfelTeeSaft/Yaroze.NET.git
synced 2026-08-26 19:43:27 +00:00
210 lines
5.9 KiB
C#
210 lines
5.9 KiB
C#
using Yaroze.Core.Utilities;
|
|
|
|
namespace Yaroze.Core.CPU;
|
|
|
|
/// <summary>
|
|
/// Represents a decoded MIPS instruction.
|
|
/// Provides methods to extract fields from the 32-bit instruction word.
|
|
/// </summary>
|
|
public readonly struct Instruction
|
|
{
|
|
private readonly uint _raw;
|
|
|
|
public Instruction(uint raw)
|
|
{
|
|
_raw = raw;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raw 32-bit instruction word.
|
|
/// </summary>
|
|
public uint Raw => _raw;
|
|
|
|
/// <summary>
|
|
/// Opcode (bits 31-26).
|
|
/// </summary>
|
|
public uint Opcode => BitUtils.ExtractBits(_raw, 26, 6);
|
|
|
|
/// <summary>
|
|
/// RS register field (bits 25-21).
|
|
/// </summary>
|
|
public uint Rs => BitUtils.ExtractBits(_raw, 21, 5);
|
|
|
|
/// <summary>
|
|
/// RT register field (bits 20-16).
|
|
/// </summary>
|
|
public uint Rt => BitUtils.ExtractBits(_raw, 16, 5);
|
|
|
|
/// <summary>
|
|
/// RD register field (bits 15-11).
|
|
/// </summary>
|
|
public uint Rd => BitUtils.ExtractBits(_raw, 11, 5);
|
|
|
|
/// <summary>
|
|
/// Shift amount field (bits 10-6).
|
|
/// </summary>
|
|
public uint Shamt => BitUtils.ExtractBits(_raw, 6, 5);
|
|
|
|
/// <summary>
|
|
/// Function code (bits 5-0).
|
|
/// </summary>
|
|
public uint Funct => BitUtils.ExtractBits(_raw, 0, 6);
|
|
|
|
/// <summary>
|
|
/// 16-bit immediate value (bits 15-0).
|
|
/// </summary>
|
|
public ushort Imm16 => (ushort)BitUtils.ExtractBits(_raw, 0, 16);
|
|
|
|
/// <summary>
|
|
/// 26-bit jump target (bits 25-0).
|
|
/// </summary>
|
|
public uint Target26 => BitUtils.ExtractBits(_raw, 0, 26);
|
|
|
|
/// <summary>
|
|
/// Sign-extended immediate value (for arithmetic/load/store).
|
|
/// </summary>
|
|
public uint ImmSigned => SignExtension.SignExtend16(Imm16);
|
|
|
|
/// <summary>
|
|
/// Zero-extended immediate value (for logic operations).
|
|
/// </summary>
|
|
public uint ImmUnsigned => Imm16;
|
|
|
|
/// <summary>
|
|
/// Coprocessor opcode (bits 25-21) for COP instructions.
|
|
/// </summary>
|
|
public uint CopOp => BitUtils.ExtractBits(_raw, 21, 5);
|
|
|
|
/// <summary>
|
|
/// Calculate branch target address.
|
|
/// </summary>
|
|
public uint BranchTarget(uint pc)
|
|
{
|
|
// Sign-extend 16-bit offset, shift left 2 bits, add to PC+4
|
|
uint offset = SignExtension.SignExtend16(Imm16) << 2;
|
|
return (pc + 4) + offset;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate jump target address.
|
|
/// </summary>
|
|
public uint JumpTarget(uint pc)
|
|
{
|
|
// Take upper 4 bits of PC+4, concatenate with target26 << 2
|
|
return (pc & 0xF0000000) | (Target26 << 2);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if this is a NOP instruction (SLL $0, $0, 0).
|
|
/// </summary>
|
|
public bool IsNop => _raw == 0x00000000;
|
|
|
|
public override string ToString()
|
|
{
|
|
return $"0x{_raw:X8} [op={Opcode:X2} rs={Rs} rt={Rt} rd={Rd} funct={Funct:X2}]";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// MIPS instruction opcodes.
|
|
/// </summary>
|
|
public static class Opcode
|
|
{
|
|
public const uint SPECIAL = 0x00; // R-type instructions (use funct field)
|
|
public const uint REGIMM = 0x01; // Branch instructions (use rt field)
|
|
public const uint J = 0x02;
|
|
public const uint JAL = 0x03;
|
|
public const uint BEQ = 0x04;
|
|
public const uint BNE = 0x05;
|
|
public const uint BLEZ = 0x06;
|
|
public const uint BGTZ = 0x07;
|
|
public const uint ADDI = 0x08;
|
|
public const uint ADDIU = 0x09;
|
|
public const uint SLTI = 0x0A;
|
|
public const uint SLTIU = 0x0B;
|
|
public const uint ANDI = 0x0C;
|
|
public const uint ORI = 0x0D;
|
|
public const uint XORI = 0x0E;
|
|
public const uint LUI = 0x0F;
|
|
public const uint COP0 = 0x10;
|
|
public const uint COP1 = 0x11;
|
|
public const uint COP2 = 0x12;
|
|
public const uint COP3 = 0x13;
|
|
public const uint LB = 0x20;
|
|
public const uint LH = 0x21;
|
|
public const uint LWL = 0x22;
|
|
public const uint LW = 0x23;
|
|
public const uint LBU = 0x24;
|
|
public const uint LHU = 0x25;
|
|
public const uint LWR = 0x26;
|
|
public const uint SB = 0x28;
|
|
public const uint SH = 0x29;
|
|
public const uint SWL = 0x2A;
|
|
public const uint SW = 0x2B;
|
|
public const uint SWR = 0x2E;
|
|
public const uint LWC0 = 0x30;
|
|
public const uint LWC1 = 0x31;
|
|
public const uint LWC2 = 0x32;
|
|
public const uint LWC3 = 0x33;
|
|
public const uint SWC0 = 0x38;
|
|
public const uint SWC1 = 0x39;
|
|
public const uint SWC2 = 0x3A;
|
|
public const uint SWC3 = 0x3B;
|
|
}
|
|
|
|
/// <summary>
|
|
/// MIPS SPECIAL (R-type) function codes.
|
|
/// </summary>
|
|
public static class Funct
|
|
{
|
|
public const uint SLL = 0x00;
|
|
public const uint SRL = 0x02;
|
|
public const uint SRA = 0x03;
|
|
public const uint SLLV = 0x04;
|
|
public const uint SRLV = 0x06;
|
|
public const uint SRAV = 0x07;
|
|
public const uint JR = 0x08;
|
|
public const uint JALR = 0x09;
|
|
public const uint SYSCALL = 0x0C;
|
|
public const uint BREAK = 0x0D;
|
|
public const uint MFHI = 0x10;
|
|
public const uint MTHI = 0x11;
|
|
public const uint MFLO = 0x12;
|
|
public const uint MTLO = 0x13;
|
|
public const uint MULT = 0x18;
|
|
public const uint MULTU = 0x19;
|
|
public const uint DIV = 0x1A;
|
|
public const uint DIVU = 0x1B;
|
|
public const uint ADD = 0x20;
|
|
public const uint ADDU = 0x21;
|
|
public const uint SUB = 0x22;
|
|
public const uint SUBU = 0x23;
|
|
public const uint AND = 0x24;
|
|
public const uint OR = 0x25;
|
|
public const uint XOR = 0x26;
|
|
public const uint NOR = 0x27;
|
|
public const uint SLT = 0x2A;
|
|
public const uint SLTU = 0x2B;
|
|
}
|
|
|
|
/// <summary>
|
|
/// REGIMM branch types (rt field determines type).
|
|
/// </summary>
|
|
public static class RegImmRt
|
|
{
|
|
public const uint BLTZ = 0x00;
|
|
public const uint BGEZ = 0x01;
|
|
public const uint BLTZAL = 0x10;
|
|
public const uint BGEZAL = 0x11;
|
|
}
|
|
|
|
/// <summary>
|
|
/// COP0 function codes (rs field determines type for COP0 instructions).
|
|
/// </summary>
|
|
public static class COP0Funct
|
|
{
|
|
public const uint MFC0 = 0x00; // Move From COP0
|
|
public const uint MTC0 = 0x04; // Move To COP0
|
|
public const uint RFE = 0x10; // Return From Exception
|
|
}
|