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