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