msp430_asm/
jxx.rs

1use std::fmt;
2
3pub fn jxx_fix_offset(offset: u16) -> i16 {
4    if offset & 0b10_0000_0000 > 0 {
5        (offset | 0xfc00) as i16
6    } else {
7        offset as i16
8    }
9}
10
11/// All jxx instructions implement this trait to provide a common interface
12/// and polymorphism
13pub trait Jxx {
14    fn mnemonic(&self) -> &str;
15    fn offset(&self) -> i16;
16    fn size(&self) -> usize;
17}
18
19macro_rules! jxx {
20    ($t:ident, $n:expr) => {
21        #[derive(Debug, Clone, Copy, PartialEq)]
22        pub struct $t {
23            offset: i16,
24        }
25
26        impl $t {
27            pub fn new(offset: i16) -> $t {
28                $t { offset }
29            }
30        }
31
32        impl Jxx for $t {
33            fn mnemonic(&self) -> &str {
34                $n
35            }
36
37            fn offset(&self) -> i16 {
38                self.offset
39            }
40
41            fn size(&self) -> usize {
42                2
43            }
44        }
45
46        impl fmt::Display for $t {
47            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48                // LowerHex will treat hex numbers as unsigned so rather than
49                // -0x6 we get 0xfffa. This is expected functionality and
50                // unlikely to change. This is a working hack for now but we
51                // should probably implement a better fix that is more
52                // efficient https://github.com/rust-lang/rust/issues/42860
53                if self.offset < 0 {
54                    write!(f, "{} #-{:#x}", $n, -self.offset)
55                } else {
56                    write!(f, "{} #{:#x}", $n, self.offset)
57                }
58            }
59        }
60    };
61}
62
63jxx!(Jnz, "jnz");
64jxx!(Jz, "jz");
65jxx!(Jlo, "jlo");
66jxx!(Jc, "jc");
67jxx!(Jn, "jn");
68jxx!(Jge, "jge");
69jxx!(Jl, "jl");
70jxx!(Jmp, "jmp");