1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // See Notices.txt for copyright information
8 use serde::{Deserialize, Serialize};
10 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
11 pub struct OverflowFlags {
17 pub fn from_xer(xer: u64) -> Self {
19 overflow: (xer & 0x4000_0000) != 0,
20 overflow32: (xer & 0x8_0000) != 0,
25 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
26 pub struct TestDivResult {
27 #[serde(with = "serde_hex::SerdeHex")]
29 #[serde(default, flatten, skip_serializing_if = "Option::is_none")]
30 pub overflow: Option<OverflowFlags>,
33 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
34 pub struct TestDivInput {
35 #[serde(with = "serde_hex::SerdeHex")]
37 #[serde(with = "serde_hex::SerdeHex")]
39 #[serde(with = "serde_hex::SerdeHex")]
43 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
44 pub struct TestDivCase {
45 pub instr: TestDivInstr,
47 pub inputs: TestDivInput,
49 pub outputs: TestDivResult,
52 macro_rules! make_div_functions {
56 $($div_enum:ident = $div_fn:ident ($div_instr:literal),)+
60 $($rem_enum:ident = $rem_fn:ident ($rem_instr:literal),)+
63 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
64 pub enum TestDivInstr {
66 #[serde(rename = $div_instr)]
70 #[serde(rename = $rem_instr)]
76 pub fn get_fn(self) -> fn(TestDivInput) -> TestDivResult {
79 Self::$div_enum => TestDivInput::$div_fn,
82 Self::$rem_enum => TestDivInput::$rem_fn,
86 pub fn name(self) -> &'static str {
89 Self::$div_enum => $div_instr,
92 Self::$rem_enum => $rem_instr,
96 pub const VALUES: &'static [Self] = &[
108 pub fn $div_fn(self) -> TestDivResult {
123 : "=&r"(result), "=&r"(xer)
124 : "0"(result_prev), "r"(dividend), "r"(divisor)
129 overflow: Some(OverflowFlags::from_xer(xer)),
134 pub fn $rem_fn(self) -> TestDivResult {
148 : "0"(result_prev), "r"(dividend), "r"(divisor));
160 make_div_functions! {
163 DivDE = divde("divdeo"),
164 DivDEU = divdeu("divdeuo"),
165 DivD = divd("divdo"),
166 DivDU = divdu("divduo"),
167 DivWE = divwe("divweo"),
168 DivWEU = divweu("divweuo"),
169 DivW = divw("divwo"),
170 DivWU = divwu("divwuo"),
174 ModSD = modsd("modsd"),
175 ModUD = modud("modud"),
176 ModSW = modsw("modsw"),
177 ModUW = moduw("moduw"),
181 const TEST_VALUES: &[u64] = &[
183 0xFFFF_FFFF_FFFF_FFFF,
184 0x7FFF_FFFF_FFFF_FFFF,
185 0x8000_0000_0000_0000,
186 0x1234_5678_0000_0000,
187 0x1234_5678_8000_0000,
188 0x1234_5678_FFFF_FFFF,
189 0x1234_5678_7FFF_FFFF,
193 let mut cases = Vec::new();
194 for &instr in TestDivInstr::VALUES {
195 for ÷nd in TEST_VALUES {
196 for &divisor in TEST_VALUES {
197 let inputs = TestDivInput {
200 result_prev: 0xFECD_BA98_7654_3210,
202 let outputs = instr.get_fn()(inputs);
203 cases.push(TestDivCase {
211 serde_json::to_writer_pretty(std::io::stdout().lock(), &cases).unwrap();