1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 // See Notices.txt for copyright information
4 #![cfg_attr(feature = "native_instrs", feature(llvm_asm))]
6 #[cfg(all(feature = "native_instrs", not(target_arch = "powerpc64")))]
7 compile_error!("native_instrs feature requires target_arch to be powerpc64");
13 use serde::{Deserialize, Serialize};
15 #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
16 pub struct OverflowFlags {
22 pub fn from_xer(xer: u64) -> Self {
24 overflow: (xer & 0x4000_0000) != 0,
25 overflow32: (xer & 0x8_0000) != 0,
30 #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
31 pub struct DivResult {
32 #[serde(with = "serde_hex::SerdeHex")]
34 #[serde(default, flatten, skip_serializing_if = "Option::is_none")]
35 pub overflow: Option<OverflowFlags>,
38 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
40 #[serde(with = "serde_hex::SerdeHex")]
42 #[serde(with = "serde_hex::SerdeHex")]
44 #[serde(default, with = "serde_hex::SerdeHex")]
48 fn is_false(v: &bool) -> bool {
52 #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
53 pub struct TestDivCase {
57 #[serde(default, skip_serializing_if = "Option::is_none")]
58 pub native_outputs: Option<DivResult>,
59 pub model_outputs: DivResult,
60 #[serde(default, skip_serializing_if = "is_false")]
61 pub model_mismatch: bool,
64 #[derive(Clone, Debug, Serialize, Deserialize)]
65 pub struct WholeTest {
66 #[serde(default, skip_serializing_if = "Vec::is_empty")]
67 pub test_div_cases: Vec<TestDivCase>,
68 pub any_model_mismatch: bool,
71 macro_rules! make_div_functions {
75 $($div_enum:ident = $div_fn:ident ($div_instr:literal),)+
79 $($rem_enum:ident = $rem_fn:ident ($rem_instr:literal),)+
82 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
85 #[serde(rename = $div_instr)]
89 #[serde(rename = $rem_instr)]
95 #[cfg(feature = "native_instrs")]
96 pub fn get_native_fn(self) -> fn(DivInput) -> DivResult {
99 Self::$div_enum => native_instrs::$div_fn,
102 Self::$rem_enum => native_instrs::$rem_fn,
106 pub fn get_model_fn(self) -> fn(DivInput) -> DivResult {
109 Self::$div_enum => instr_models::$div_fn,
112 Self::$rem_enum => instr_models::$rem_fn,
116 pub fn name(self) -> &'static str {
119 Self::$div_enum => $div_instr,
122 Self::$rem_enum => $rem_instr,
126 pub const VALUES: &'static [Self] = &[
136 #[cfg(feature = "native_instrs")]
137 pub mod native_instrs {
141 pub fn $div_fn(inputs: DivInput) -> DivResult {
156 : "=&r"(result), "=&r"(xer)
157 : "0"(result_prev), "r"(dividend), "r"(divisor)
162 overflow: Some(OverflowFlags::from_xer(xer)),
167 pub fn $rem_fn(inputs: DivInput) -> DivResult {
181 : "0"(result_prev), "r"(dividend), "r"(divisor));
193 make_div_functions! {
196 DivDEO = divdeo("divdeo"),
197 DivDEUO = divdeuo("divdeuo"),
198 DivDO = divdo("divdo"),
199 DivDUO = divduo("divduo"),
200 DivWEO = divweo("divweo"),
201 DivWEUO = divweuo("divweuo"),
202 DivWO = divwo("divwo"),
203 DivWUO = divwuo("divwuo"),
207 ModSD = modsd("modsd"),
208 ModUD = modud("modud"),
209 ModSW = modsw("modsw"),
210 ModUW = moduw("moduw"),