use crate::format::{Format, TypeCB1, TypeCB2, TypeCB4, TypeCI1, TypeCI2, TypeCI3, TypeCJ, TypeCS};
use crate::instruction::{embive, riscv};
use crate::transpiler::Error;
use super::{c_bit12, c_bits11_10, c_bits6_5, c_funct3, embive_raw, Convert, RawInstruction};
const C_ADDI_FUNC: u8 = 0b000;
const C_JAL_FUNC: u8 = 0b001;
const C_LI_FUNC: u8 = 0b010;
const C_ADDI16SP_LUI_FUNC: u8 = 0b011;
const C_SRLI_SRAI_ANDI_SUB_XOR_OR_AND_FUNC: u8 = 0b100;
const C_J_FUNC: u8 = 0b101;
const C_BEQZ_FUNC: u8 = 0b110;
const C_BNEZ_FUNC: u8 = 0b111;
const C_SRLI_BITS11_10: u8 = 0b00;
const C_SRAI_BITS11_10: u8 = 0b01;
const C_ANDI_BITS11_10: u8 = 0b10;
const C_SUB_XOR_OR_AND_BIT12: u8 = 0b0;
const C_SUB_XOR_OR_AND_BITS11_10: u8 = 0b11;
const C_SUB_BITS6_5: u8 = 0b00;
const C_XOR_BITS6_5: u8 = 0b01;
const C_OR_BITS6_5: u8 = 0b10;
const C_AND_BITS6_5: u8 = 0b11;
impl Convert for riscv::C1 {
fn convert(data: u32) -> Result<RawInstruction, Error> {
match c_funct3(data) {
C_ADDI_FUNC => {
let inst = TypeCI1::from_riscv(data);
Ok(embive_raw!(embive::CAddi, inst))
}
C_JAL_FUNC => {
let inst = TypeCJ::from_riscv(data);
Ok(embive_raw!(embive::CJal, inst))
}
C_LI_FUNC => {
let inst = TypeCI1::from_riscv(data);
Ok(embive_raw!(embive::CLi, inst))
}
C_ADDI16SP_LUI_FUNC => {
let inst = TypeCI3::from_riscv(data);
if inst.rd_rs1 == 2 {
let inst = TypeCI2::from_riscv(data);
Ok(embive_raw!(embive::CAddi16sp, inst))
} else {
Ok(embive_raw!(embive::CLui, inst))
}
}
C_SRLI_SRAI_ANDI_SUB_XOR_OR_AND_FUNC => match c_bits11_10(data) {
C_SRLI_BITS11_10 => {
let inst = TypeCB1::from_riscv(data);
Ok(embive_raw!(embive::CSrli, inst))
}
C_SRAI_BITS11_10 => {
let inst = TypeCB1::from_riscv(data);
Ok(embive_raw!(embive::CSrai, inst))
}
C_ANDI_BITS11_10 => {
let inst = TypeCB2::from_riscv(data);
Ok(embive_raw!(embive::CAndi, inst))
}
C_SUB_XOR_OR_AND_BITS11_10 if (c_bit12(data) == C_SUB_XOR_OR_AND_BIT12) => {
let inst = TypeCS::from_riscv(data);
match c_bits6_5(data) {
C_SUB_BITS6_5 => Ok(embive_raw!(embive::CSub, inst)),
C_XOR_BITS6_5 => Ok(embive_raw!(embive::CXor, inst)),
C_OR_BITS6_5 => Ok(embive_raw!(embive::COr, inst)),
C_AND_BITS6_5 => Ok(embive_raw!(embive::CAnd, inst)),
_ => Err(Error::InvalidInstruction(data & 0xFFFF)),
}
}
_ => Err(Error::InvalidInstruction(data & 0xFFFF)),
},
C_J_FUNC => {
let inst = TypeCJ::from_riscv(data);
Ok(embive_raw!(embive::CJ, inst))
}
C_BEQZ_FUNC => {
let inst = TypeCB4::from_riscv(data);
Ok(embive_raw!(embive::CBeqz, inst))
}
C_BNEZ_FUNC => {
let inst = TypeCB4::from_riscv(data);
Ok(embive_raw!(embive::CBnez, inst))
}
_ => Err(Error::InvalidInstruction(data & 0xFFFF)),
}
}
}