158 lines
5.5 KiB
Rust
158 lines
5.5 KiB
Rust
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
// See Notices.txt for copyright information
|
|
|
|
use cpu::{instruction::MOp, util::array_vec::ArrayVec};
|
|
use fayalite::prelude::*;
|
|
use std::fmt;
|
|
|
|
mod branch;
|
|
mod condition_register;
|
|
mod fixed_point_arithmetic;
|
|
mod fixed_point_compare;
|
|
mod fixed_point_load;
|
|
mod fixed_point_logical;
|
|
mod fixed_point_rotate_and_shift;
|
|
mod fixed_point_store;
|
|
mod move_to_from_system_register;
|
|
mod prefixed_no_operation;
|
|
|
|
pub struct TestCase {
|
|
pub mnemonic: &'static str,
|
|
pub first_input: u32,
|
|
pub second_input: Option<u32>,
|
|
pub output: SimValue<ArrayVec<MOp, ConstUsize<3>>>,
|
|
pub loc: &'static std::panic::Location<'static>,
|
|
}
|
|
|
|
impl fmt::Debug for TestCase {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
let Self {
|
|
mnemonic,
|
|
first_input,
|
|
second_input,
|
|
output,
|
|
loc,
|
|
} = self;
|
|
let mut debug_struct = f.debug_struct("TestCase");
|
|
debug_struct
|
|
.field("mnemonic", mnemonic)
|
|
.field("first_input", &format_args!("0x{first_input:08x}"));
|
|
if let Some(second_input) = second_input {
|
|
debug_struct.field("second_input", &format_args!("0x{second_input:08x}"));
|
|
} else {
|
|
debug_struct.field("second_input", &format_args!("None"));
|
|
}
|
|
debug_struct
|
|
.field("output", &ArrayVec::elements_sim_ref(output))
|
|
.field("loc", &format_args!("{loc}"))
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
#[track_caller]
|
|
fn insn_empty(mnemonic: &'static str, first_input: u32, second_input: Option<u32>) -> TestCase {
|
|
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width())
|
|
.zero()
|
|
.cast_bits_to(MOp);
|
|
TestCase {
|
|
mnemonic,
|
|
first_input,
|
|
second_input,
|
|
output: ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop),
|
|
loc: std::panic::Location::caller(),
|
|
}
|
|
}
|
|
|
|
#[track_caller]
|
|
fn insn_single(
|
|
mnemonic: &'static str,
|
|
first_input: u32,
|
|
second_input: Option<u32>,
|
|
output: impl ToSimValue<Type = MOp>,
|
|
) -> TestCase {
|
|
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width())
|
|
.zero()
|
|
.cast_bits_to(MOp);
|
|
let mut single_storage = ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop);
|
|
ArrayVec::try_push_sim(&mut single_storage, zero_mop).expect("known to have space");
|
|
ArrayVec::elements_sim_mut(&mut single_storage)[0] = output.to_sim_value();
|
|
TestCase {
|
|
mnemonic,
|
|
first_input,
|
|
second_input,
|
|
output: single_storage,
|
|
loc: std::panic::Location::caller(),
|
|
}
|
|
}
|
|
|
|
#[track_caller]
|
|
fn insn_double(
|
|
mnemonic: &'static str,
|
|
first_input: u32,
|
|
second_input: Option<u32>,
|
|
insns: [impl ToSimValue<Type = MOp>; 2],
|
|
) -> TestCase {
|
|
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width())
|
|
.zero()
|
|
.cast_bits_to(MOp);
|
|
let mut single_storage = ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop);
|
|
ArrayVec::try_push_sim(&mut single_storage, &zero_mop).expect("known to have space");
|
|
ArrayVec::try_push_sim(&mut single_storage, zero_mop).expect("known to have space");
|
|
ArrayVec::elements_sim_mut(&mut single_storage)[0] = insns[0].to_sim_value();
|
|
ArrayVec::elements_sim_mut(&mut single_storage)[1] = insns[1].to_sim_value();
|
|
TestCase {
|
|
mnemonic,
|
|
first_input,
|
|
second_input,
|
|
output: single_storage,
|
|
loc: std::panic::Location::caller(),
|
|
}
|
|
}
|
|
|
|
#[track_caller]
|
|
fn insn_triple(
|
|
mnemonic: &'static str,
|
|
first_input: u32,
|
|
second_input: Option<u32>,
|
|
insns: [impl ToSimValue<Type = MOp>; 3],
|
|
) -> TestCase {
|
|
let zero_mop = UInt::new_dyn(MOp.canonical().bit_width())
|
|
.zero()
|
|
.cast_bits_to(MOp);
|
|
let mut single_storage = ArrayVec::new_sim(ArrayVec[MOp][ConstUsize], &zero_mop);
|
|
ArrayVec::try_push_sim(&mut single_storage, &zero_mop).expect("known to have space");
|
|
ArrayVec::try_push_sim(&mut single_storage, &zero_mop).expect("known to have space");
|
|
ArrayVec::try_push_sim(&mut single_storage, zero_mop).expect("known to have space");
|
|
ArrayVec::elements_sim_mut(&mut single_storage)[0] = insns[0].to_sim_value();
|
|
ArrayVec::elements_sim_mut(&mut single_storage)[1] = insns[1].to_sim_value();
|
|
ArrayVec::elements_sim_mut(&mut single_storage)[2] = insns[2].to_sim_value();
|
|
TestCase {
|
|
mnemonic,
|
|
first_input,
|
|
second_input,
|
|
output: single_storage,
|
|
loc: std::panic::Location::caller(),
|
|
}
|
|
}
|
|
|
|
pub fn test_cases() -> Vec<TestCase> {
|
|
let mut retval = Vec::new();
|
|
branch::test_cases_book_i_2_4_branch(&mut retval);
|
|
condition_register::test_cases_book_i_2_5_condition_register(&mut retval);
|
|
fixed_point_load::test_cases_book_i_3_3_2_fixed_point_load(&mut retval);
|
|
fixed_point_store::test_cases_book_i_3_3_3_fixed_point_store(&mut retval);
|
|
fixed_point_arithmetic::test_cases_book_i_3_3_9_fixed_point_arithmetic(&mut retval);
|
|
fixed_point_compare::test_cases_book_i_3_3_10_fixed_point_compare(&mut retval);
|
|
fixed_point_logical::test_cases_book_i_3_3_13_fixed_point_logical(&mut retval);
|
|
fixed_point_rotate_and_shift::test_cases_book_i_3_3_14_fixed_point_rotate_and_shift(
|
|
&mut retval,
|
|
);
|
|
move_to_from_system_register::test_cases_book_i_3_3_19_move_to_from_system_register(
|
|
&mut retval,
|
|
);
|
|
prefixed_no_operation::test_cases_book_i_3_3_20_prefixed_no_operation(&mut retval);
|
|
move_to_from_system_register::test_cases_book_iii_5_4_4_move_to_from_system_register(
|
|
&mut retval,
|
|
);
|
|
retval
|
|
}
|