1use crate::options::Numproc;
7use std::cmp::Ordering;
8use zarch::check::ProgramCheck;
9use zarch::decimal::{self, MINUS, PLUS, UNSIGNED};
10
11pub const fn preferred(negative: bool, signed: bool) -> u8 {
12 match (signed, negative) {
13 (false, _) => UNSIGNED,
14 (true, true) => MINUS,
15 (true, false) => PLUS,
16 }
17}
18
19pub fn move_packed(source: &[u8], receiver_signed: bool, numproc: Numproc) -> Vec<u8> {
21 let mut out = source.to_vec();
22 if numproc == Numproc::Nopfd {
23 let last = out.last_mut().expect("a packed item is at least one byte");
24 let negative = decimal::is_minus(*last & 0xF);
25 *last = (*last & 0xF0) | preferred(negative, receiver_signed);
26 }
27 out
28}
29
30pub fn compare_packed(a: &[u8], b: &[u8], numproc: Numproc) -> Result<Ordering, ProgramCheck> {
32 match numproc {
33 Numproc::Nopfd => Ok(decimal::cp(a, b)?.ordering().unwrap_or(Ordering::Greater)),
34 Numproc::Pfd => Ok(a.cmp(b)),
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn nopfd_repairs_the_sign_on_a_move_and_pfd_copies_it() {
44 assert_eq!(move_packed(&[0x12, 0x3A], true, Numproc::Nopfd), [0x12, 0x3C]);
45 assert_eq!(move_packed(&[0x12, 0x3B], true, Numproc::Nopfd), [0x12, 0x3D]);
46 assert_eq!(move_packed(&[0x12, 0x3C], false, Numproc::Nopfd), [0x12, 0x3F]);
47 assert_eq!(move_packed(&[0x12, 0x3A], true, Numproc::Pfd), [0x12, 0x3A]);
48 }
49
50 #[test]
51 fn plus_signs_f_and_c_are_equal_only_under_nopfd() {
52 assert_eq!(compare_packed(&[0x1F], &[0x1C], Numproc::Nopfd), Ok(Ordering::Equal));
53 assert_eq!(compare_packed(&[0x1F], &[0x1C], Numproc::Pfd), Ok(Ordering::Greater));
54 }
55
56 #[test]
57 fn nopfd_comparison_of_an_invalid_sign_is_a_data_exception() {
58 assert_eq!(compare_packed(&[0x14], &[0x1C], Numproc::Nopfd), Err(ProgramCheck::Data));
59 }
60}