mos_hardware/mega65/
math.rs

1// copyright 2023 mikael lund aka wombat
2//
3// licensed under the apache license, version 2.0 (the "license");
4// you may not use this file except in compliance with the license.
5// you may obtain a copy of the license at
6//
7//     http://www.apache.org/licenses/license-2.0
8//
9// unless required by applicable law or agreed to in writing, software
10// distributed under the license is distributed on an "as is" basis,
11// without warranties or conditions of any kind, either express or implied.
12// see the license for the specific language governing permissions and
13// limitations under the license.
14
15//! Mathematical support functions
16
17use super::MATH_STATUS;
18use bitflags::bitflags;
19use volatile_register::{RO, WO};
20
21bitflags! {
22    /// Control flags for hardware multiplier/divider
23    pub struct StatusFlags: u8 {
24        const DIVBUSY = 0b1000_0000; // bit 7
25        const MULBUSY = 0b0100_0000; // bit 6
26    }
27}
28
29/// Registers for Math Acceleration
30///
31/// See the MEGA64 book, Section G-19.
32/// The hardware registers use little endian storage.
33#[repr(C, packed)]
34pub struct MathAccelerator {
35    /// 32-bit fractional part DIVOUT(0-3) of MULTINA divided by MULTINB
36    pub divout_fraction: RO<u32>, // 0x00
37    /// 32-bit whole part DIVOUT(4-7) of MULTINA divided by MULTINB
38    pub divout_whole: RO<u32>, // 0x04
39    /// 32-bit input A
40    pub multin_a: WO<u32>, // 0x08
41    /// 32-bit input B
42    pub multin_b: WO<u32>, // 0x0c
43    /// 64-bit product MULTOUT of MULTINA and MULTINB
44    pub multout: RO<u64>, // 0x10
45}
46
47impl MathAccelerator {
48    /// 32 bit multiplication using hardware multiplier
49    ///
50    /// Cycles: 1
51    pub fn multiply(&self, a: u32, b: u32) -> u64 {
52        unsafe {
53            self.multin_a.write(a);
54            self.multin_b.write(b);
55        }
56        self.multout.read()
57    }
58
59    /// 32 bit multiplication and division using hardware multiplier
60    ///
61    /// Returns a tuple with:
62    /// 1. 64-bit `a x b` product
63    /// 2. 32-bit whole part of `a / b`;
64    /// 3. 32-bit fractional part of `a / b`
65    ///
66    /// Cycles: less than 20
67    pub fn multiply_divide(&self, a: u32, b: u32) -> (u64, u32, u32) {
68        let product = self.multiply(a, b);
69        while unsafe { &(*MATH_STATUS) }
70            .read()
71            .contains(StatusFlags::DIVBUSY)
72        {}
73        (
74            product,
75            self.divout_whole.read(),
76            self.divout_fraction.read(),
77        )
78    }
79}