powerpc_asm/
types.rs

1use crate::Arguments;
2use thiserror::Error;
3
4#[derive(Error, Debug)]
5pub enum ArgumentError {
6    #[error(
7        "argument index {index} is out of range: {value} (expected between {start} and {end})"
8    )]
9    ArgOutOfRangeUnsigned { index: usize, value: u32, start: u32, end: u32 },
10    #[error(
11        "argument index {index} is out of range: {value} (expected between {start} and {end})"
12    )]
13    ArgOutOfRangeSigned { index: usize, value: i32, start: i32, end: i32 },
14    #[error("unexpected number of arguments: {value} (expected at most {expected})")]
15    ArgCount { value: usize, expected: usize },
16    #[error("unknown instruction mnemonic")]
17    UnknownMnemonic,
18}
19
20#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
21pub enum Argument {
22    #[default]
23    None,
24    Unsigned(u32),
25    Signed(i32),
26}
27
28pub const fn parse_unsigned(
29    args: &Arguments,
30    index: usize,
31    start: u32,
32    end: u32,
33) -> Result<u32, ArgumentError> {
34    match args[index] {
35        Argument::Unsigned(value) => {
36            if value >= start && value <= end {
37                Ok(value)
38            } else {
39                Err(ArgumentError::ArgOutOfRangeUnsigned { index, value, start, end })
40            }
41        }
42        Argument::Signed(value) => {
43            if value >= start as i32 && value <= end as i32 {
44                Ok(value as u32)
45            } else {
46                Err(ArgumentError::ArgOutOfRangeUnsigned { index, value: value as u32, start, end })
47            }
48        }
49        Argument::None => Err(ArgumentError::ArgCount { value: index, expected: index + 1 }),
50    }
51}
52
53pub const fn parse_signed(
54    args: &Arguments,
55    index: usize,
56    start: i32,
57    end: i32,
58) -> Result<i32, ArgumentError> {
59    match args[index] {
60        Argument::Unsigned(value) => {
61            if (start < 0 || value >= start as u32) && value <= end as u32 {
62                Ok(value as i32)
63            } else {
64                Err(ArgumentError::ArgOutOfRangeSigned { index, value: value as i32, start, end })
65            }
66        }
67        Argument::Signed(value) => {
68            if value >= start && value <= end {
69                Ok(value)
70            } else {
71                Err(ArgumentError::ArgOutOfRangeSigned { index, value, start, end })
72            }
73        }
74        Argument::None => Err(ArgumentError::ArgCount { value: index, expected: index + 1 }),
75    }
76}
77
78pub const fn arg_count(args: &Arguments) -> usize {
79    let mut i = 0;
80    while i < args.len() && !matches!(args[i], Argument::None) {
81        i += 1;
82    }
83    i
84}
85
86pub const fn check_arg_count(args: &Arguments, expected: usize) -> Result<(), ArgumentError> {
87    let value = arg_count(args);
88    if value == expected {
89        Ok(())
90    } else {
91        Err(ArgumentError::ArgCount { value, expected })
92    }
93}