use crate::CPU::Endian;
#[derive (Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mips32Register
{
ZERO = 0,
AT = 1,
V0 = 2,
V1 = 3,
A0 = 4,
A1 = 5,
A2 = 6,
A3 = 7,
T0 = 8,
T1 = 9,
T2 = 10,
T3 = 11,
T4 = 12,
T5 = 13,
T6 = 14,
T7 = 15,
S0 = 16,
S1 = 17,
S2 = 18,
S3 = 19,
S4 = 20,
S5 = 21,
S6 = 22,
S7 = 23,
T8 = 24,
T9 = 25,
K0 = 26,
K1 = 27,
GP = 28,
SP = 29,
FP = 30,
RA = 31,
}
impl TryFrom<usize> for Mips32Register
{
type Error = ();
fn try_from (value: usize) -> Result<Self, Self::Error>
{
match value
{
x if x == Self::ZERO as usize => Ok(Self::ZERO),
x if x == Self::AT as usize => Ok(Self::AT),
x if x == Self::V0 as usize => Ok(Self::V0),
x if x == Self::V1 as usize => Ok(Self::V1),
x if x == Self::A0 as usize => Ok(Self::A0),
x if x == Self::A1 as usize => Ok(Self::A1),
x if x == Self::A2 as usize => Ok(Self::A2),
x if x == Self::A3 as usize => Ok(Self::A3),
x if x == Self::T0 as usize => Ok(Self::T0),
x if x == Self::T1 as usize => Ok(Self::T1),
x if x == Self::T2 as usize => Ok(Self::T2),
x if x == Self::T3 as usize => Ok(Self::T3),
x if x == Self::T4 as usize => Ok(Self::T4),
x if x == Self::T5 as usize => Ok(Self::T5),
x if x == Self::T6 as usize => Ok(Self::T6),
x if x == Self::T7 as usize => Ok(Self::T7),
x if x == Self::S0 as usize => Ok(Self::S0),
x if x == Self::S1 as usize => Ok(Self::S1),
x if x == Self::S2 as usize => Ok(Self::S2),
x if x == Self::S3 as usize => Ok(Self::S3),
x if x == Self::S4 as usize => Ok(Self::S4),
x if x == Self::S5 as usize => Ok(Self::S5),
x if x == Self::S6 as usize => Ok(Self::S6),
x if x == Self::S7 as usize => Ok(Self::S7),
x if x == Self::T8 as usize => Ok(Self::T8),
x if x == Self::T9 as usize => Ok(Self::T9),
x if x == Self::K0 as usize => Ok(Self::K0),
x if x == Self::K1 as usize => Ok(Self::K1),
x if x == Self::GP as usize => Ok(Self::GP),
x if x == Self::SP as usize => Ok(Self::SP),
x if x == Self::FP as usize => Ok(Self::FP),
x if x == Self::RA as usize => Ok(Self::RA),
_ => Err(()),
}
}
}
#[derive (Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mips32InstructionOpcode
{
REG = 0b000000,
ADDI = 0b001000,
ADDIU = 0b001001,
SLTI = 0b001010,
SLTIU = 0b001011,
ANDI = 0b001100,
ORI = 0b001101,
XORI = 0b001110,
LUI = 0b001111,
LB = 0b100000,
LH = 0b100001,
LW = 0b100011,
LHU = 0b100101,
SH = 0b101001,
SW = 0b101011,
SB = 0b101000,
BEQ = 0b000100,
BNE = 0b000101,
}
#[derive (Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mips32InstructionFunctionCode
{
SYSCALL = 0b001100,
SYNC = 0x001111,
MFHI = 0b010000,
MTHI = 0b010001,
MFLO = 0b010010,
MTLO = 0b010011,
MULT = 0b011000,
MULTU = 0b011001,
DIV = 0b011010,
DIVU = 0b011011,
ADD = 0b100000,
ADDU = 0b100001,
SUB = 0b100010,
SUBU = 0b100011,
AND = 0b100100,
OR = 0b100101,
XOR = 0b100110,
NOR = 0b100111,
SLT = 0b101010,
SLTU = 0b101011,
}
#[derive (Clone, Copy, Debug, Eq, PartialEq)]
pub struct Mips32RTypeInstruction
{
opcode: Mips32InstructionOpcode,
rs: Mips32Register,
rt: Mips32Register,
rd: Mips32Register,
shamt: usize,
funct: Mips32InstructionFunctionCode,
}
impl Mips32RTypeInstruction
{
pub fn New (opcode: Mips32InstructionOpcode, rs: Mips32Register, rt: Mips32Register, rd: Mips32Register, shamt: usize, funct: Mips32InstructionFunctionCode) -> Self
{
Self
{
opcode,
rs,
rt,
rd,
shamt,
funct,
}
}
pub fn ToByteArray (&self, endian: Endian) -> Vec<u8>
{
let op = (self.opcode as usize)&0b111111;
let rs = (self.rs as usize)&0b11111;
let rt = (self.rt as usize)&0b11111;
let rd = (self.rd as usize)&0b11111;
let shamt = self.shamt&0b11111;
let funct = (self.funct as usize)&0b111111;
let code: u32 = ((op<<26) | (rs<<21) | (rt<<16) | (rd<<11) | (shamt<<6) | funct) as u32;
if endian == Endian::BIG
{
code.to_be_bytes ().to_vec ()
}
else
{
code.to_le_bytes ().to_vec ()
}
}
pub fn ToAssemblySource (&self) -> String
{
unimplemented! ();
}
}
#[derive (Clone, Copy, Debug, Eq, PartialEq)]
pub struct Mips32ITypeInstruction
{
opcode: Mips32InstructionOpcode,
rs: Mips32Register,
rt: Mips32Register,
addrImm: u16,
}
impl Mips32ITypeInstruction
{
pub fn New (opcode: Mips32InstructionOpcode, rs: Mips32Register, rt: Mips32Register, addrImm: u16) -> Self
{
Self
{
opcode,
rs,
rt,
addrImm,
}
}
pub fn ToByteArray (&self, endian: Endian) -> Vec<u8>
{
let op = (self.opcode as usize)&0b111111;
let rs = (self.rs as usize)&0b11111;
let rt = (self.rt as usize)&0b11111;
let code: u32 = ((op<<26) | (rs<<21) | (rt<<16) | self.addrImm as usize) as u32;
if endian == Endian::BIG
{
code.to_be_bytes ().to_vec ()
}
else
{
code.to_le_bytes ().to_vec ()
}
}
pub fn ToAssemblySource (&self) -> String
{
unimplemented! ();
}
}
#[derive (Clone, Copy, Debug, Eq, PartialEq)]
pub struct Mips32JTypeInstruction
{
opcode: Mips32InstructionOpcode,
targetAddress: usize,
}
impl Mips32JTypeInstruction
{
pub fn New (opcode: Mips32InstructionOpcode, targetAddress: usize) -> Self
{
Self
{
opcode,
targetAddress,
}
}
pub fn ToByteArray (&self, endian: Endian) -> Vec<u8>
{
let op = (self.opcode as usize)&0b111111;
let targetAddress = self.targetAddress&0b1111_1111_1111_1111_1111_1111_11;
let code: u32 = ((op<<26) | targetAddress) as u32;
if endian == Endian::BIG
{
code.to_be_bytes ().to_vec ()
}
else
{
code.to_le_bytes ().to_vec ()
}
}
pub fn ToAssemblySource (&self) -> String
{
unimplemented! ();
}
}
#[derive (Clone, Copy, Debug, Eq, PartialEq)]
pub enum Mips32Instruction
{
RType(Mips32RTypeInstruction),
IType(Mips32ITypeInstruction),
JType(Mips32JTypeInstruction),
}
impl Mips32Instruction
{
pub fn ToByteArray (&self, endian: Endian) -> Vec<u8>
{
match self
{
Self::RType(instruction) => instruction.ToByteArray (endian),
Self::IType(instruction) => instruction.ToByteArray (endian),
Self::JType(instruction) => instruction.ToByteArray (endian),
}
}
pub fn ToAssemblySource (&self) -> String
{
match self
{
Self::RType(instruction) => instruction.ToAssemblySource (),
Self::IType(instruction) => instruction.ToAssemblySource (),
Self::JType(instruction) => instruction.ToAssemblySource (),
}
}
}