use crate::architecture::xtensa::arch::{CpuRegister, SpecialRegister};
pub mod format;
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Instruction {
Lddr32P(CpuRegister),
Sddr32P(CpuRegister),
L32I(CpuRegister, CpuRegister, u8),
S32I(CpuRegister, CpuRegister, u8),
Rsr(SpecialRegister, CpuRegister),
Wsr(SpecialRegister, CpuRegister),
Rfdo(u8),
CallX8(CpuRegister),
Break(u8, u8),
}
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum InstructionEncoding {
Narrow(u32),
}
impl Instruction {
const fn encode_bytes(self) -> (usize, u32) {
let word = match self {
Instruction::Lddr32P(src) => 0x0070E0 | (src as u32 & 0x0F) << 8,
Instruction::Sddr32P(src) => 0x0070F0 | (src as u32 & 0x0F) << 8,
Instruction::L32I(s, t, imm) => format::rri8(0x002002, s as u8, t as u8, imm),
Instruction::S32I(s, t, imm) => format::rri8(0x006002, s as u8, t as u8, imm),
Instruction::Rsr(sr, t) => format::rsr(0x030000, sr as u8, t as u8),
Instruction::Wsr(sr, t) => format::rsr(0x130000, sr as u8, t as u8),
Instruction::Break(s, t) => {
format::rrr(0x000000, 4, s, t)
}
Instruction::CallX8(s) => format::callx(2, s as u8),
Instruction::Rfdo(_) => 0xF1E000,
};
(3, word)
}
pub fn encode_into_vec(self, vec: &mut Vec<u8>) {
let (bytes, narrow) = self.encode_bytes();
vec.extend_from_slice(&narrow.to_le_bytes()[..bytes]);
}
pub const fn encode(self) -> InstructionEncoding {
let narrow = self.encode_bytes().1;
InstructionEncoding::Narrow(narrow)
}
}
pub(crate) fn into_binary(instructions: impl IntoIterator<Item = Instruction>) -> Vec<u8> {
Program::instructions_into_bytes(instructions)
}
#[derive(Debug, Default)]
pub(crate) struct Program {
bytes: Vec<u8>,
}
impl Program {
pub fn new() -> Self {
Program { bytes: Vec::new() }
}
pub fn add_instruction(&mut self, instruction: Instruction) {
instruction.encode_into_vec(&mut self.bytes);
}
pub fn add_instructions(&mut self, instructions: impl IntoIterator<Item = Instruction>) {
for instruction in instructions {
self.add_instruction(instruction);
}
}
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
pub fn instructions_into_bytes(instructions: impl IntoIterator<Item = Instruction>) -> Vec<u8> {
let mut program = Program::new();
program.add_instructions(instructions);
program.into_bytes()
}
}