cranelift_codegen/isa/s390x/inst/
imms.rs

1//! S390x ISA definitions: immediate constants.
2
3use crate::machinst::PrettyPrint;
4use std::string::String;
5
6/// An unsigned 12-bit immediate.
7#[derive(Clone, Copy, Debug)]
8pub struct UImm12 {
9    /// The value.
10    value: u16,
11}
12
13impl UImm12 {
14    pub fn maybe_from_u64(value: u64) -> Option<UImm12> {
15        if value < 4096 {
16            Some(UImm12 {
17                value: value as u16,
18            })
19        } else {
20            None
21        }
22    }
23
24    /// Create a zero immediate of this format.
25    pub fn zero() -> UImm12 {
26        UImm12 { value: 0 }
27    }
28
29    /// Bits for encoding.
30    pub fn bits(&self) -> u32 {
31        u32::from(self.value)
32    }
33}
34
35/// A signed 20-bit immediate.
36#[derive(Clone, Copy, Debug)]
37pub struct SImm20 {
38    /// The value.
39    value: i32,
40}
41
42impl SImm20 {
43    pub fn maybe_from_i64(value: i64) -> Option<SImm20> {
44        if value >= -524288 && value < 524288 {
45            Some(SImm20 {
46                value: value as i32,
47            })
48        } else {
49            None
50        }
51    }
52
53    pub fn from_uimm12(value: UImm12) -> SImm20 {
54        SImm20 {
55            value: value.bits() as i32,
56        }
57    }
58
59    /// Bits for encoding.
60    pub fn bits(&self) -> u32 {
61        let encoded: u32 = self.value as u32;
62        encoded & 0xfffff
63    }
64}
65
66/// A 16-bit immediate with a {0,16,32,48}-bit shift.
67#[derive(Clone, Copy, Debug)]
68pub struct UImm16Shifted {
69    /// The value.
70    pub bits: u16,
71    /// Result is `bits` shifted 16*shift bits to the left.
72    pub shift: u8,
73}
74
75impl UImm16Shifted {
76    /// Construct a UImm16Shifted from an arbitrary 64-bit constant if possible.
77    pub fn maybe_from_u64(value: u64) -> Option<UImm16Shifted> {
78        let mask0 = 0x0000_0000_0000_ffffu64;
79        let mask1 = 0x0000_0000_ffff_0000u64;
80        let mask2 = 0x0000_ffff_0000_0000u64;
81        let mask3 = 0xffff_0000_0000_0000u64;
82
83        if value == (value & mask0) {
84            return Some(UImm16Shifted {
85                bits: (value & mask0) as u16,
86                shift: 0,
87            });
88        }
89        if value == (value & mask1) {
90            return Some(UImm16Shifted {
91                bits: ((value >> 16) & mask0) as u16,
92                shift: 1,
93            });
94        }
95        if value == (value & mask2) {
96            return Some(UImm16Shifted {
97                bits: ((value >> 32) & mask0) as u16,
98                shift: 2,
99            });
100        }
101        if value == (value & mask3) {
102            return Some(UImm16Shifted {
103                bits: ((value >> 48) & mask0) as u16,
104                shift: 3,
105            });
106        }
107        None
108    }
109
110    pub fn maybe_with_shift(imm: u16, shift: u8) -> Option<UImm16Shifted> {
111        let shift_enc = shift / 16;
112        if shift_enc > 3 {
113            None
114        } else {
115            Some(UImm16Shifted {
116                bits: imm,
117                shift: shift_enc,
118            })
119        }
120    }
121
122    pub fn negate_bits(&self) -> UImm16Shifted {
123        UImm16Shifted {
124            bits: !self.bits,
125            shift: self.shift,
126        }
127    }
128}
129
130/// A 32-bit immediate with a {0,32}-bit shift.
131#[derive(Clone, Copy, Debug)]
132pub struct UImm32Shifted {
133    /// The value.
134    pub bits: u32,
135    /// Result is `bits` shifted 32*shift bits to the left.
136    pub shift: u8,
137}
138
139impl UImm32Shifted {
140    /// Construct a UImm32Shifted from an arbitrary 64-bit constant if possible.
141    pub fn maybe_from_u64(value: u64) -> Option<UImm32Shifted> {
142        let mask0 = 0x0000_0000_ffff_ffffu64;
143        let mask1 = 0xffff_ffff_0000_0000u64;
144
145        if value == (value & mask0) {
146            return Some(UImm32Shifted {
147                bits: (value & mask0) as u32,
148                shift: 0,
149            });
150        }
151        if value == (value & mask1) {
152            return Some(UImm32Shifted {
153                bits: ((value >> 32) & mask0) as u32,
154                shift: 1,
155            });
156        }
157        None
158    }
159
160    pub fn maybe_with_shift(imm: u32, shift: u8) -> Option<UImm32Shifted> {
161        let shift_enc = shift / 32;
162        if shift_enc > 3 {
163            None
164        } else {
165            Some(UImm32Shifted {
166                bits: imm,
167                shift: shift_enc,
168            })
169        }
170    }
171
172    pub fn negate_bits(&self) -> UImm32Shifted {
173        UImm32Shifted {
174            bits: !self.bits,
175            shift: self.shift,
176        }
177    }
178}
179
180impl PrettyPrint for UImm12 {
181    fn pretty_print(&self, _: u8) -> String {
182        format!("{}", self.value)
183    }
184}
185
186impl PrettyPrint for SImm20 {
187    fn pretty_print(&self, _: u8) -> String {
188        format!("{}", self.value)
189    }
190}
191
192impl PrettyPrint for UImm16Shifted {
193    fn pretty_print(&self, _: u8) -> String {
194        format!("{}", self.bits)
195    }
196}
197
198impl PrettyPrint for UImm32Shifted {
199    fn pretty_print(&self, _: u8) -> String {
200        format!("{}", self.bits)
201    }
202}