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