add cmprb_0
[power-instruction-analyzer.git] / src / main.rs
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // See Notices.txt for copyright information
3
4 use power_instruction_analyzer::{
5 CarryFlags, Instr, InstructionInput, InstructionInputRegister, MissingInstructionInput,
6 OverflowFlags, TestCase, WholeTest,
7 };
8
9 const TEST_VALUES: &[u64] = &[
10 0x0,
11 0x1,
12 0x2,
13 0xFFFF_FFFF_FFFF_FFFF,
14 0xFFFF_FFFF_FFFF_FFFE,
15 0x7FFF_FFFF_FFFF_FFFE,
16 0x7FFF_FFFF_FFFF_FFFF,
17 0x8000_0000_0000_0000,
18 0x8000_0000_0000_0001,
19 0x1234_5678_0000_0000,
20 0x1234_5678_7FFF_FFFE,
21 0x1234_5678_7FFF_FFFF,
22 0x1234_5678_8000_0000,
23 0x1234_5678_8000_0001,
24 0x1234_5678_FFFF_FFFF,
25 0x7FFE,
26 0x7FFF,
27 0x8000,
28 0x8001,
29 // picked for cmprb
30 0xFFED_CBA9_8765_4321,
31 // last byte of next 12 tests limits of ranges for cmprb
32 0x85AE_16A6_0C1A_0E1F,
33 0xCF24_50C7_9E7E_DF20,
34 0xD486_2724_930B_9021,
35 0xDDBA_3880_8588_DF42,
36 0x1F07_F322_68FE_5C43,
37 0x739D_46C6_1E05_AE44,
38 0xA131_E014_B201_9064,
39 0xC70D_BC09_C48A_C665,
40 0x1D61_5696_5920_E966,
41 0x70F1_F260_8938_4486,
42 0xEF25_5D74_1B45_CA87,
43 0x3C54_DFA8_C006_5688,
44 ];
45
46 const IMMED16_TEST_VALUES: &[u16] = &[
47 0x0, 0x1, 0x2, 0xFFFF, 0xFFFE, 0x7FFE, 0x7FFF, 0x8000, 0x8001,
48 ];
49
50 const BOOL_VALUES: &[bool] = &[false, true];
51
52 fn call_with_inputs(
53 mut inputs: InstructionInput,
54 input_registers: &[InstructionInputRegister],
55 f: &mut impl FnMut(InstructionInput) -> Result<(), MissingInstructionInput>,
56 ) -> Result<(), MissingInstructionInput> {
57 if let Some((&input_register, input_registers)) = input_registers.split_first() {
58 match input_register {
59 InstructionInputRegister::Ra => {
60 for &i in TEST_VALUES {
61 inputs.ra = Some(i);
62 call_with_inputs(inputs, input_registers, f)?;
63 }
64 }
65 InstructionInputRegister::Rb => {
66 for &i in TEST_VALUES {
67 inputs.rb = Some(i);
68 call_with_inputs(inputs, input_registers, f)?;
69 }
70 }
71 InstructionInputRegister::Rc => {
72 for &i in TEST_VALUES {
73 inputs.rc = Some(i);
74 call_with_inputs(inputs, input_registers, f)?;
75 }
76 }
77 InstructionInputRegister::ImmediateS16 => {
78 for &i in IMMED16_TEST_VALUES {
79 inputs.immediate = Some(i as i16 as u64);
80 call_with_inputs(inputs, input_registers, f)?;
81 }
82 }
83 InstructionInputRegister::ImmediateU16 => {
84 for &i in IMMED16_TEST_VALUES {
85 inputs.immediate = Some(i as u64);
86 call_with_inputs(inputs, input_registers, f)?;
87 }
88 }
89 InstructionInputRegister::Carry => {
90 for &ca in BOOL_VALUES {
91 for &ca32 in BOOL_VALUES {
92 inputs.carry = Some(CarryFlags { ca, ca32 });
93 call_with_inputs(inputs, input_registers, f)?;
94 }
95 }
96 }
97 InstructionInputRegister::Overflow => {
98 for &so in BOOL_VALUES {
99 for &ov in BOOL_VALUES {
100 for &ov32 in BOOL_VALUES {
101 inputs.overflow = Some(OverflowFlags { so, ov, ov32 });
102 call_with_inputs(inputs, input_registers, f)?;
103 }
104 }
105 }
106 }
107 }
108 } else {
109 f(inputs)?;
110 }
111 Ok(())
112 }
113
114 fn main() -> Result<(), String> {
115 let mut test_cases = Vec::new();
116 let mut any_model_mismatch = false;
117 for &instr in Instr::VALUES {
118 call_with_inputs(
119 InstructionInput::default(),
120 instr.get_used_input_registers(),
121 &mut |inputs| -> Result<(), _> {
122 let model_outputs = instr.get_model_fn()(inputs)?;
123 #[cfg(feature = "native_instrs")]
124 let native_outputs = Some(instr.get_native_fn()(inputs)?);
125 #[cfg(not(feature = "native_instrs"))]
126 let native_outputs = None;
127 let model_mismatch = match native_outputs {
128 Some(native_outputs) if native_outputs != model_outputs => true,
129 _ => false,
130 };
131 any_model_mismatch |= model_mismatch;
132 test_cases.push(TestCase {
133 instr,
134 inputs,
135 native_outputs,
136 model_outputs,
137 model_mismatch,
138 });
139 Ok(())
140 },
141 )
142 .map_err(|err| format!("instruction {}: {}", instr.name(), err))?;
143 }
144 let whole_test = WholeTest {
145 test_cases,
146 any_model_mismatch,
147 };
148 serde_json::to_writer_pretty(std::io::stdout().lock(), &whole_test).unwrap();
149 println!();
150 Ok(())
151 }