1use crate::api::CodeSink;
4use std::fmt;
5
6macro_rules! hexify {
10 ($n:expr) => {
11 format!("$0x{:x}", $n)
12 };
13}
14
15macro_rules! hexify_sign_extend {
17 ($n:expr, $from:ty => $to:ty) => {{
18 let from: $from = $n; let to = <$to>::from(from);
20 format!("$0x{:x}", to)
21 }};
22}
23
24#[derive(Clone, Copy, Debug)]
26#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
27pub struct Imm8(u8);
28
29impl Imm8 {
30 #[must_use]
31 pub fn new(value: u8) -> Self {
32 Self(value)
33 }
34
35 #[must_use]
36 pub fn value(&self) -> u8 {
37 self.0
38 }
39
40 pub fn encode(&self, sink: &mut impl CodeSink) {
41 sink.put1(self.0);
42 }
43}
44
45impl From<u8> for Imm8 {
46 fn from(imm8: u8) -> Self {
47 Self(imm8)
48 }
49}
50
51impl TryFrom<i32> for Imm8 {
52 type Error = std::num::TryFromIntError;
53 fn try_from(simm32: i32) -> Result<Self, Self::Error> {
54 Ok(Self(u8::try_from(simm32)?))
55 }
56}
57
58impl fmt::Display for Imm8 {
59 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60 write!(f, "$0x{:x}", self.0)
61 }
62}
63
64#[derive(Clone, Copy, Debug)]
66#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
67pub struct Simm8(i8);
68
69impl Simm8 {
70 #[must_use]
71 pub fn new(value: i8) -> Self {
72 Self(value)
73 }
74
75 #[must_use]
76 pub fn value(&self) -> i8 {
77 self.0
78 }
79
80 pub fn encode(&self, sink: &mut impl CodeSink) {
81 sink.put1(self.0 as u8);
82 }
83
84 #[must_use]
85 pub fn to_string(&self, extend: Extension) -> String {
86 use Extension::{None, SignExtendLong, SignExtendQuad, SignExtendWord};
87 match extend {
88 None => hexify!(self.0),
89 SignExtendWord => hexify_sign_extend!(self.0, i8 => i16),
90 SignExtendLong => hexify_sign_extend!(self.0, i8 => i32),
91 SignExtendQuad => hexify_sign_extend!(self.0, i8 => i64),
92 }
93 }
94}
95
96impl From<i8> for Simm8 {
97 fn from(simm8: i8) -> Self {
98 Self(simm8)
99 }
100}
101
102impl TryFrom<i32> for Simm8 {
103 type Error = std::num::TryFromIntError;
104 fn try_from(simm32: i32) -> Result<Self, Self::Error> {
105 Ok(Self(i8::try_from(simm32)?))
106 }
107}
108
109#[derive(Copy, Clone, Debug)]
111#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
112pub struct Imm16(u16);
113
114impl Imm16 {
115 #[must_use]
116 pub fn new(value: u16) -> Self {
117 Self(value)
118 }
119
120 #[must_use]
121 pub fn value(&self) -> u16 {
122 self.0
123 }
124
125 pub fn encode(&self, sink: &mut impl CodeSink) {
126 sink.put2(self.0);
127 }
128}
129
130impl From<u16> for Imm16 {
131 fn from(imm16: u16) -> Self {
132 Self(imm16)
133 }
134}
135
136impl TryFrom<i32> for Imm16 {
137 type Error = std::num::TryFromIntError;
138 fn try_from(simm32: i32) -> Result<Self, Self::Error> {
139 Ok(Self(u16::try_from(simm32)?))
140 }
141}
142
143impl fmt::Display for Imm16 {
144 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145 write!(f, "$0x{:x}", self.0)
146 }
147}
148
149#[derive(Copy, Clone, Debug)]
151#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
152pub struct Simm16(i16);
153
154impl Simm16 {
155 #[must_use]
156 pub fn new(value: i16) -> Self {
157 Self(value)
158 }
159
160 #[must_use]
161 pub fn value(&self) -> i16 {
162 self.0
163 }
164
165 pub fn encode(&self, sink: &mut impl CodeSink) {
166 sink.put2(self.0 as u16);
167 }
168
169 #[must_use]
170 pub fn to_string(&self, extend: Extension) -> String {
171 use Extension::{None, SignExtendLong, SignExtendQuad, SignExtendWord};
172 match extend {
173 None => hexify!(self.0),
174 SignExtendWord => unreachable!("the 16-bit value is already 16 bits"),
175 SignExtendLong => hexify_sign_extend!(self.0, i16 => i32),
176 SignExtendQuad => hexify_sign_extend!(self.0, i16 => i64),
177 }
178 }
179}
180
181impl From<i16> for Simm16 {
182 fn from(simm16: i16) -> Self {
183 Self(simm16)
184 }
185}
186
187impl TryFrom<i32> for Simm16 {
188 type Error = std::num::TryFromIntError;
189 fn try_from(simm32: i32) -> Result<Self, Self::Error> {
190 Ok(Self(i16::try_from(simm32)?))
191 }
192}
193
194#[derive(Copy, Clone, Debug)]
200#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
201pub struct Imm32(u32);
202
203impl Imm32 {
204 #[must_use]
205 pub fn new(value: u32) -> Self {
206 Self(value)
207 }
208
209 #[must_use]
210 pub fn value(&self) -> u32 {
211 self.0
212 }
213
214 pub fn encode(&self, sink: &mut impl CodeSink) {
215 sink.put4(self.0);
216 }
217}
218
219impl From<u32> for Imm32 {
220 fn from(imm32: u32) -> Self {
221 Self(imm32)
222 }
223}
224
225impl From<i32> for Imm32 {
226 fn from(simm32: i32) -> Self {
227 Self(simm32 as u32)
229 }
230}
231
232impl fmt::Display for Imm32 {
233 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234 write!(f, "$0x{:x}", self.0)
235 }
236}
237
238#[derive(Copy, Clone, Debug)]
244#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
245pub struct Simm32(i32);
246
247impl Simm32 {
248 #[must_use]
249 pub fn new(value: i32) -> Self {
250 Self(value)
251 }
252
253 #[must_use]
254 pub fn value(&self) -> i32 {
255 self.0
256 }
257
258 pub fn encode(&self, sink: &mut impl CodeSink) {
259 sink.put4(self.0 as u32);
260 }
261
262 #[must_use]
263 pub fn to_string(&self, extend: Extension) -> String {
264 use Extension::{None, SignExtendLong, SignExtendQuad, SignExtendWord};
265 match extend {
266 None => hexify!(self.0),
267 SignExtendWord => unreachable!("cannot sign extend a 32-bit value to 16 bits"),
268 SignExtendLong => unreachable!("the 32-bit value is already 32 bits"),
269 SignExtendQuad => hexify_sign_extend!(self.0, i32 => i64),
270 }
271 }
272}
273
274impl From<i32> for Simm32 {
275 fn from(simm32: i32) -> Self {
276 Self(simm32)
277 }
278}
279
280#[derive(Copy, Clone, Debug)]
284#[cfg_attr(any(test, feature = "fuzz"), derive(arbitrary::Arbitrary))]
285pub struct Imm64(u64);
286
287impl Imm64 {
288 #[must_use]
289 pub fn new(value: u64) -> Self {
290 Self(value)
291 }
292
293 #[must_use]
294 pub fn value(&self) -> u64 {
295 self.0
296 }
297
298 pub fn encode(&self, sink: &mut impl CodeSink) {
299 sink.put8(self.0);
300 }
301}
302
303impl From<u64> for Imm64 {
304 fn from(imm64: u64) -> Self {
305 Self(imm64)
306 }
307}
308
309impl fmt::Display for Imm64 {
310 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311 write!(f, "$0x{:x}", self.0)
312 }
313}
314
315#[derive(Clone, Copy, Debug)]
317pub enum Extension {
318 None,
319 SignExtendQuad,
320 SignExtendLong,
321 SignExtendWord,
322}