1use super::Emulator;
5use super::InternalError;
6use super::rflags::update_flags_szp;
7use crate::Cpu;
8use iced_x86::Instruction;
9use x86defs::RFlags;
10
11const LSB_MASK: u64 = 0x1;
12
13impl<T: Cpu> Emulator<'_, T> {
14 pub(super) async fn shift_sign_unextended<Op: ShiftingOp>(
16 &mut self,
17 instr: &Instruction,
18 ) -> Result<(), InternalError<T::Error>> {
19 let left = self.op_value(instr, 0).await?;
20 self.shift::<Op>(instr, left, 1).await
21 }
22
23 pub(super) async fn shift_arithmetic_right(
25 &mut self,
26 instr: &Instruction,
27 ) -> Result<(), InternalError<T::Error>> {
28 let left = self.op_value_sign_extend(instr, 0).await?;
29 self.shift::<SarOp>(instr, left as u64, 1).await
30 }
31
32 pub(super) async fn shld(
34 &mut self,
35 instr: &Instruction,
36 ) -> Result<(), InternalError<T::Error>> {
37 let left = self.op_value(instr, 0).await?;
38 self.shift::<ShldOp>(instr, left, 2).await
39 }
40
41 pub(super) async fn shrd(
43 &mut self,
44 instr: &Instruction,
45 ) -> Result<(), InternalError<T::Error>> {
46 let left = self.op_value(instr, 0).await?;
47 self.shift::<ShrdOp>(instr, left, 2).await
48 }
49
50 async fn shift<Op: ShiftingOp>(
52 &mut self,
53 instr: &Instruction,
54 left: u64,
55 count_op: u32,
56 ) -> Result<(), InternalError<T::Error>> {
57 let operand_size = instr.memory_size().size();
58 let operand_bit_size = operand_size as u32 * 8;
59
60 let masked_count = shift_count(self.op_value(instr, count_op).await?, operand_bit_size);
61 let count = Op::mod_count(masked_count, operand_bit_size);
62
63 let right = self.op_value(instr, 1).await?;
64 let mut rflags = self.cpu.rflags();
65
66 if count == 0 {
67 if Op::ZERO_SHIFT_UPDATES_CARRY && masked_count != 0 {
68 rflags.set_carry(Op::carry_flag(left, right, left, count, operand_bit_size));
70 self.cpu.set_rflags(rflags);
71 }
72 return Ok(());
74 }
75 let result = Op::op(left, right, count, rflags, operand_bit_size);
76 let carry = Op::carry_flag(left, right, result, count, operand_bit_size);
77
78 self.write_op_0(instr, result).await?;
79
80 if Op::UPDATE_SZP {
81 update_flags_szp(&mut rflags, operand_size, result);
82 }
83
84 rflags.set_carry(carry);
85
86 if (Op::MASKED_COUNT_UPDATES_OF && masked_count == 1)
87 || (!Op::MASKED_COUNT_UPDATES_OF && count == 1)
88 {
89 rflags.set_overflow(Op::overflow_flag(left, result, carry, operand_bit_size));
90 }
91
92 self.cpu.set_rflags(rflags);
93
94 Ok(())
95 }
96}
97
98pub(super) trait ShiftingOp {
100 const UPDATE_SZP: bool;
102 const ZERO_SHIFT_UPDATES_CARRY: bool;
105 const MASKED_COUNT_UPDATES_OF: bool;
107 fn op(left: u64, right: u64, count: u32, flags: RFlags, operand_bit_size: u32) -> u64;
109 fn mod_count(masked_count: u32, operand_bit_size: u32) -> u32;
111 fn carry_flag(left: u64, right: u64, result: u64, count: u32, operand_bit_size: u32) -> bool;
113 fn overflow_flag(left: u64, result: u64, carry_flag: bool, operand_bit_size: u32) -> bool;
115}
116
117pub(super) struct SxlOp {}
118impl ShiftingOp for SxlOp {
119 const UPDATE_SZP: bool = true;
120 const ZERO_SHIFT_UPDATES_CARRY: bool = false;
121 const MASKED_COUNT_UPDATES_OF: bool = false;
122 fn op(left: u64, _right: u64, count: u32, _flags: RFlags, _operand_bit_size: u32) -> u64 {
123 left << count
124 }
125
126 fn mod_count(masked_count: u32, _operand_bit_size: u32) -> u32 {
127 masked_count
128 }
129
130 fn carry_flag(left: u64, _right: u64, _result: u64, count: u32, operand_bit_size: u32) -> bool {
131 ((left << (count - 1)) & msb_mask(operand_bit_size)) != 0
132 }
133
134 fn overflow_flag(_left: u64, result: u64, carry_flag: bool, operand_bit_size: u32) -> bool {
135 ((msb_mask(operand_bit_size) & result) != 0) ^ carry_flag
136 }
137}
138
139struct SarOp {}
140impl ShiftingOp for SarOp {
141 const UPDATE_SZP: bool = true;
142 const ZERO_SHIFT_UPDATES_CARRY: bool = false;
143 const MASKED_COUNT_UPDATES_OF: bool = false;
144 fn op(left: u64, _right: u64, count: u32, _flags: RFlags, _operand_bit_size: u32) -> u64 {
145 ((left as i64) >> count) as u64
146 }
147
148 fn mod_count(masked_count: u32, _operand_bit_size: u32) -> u32 {
149 masked_count
150 }
151
152 fn carry_flag(
153 left: u64,
154 _right: u64,
155 _result: u64,
156 count: u32,
157 _operand_bit_size: u32,
158 ) -> bool {
159 (left >> (count - 1) & LSB_MASK) != 0
160 }
161
162 fn overflow_flag(_left: u64, _result: u64, _carry_flag: bool, _operand_bit_size: u32) -> bool {
163 false
164 }
165}
166
167pub(super) struct ShrOp {}
168impl ShiftingOp for ShrOp {
169 const UPDATE_SZP: bool = true;
170 const ZERO_SHIFT_UPDATES_CARRY: bool = false;
171 const MASKED_COUNT_UPDATES_OF: bool = false;
172 fn op(left: u64, _right: u64, count: u32, _flags: RFlags, _operand_bit_size: u32) -> u64 {
173 left >> count
174 }
175
176 fn mod_count(masked_count: u32, _operand_bit_size: u32) -> u32 {
177 masked_count
178 }
179
180 fn carry_flag(
181 left: u64,
182 _right: u64,
183 _result: u64,
184 count: u32,
185 _operand_bit_size: u32,
186 ) -> bool {
187 (left >> (count - 1) & LSB_MASK) != 0
188 }
189
190 fn overflow_flag(left: u64, _result: u64, _carry_flag: bool, operand_bit_size: u32) -> bool {
191 (msb_mask(operand_bit_size) & left) != 0
192 }
193}
194
195struct ShldOp {}
196impl ShiftingOp for ShldOp {
197 const UPDATE_SZP: bool = true;
198 const ZERO_SHIFT_UPDATES_CARRY: bool = false;
199 const MASKED_COUNT_UPDATES_OF: bool = false;
200 fn op(left: u64, right: u64, count: u32, _flags: RFlags, operand_bit_size: u32) -> u64 {
201 if operand_bit_size == 16 && count > 16 {
204 let combined: u32 = ((left as u32) << 16) | (right as u32);
205 (combined.rotate_left(count - 16) as u16).into()
206 } else {
207 (left << count) | (right >> (operand_bit_size - count))
208 }
209 }
210
211 fn mod_count(masked_count: u32, _operand_bit_size: u32) -> u32 {
212 masked_count
213 }
214
215 fn carry_flag(left: u64, right: u64, _result: u64, count: u32, operand_bit_size: u32) -> bool {
216 if operand_bit_size == 16 && count > 16 {
219 ((right >> (operand_bit_size - (count - 16))) & LSB_MASK) != 0
220 } else {
221 ((left >> (operand_bit_size - count)) & LSB_MASK) != 0
222 }
223 }
224
225 fn overflow_flag(left: u64, result: u64, _carry_flag: bool, operand_bit_size: u32) -> bool {
226 (msb_mask(operand_bit_size) & (left ^ result)) != 0
227 }
228}
229
230struct ShrdOp {}
231impl ShiftingOp for ShrdOp {
232 const UPDATE_SZP: bool = true;
233 const ZERO_SHIFT_UPDATES_CARRY: bool = false;
234 const MASKED_COUNT_UPDATES_OF: bool = false;
235 fn op(left: u64, right: u64, count: u32, _flags: RFlags, operand_bit_size: u32) -> u64 {
236 if operand_bit_size == 16 && count > 16 {
239 let combined: u32 = ((left as u32) << 16) | (right as u32);
240 (combined.rotate_right(count - 16) as u16).into()
241 } else {
242 (left >> count) | (right << (operand_bit_size - count))
243 }
244 }
245
246 fn mod_count(masked_count: u32, _operand_bit_size: u32) -> u32 {
247 masked_count
248 }
249
250 fn carry_flag(left: u64, right: u64, _result: u64, count: u32, operand_bit_size: u32) -> bool {
251 if operand_bit_size == 16 && count > 16 {
254 ((right >> (count - 17)) & LSB_MASK) != 0
255 } else {
256 ((left >> (count - 1)) & LSB_MASK) != 0
257 }
258 }
259
260 fn overflow_flag(_left: u64, result: u64, carry_flag: bool, operand_bit_size: u32) -> bool {
261 ((msb_mask(operand_bit_size) & result) != 0) ^ carry_flag
262 }
263}
264
265pub(super) struct RolOp {}
266impl ShiftingOp for RolOp {
267 const UPDATE_SZP: bool = false;
268 const ZERO_SHIFT_UPDATES_CARRY: bool = true;
269 const MASKED_COUNT_UPDATES_OF: bool = true;
270 fn op(left: u64, _right: u64, count: u32, _flags: RFlags, operand_bit_size: u32) -> u64 {
271 let result = (left << count) | (left >> (operand_bit_size - count));
272 sign_extend(result, operand_bit_size)
273 }
274
275 fn carry_flag(
276 _left: u64,
277 _right: u64,
278 result: u64,
279 _count: u32,
280 _operand_bit_size: u32,
281 ) -> bool {
282 (result & LSB_MASK) != 0
283 }
284
285 fn mod_count(masked_count: u32, operand_bit_size: u32) -> u32 {
286 rox_mod_count(masked_count, operand_bit_size)
287 }
288
289 fn overflow_flag(_left: u64, result: u64, carry_flag: bool, operand_bit_size: u32) -> bool {
290 rotate_left_overflow(result, carry_flag, operand_bit_size)
291 }
292}
293
294pub(super) struct RorOp {}
295impl ShiftingOp for RorOp {
296 const UPDATE_SZP: bool = false;
297 const ZERO_SHIFT_UPDATES_CARRY: bool = true;
298 const MASKED_COUNT_UPDATES_OF: bool = true;
299 fn op(left: u64, _right: u64, count: u32, _flags: RFlags, operand_bit_size: u32) -> u64 {
300 let result = (left >> count) | (left << (operand_bit_size - count));
301 sign_extend(result, operand_bit_size)
302 }
303
304 fn carry_flag(
305 _left: u64,
306 _right: u64,
307 result: u64,
308 _count: u32,
309 operand_bit_size: u32,
310 ) -> bool {
311 (result & msb_mask(operand_bit_size)) != 0
312 }
313
314 fn mod_count(masked_count: u32, operand_bit_size: u32) -> u32 {
315 rox_mod_count(masked_count, operand_bit_size)
316 }
317
318 fn overflow_flag(_left: u64, result: u64, carry_flag: bool, operand_bit_size: u32) -> bool {
319 rotate_right_overflow(result, carry_flag, operand_bit_size)
320 }
321}
322
323pub(super) struct RclOp {}
324impl ShiftingOp for RclOp {
325 const UPDATE_SZP: bool = false;
326 const ZERO_SHIFT_UPDATES_CARRY: bool = false;
327 const MASKED_COUNT_UPDATES_OF: bool = true;
328 fn op(left: u64, _right: u64, count: u32, flags: RFlags, operand_bit_size: u32) -> u64 {
329 let result = (left << count)
330 | ((flags.carry() as u64) << (count - 1))
331 | ((left as u128) >> ((operand_bit_size + 1) - count)) as u64; sign_extend(result, operand_bit_size)
333 }
334
335 fn mod_count(masked_count: u32, operand_bit_size: u32) -> u32 {
336 rcx_mod_count(masked_count, operand_bit_size)
337 }
338
339 fn carry_flag(left: u64, _right: u64, _result: u64, count: u32, operand_bit_size: u32) -> bool {
340 ((left >> (operand_bit_size - count)) & LSB_MASK) != 0
341 }
342
343 fn overflow_flag(_left: u64, result: u64, carry_flag: bool, operand_bit_size: u32) -> bool {
344 rotate_left_overflow(result, carry_flag, operand_bit_size)
345 }
346}
347
348pub(super) struct RcrOp {}
349impl ShiftingOp for RcrOp {
350 const UPDATE_SZP: bool = false;
351 const ZERO_SHIFT_UPDATES_CARRY: bool = false;
352 const MASKED_COUNT_UPDATES_OF: bool = true;
353 fn op(left: u64, _right: u64, count: u32, flags: RFlags, operand_bit_size: u32) -> u64 {
354 let result = (left >> count)
355 | ((flags.carry() as u64) << (operand_bit_size - count))
356 | ((left as u128) << ((operand_bit_size + 1) - count)) as u64; sign_extend(result, operand_bit_size)
358 }
359
360 fn mod_count(masked_count: u32, operand_bit_size: u32) -> u32 {
361 rcx_mod_count(masked_count, operand_bit_size)
362 }
363
364 fn carry_flag(
365 left: u64,
366 _right: u64,
367 _result: u64,
368 count: u32,
369 _operand_bit_size: u32,
370 ) -> bool {
371 ((left >> (count - 1)) & LSB_MASK) != 0
372 }
373
374 fn overflow_flag(_left: u64, result: u64, carry_flag: bool, operand_bit_size: u32) -> bool {
375 rotate_right_overflow(result, carry_flag, operand_bit_size)
376 }
377}
378
379fn msb_mask(operand_bit_size: u32) -> u64 {
381 match operand_bit_size {
382 8 => 0x80,
383 16 => 0x8000,
384 32 => 0x80000000,
385 64 => 0x8000000000000000,
386 _ => unreachable!(),
387 }
388}
389
390fn rcx_mod_count(masked_count: u32, operand_bit_size: u32) -> u32 {
391 if operand_bit_size == 8 {
392 masked_count % 9
393 } else if operand_bit_size == 16 {
394 masked_count % 17
395 } else {
396 masked_count
397 }
398}
399
400fn rox_mod_count(masked_count: u32, operand_bit_size: u32) -> u32 {
401 masked_count % operand_bit_size
402}
403
404fn sign_extend(value: u64, operand_bit_size: u32) -> u64 {
406 let sign_shift = 64 - operand_bit_size;
407 (((value as i64) << sign_shift) >> sign_shift) as u64
408}
409
410fn shift_count(right: u64, operand_bit_size: u32) -> u32 {
412 (if operand_bit_size == 64 {
413 right & 0x3f
414 } else {
415 right & 0x1f
416 }) as u32
417}
418
419fn rotate_right_overflow(result: u64, _carry_flag: bool, operand_bit_size: u32) -> bool {
421 let mask = msb_mask(operand_bit_size);
422 let msb = (result & mask) != 0;
423 let second_msb = (result & (mask >> 1)) != 0;
424 msb ^ second_msb
425}
426
427fn rotate_left_overflow(result: u64, carry_flag: bool, operand_bit_size: u32) -> bool {
429 ((msb_mask(operand_bit_size) & result) != 0) ^ carry_flag
430}