1use crate::cpu::cpu::*;
2use crate::cpu::global_pointers::*;
3use crate::cpu::memory;
4use crate::cpu::misc_instr::{getaf, getcf, getzf};
5
6fn int_log2(x: i32) -> i32 {
7 31 - x.leading_zeros() as i32
8}
9
10fn opsize_to_mask(op_size: i32) -> i32 {
11 dbg_assert!(op_size == OPSIZE_8 || op_size == OPSIZE_16 || op_size == OPSIZE_32);
12 (2i32.wrapping_shl(op_size as u32)).wrapping_sub(1)
13}
14
15unsafe fn add(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 {
16 let res = dest_operand.wrapping_add(source_operand) & opsize_to_mask(op_size);
17 *last_op1 = dest_operand;
18 *last_result = res;
19 *last_op_size = op_size;
20 *flags_changed = FLAGS_ALL;
21 return res;
22}
23unsafe fn adc(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 {
24 let cf = getcf() as i32;
25 let res = dest_operand.wrapping_add(source_operand).wrapping_add(cf) & opsize_to_mask(op_size);
26 *last_op1 = dest_operand;
27 *last_result = res;
28 *last_op_size = op_size;
29 *flags_changed = FLAGS_ALL & !FLAG_CARRY & !FLAG_ADJUST & !FLAG_OVERFLOW;
30 *flags = *flags & !FLAG_CARRY & !FLAG_ADJUST & !FLAG_OVERFLOW
31 | (dest_operand ^ ((dest_operand ^ source_operand) & (source_operand ^ res))) >> op_size
32 & FLAG_CARRY
33 | (dest_operand ^ source_operand ^ res) & FLAG_ADJUST
34 | ((source_operand ^ res) & (dest_operand ^ res)) >> op_size << 11 & FLAG_OVERFLOW;
35 return res;
36}
37unsafe fn sub(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 {
38 let res = dest_operand.wrapping_sub(source_operand) & opsize_to_mask(op_size);
39 *last_op1 = dest_operand;
40 *last_result = res;
41 *last_op_size = op_size;
42 *flags_changed = FLAGS_ALL | FLAG_SUB;
43 return res;
44}
45unsafe fn sbb(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 {
46 let cf = getcf() as i32;
47 let res = dest_operand.wrapping_sub(source_operand).wrapping_sub(cf) & opsize_to_mask(op_size);
48 *last_op1 = dest_operand;
49 *last_result = res;
50 *last_op_size = op_size;
51 *flags_changed = FLAGS_ALL & !FLAG_CARRY & !FLAG_ADJUST & !FLAG_OVERFLOW | FLAG_SUB;
52 *flags = *flags & !FLAG_CARRY & !FLAG_ADJUST & !FLAG_OVERFLOW
53 | (res ^ ((res ^ source_operand) & (source_operand ^ dest_operand))) >> op_size
54 & FLAG_CARRY
55 | (dest_operand ^ source_operand ^ res) & FLAG_ADJUST
56 | ((source_operand ^ dest_operand) & (res ^ dest_operand)) >> op_size << 11 & FLAG_OVERFLOW;
57 return res;
58}
59pub unsafe fn add8(x: i32, y: i32) -> i32 {
60 dbg_assert!(x >= 0 && x < 0x100);
61 dbg_assert!(y >= 0 && y < 0x100);
62 return add(x, y, OPSIZE_8);
63}
64#[no_mangle]
65pub unsafe fn add16(x: i32, y: i32) -> i32 {
66 dbg_assert!(x >= 0 && x < 0x10000);
67 dbg_assert!(y >= 0 && y < 0x10000);
68 return add(x, y, OPSIZE_16);
69}
70pub unsafe fn add32(x: i32, y: i32) -> i32 {
71 return add(x, y, OPSIZE_32);
72}
73pub unsafe fn sub8(x: i32, y: i32) -> i32 {
74 return sub(x, y, OPSIZE_8);
75}
76#[no_mangle]
77pub unsafe fn sub16(x: i32, y: i32) -> i32 {
78 return sub(x, y, OPSIZE_16);
79}
80pub unsafe fn sub32(x: i32, y: i32) -> i32 {
81 return sub(x, y, OPSIZE_32);
82}
83#[no_mangle]
84pub unsafe fn adc8(x: i32, y: i32) -> i32 {
85 return adc(x, y, OPSIZE_8);
86}
87#[no_mangle]
88pub unsafe fn adc16(x: i32, y: i32) -> i32 {
89 return adc(x, y, OPSIZE_16);
90}
91pub unsafe fn adc32(x: i32, y: i32) -> i32 {
92 return adc(x, y, OPSIZE_32);
93}
94#[no_mangle]
95pub unsafe fn sbb8(x: i32, y: i32) -> i32 {
96 return sbb(x, y, OPSIZE_8);
97}
98#[no_mangle]
99pub unsafe fn sbb16(x: i32, y: i32) -> i32 {
100 return sbb(x, y, OPSIZE_16);
101}
102pub unsafe fn sbb32(x: i32, y: i32) -> i32 {
103 return sbb(x, y, OPSIZE_32);
104}
105pub unsafe fn cmp8(x: i32, y: i32) {
106 dbg_assert!(x >= 0 && x < 0x100);
107 dbg_assert!(y >= 0 && y < 0x100);
108 sub(x, y, OPSIZE_8);
109}
110pub unsafe fn cmp16(x: i32, y: i32) {
111 dbg_assert!(x >= 0 && x < 0x10000);
112 dbg_assert!(y >= 0 && y < 0x10000);
113 sub(x, y, OPSIZE_16);
114}
115pub unsafe fn cmp32(x: i32, y: i32) {
116 sub(x, y, OPSIZE_32);
117}
118unsafe fn inc(dest_operand: i32, op_size: i32) -> i32 {
119 *flags = *flags & !1 | getcf() as i32;
120 let res = (dest_operand + 1) & opsize_to_mask(op_size);
121 *last_op1 = dest_operand;
122 *last_result = res;
123 *last_op_size = op_size;
124 *flags_changed = FLAGS_ALL & !1;
125 return res;
126}
127unsafe fn dec(dest_operand: i32, op_size: i32) -> i32 {
128 *flags = *flags & !1 | getcf() as i32;
129 let res = (dest_operand - 1) & opsize_to_mask(op_size);
130 *last_op1 = dest_operand;
131 *last_result = res;
132 *last_op_size = op_size;
133 *flags_changed = FLAGS_ALL & !1 | FLAG_SUB;
134 return res;
135}
136#[no_mangle]
137pub unsafe fn inc8(x: i32) -> i32 {
138 return inc(x, OPSIZE_8);
139}
140pub unsafe fn inc16(x: i32) -> i32 {
141 return inc(x, OPSIZE_16);
142}
143pub unsafe fn inc32(x: i32) -> i32 {
144 return inc(x, OPSIZE_32);
145}
146#[no_mangle]
147pub unsafe fn dec8(x: i32) -> i32 {
148 return dec(x, OPSIZE_8);
149}
150pub unsafe fn dec16(x: i32) -> i32 {
151 return dec(x, OPSIZE_16);
152}
153pub unsafe fn dec32(x: i32) -> i32 {
154 return dec(x, OPSIZE_32);
155}
156
157unsafe fn neg(dest_operand: i32, op_size: i32) -> i32 {
158 sub(0, dest_operand, op_size)
159}
160#[no_mangle]
161pub unsafe fn not8(x: i32) -> i32 {
162 return !x;
163}
164#[no_mangle]
165pub unsafe fn neg8(x: i32) -> i32 {
166 return neg(x, OPSIZE_8);
167}
168#[no_mangle]
169pub unsafe fn neg16(x: i32) -> i32 {
170 return neg(x, OPSIZE_16);
171}
172pub unsafe fn neg32(x: i32) -> i32 {
173 return neg(x, OPSIZE_32);
174}
175
176#[no_mangle]
177pub unsafe fn mul8(source_operand: i32) {
178 let result = source_operand * read_reg8(AL);
179 write_reg16(AX, result);
180 *last_result = result & 255;
181 *last_op_size = OPSIZE_8;
182 if result < 256 {
183 *flags &= !1 & !FLAG_OVERFLOW
184 } else {
185 *flags |= 1 | FLAG_OVERFLOW
186 }
187 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
188}
189#[no_mangle]
190pub unsafe fn imul8(source_operand: i32) {
191 let result = source_operand * (read_reg8(AL) << 24 >> 24);
192 write_reg16(AX, result);
193 *last_result = result & 255;
194 *last_op_size = OPSIZE_8;
195 if result > 127 || result < -128 {
196 *flags |= 1 | FLAG_OVERFLOW
197 } else {
198 *flags &= !1 & !FLAG_OVERFLOW
199 }
200 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
201}
202#[no_mangle]
203pub unsafe fn mul16(source_operand: u32) {
204 let result = source_operand * read_reg16(AX) as u32;
205 let high_result = result >> 16;
206 write_reg16(AX, result as i32);
207 write_reg16(DX, high_result as i32);
208 *last_result = (result & 0xFFFF) as i32;
209 *last_op_size = OPSIZE_16;
210 if high_result == 0 {
211 *flags &= !1 & !FLAG_OVERFLOW
212 } else {
213 *flags |= 1 | FLAG_OVERFLOW
214 }
215 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
216}
217#[no_mangle]
218pub unsafe fn imul16(source_operand: i32) {
219 let result = source_operand * (read_reg16(AX) << 16 >> 16);
220 write_reg16(AX, result);
221 write_reg16(DX, result >> 16);
222 *last_result = result & 0xFFFF;
223 *last_op_size = OPSIZE_16;
224 if result > 32767 || result < -32768 {
225 *flags |= 1 | FLAG_OVERFLOW
226 } else {
227 *flags &= !1 & !FLAG_OVERFLOW
228 }
229 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
230}
231#[no_mangle]
232pub unsafe fn imul_reg16(mut operand1: i32, mut operand2: i32) -> i32 {
233 operand1 = operand1 << 16 >> 16;
234 operand2 = operand2 << 16 >> 16;
235 let result = operand1 * operand2;
236 *last_result = result & 0xFFFF;
237 *last_op_size = OPSIZE_16;
238 if result > 32767 || result < -32768 {
239 *flags |= 1 | FLAG_OVERFLOW
240 } else {
241 *flags &= !1 & !FLAG_OVERFLOW
242 }
243 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
244 return result;
245}
246#[no_mangle]
247pub unsafe fn mul32(source_operand: i32) {
248 let dest_operand = read_reg32(EAX);
249 let result = (dest_operand as u32 as u64) * (source_operand as u32 as u64);
250 let result_low = result as i32;
251 let result_high = (result >> 32) as i32;
252 write_reg32(EAX, result_low);
253 write_reg32(EDX, result_high);
254 *last_result = result_low;
255 *last_op_size = OPSIZE_32;
256 if result_high == 0 {
257 *flags &= !1 & !FLAG_OVERFLOW
258 } else {
259 *flags |= 1 | FLAG_OVERFLOW
260 }
261 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
262}
263pub unsafe fn imul32(source_operand: i32) {
264 let dest_operand = read_reg32(EAX);
265 let result = dest_operand as i64 * source_operand as i64;
266 let result_low = result as i32;
267 let result_high = (result >> 32) as i32;
268 write_reg32(EAX, result_low);
269 write_reg32(EDX, result_high);
270 *last_result = result_low;
271 *last_op_size = OPSIZE_32;
272 if result_high == result_low >> 31 {
273 *flags &= !1 & !FLAG_OVERFLOW
274 } else {
275 *flags |= 1 | FLAG_OVERFLOW
276 }
277 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
278}
279pub unsafe fn imul_reg32(operand1: i32, operand2: i32) -> i32 {
280 let result = operand1 as i64 * operand2 as i64;
281 let result_low = result as i32;
282 let result_high = (result >> 32) as i32;
283 *last_result = result_low;
284 *last_op_size = OPSIZE_32;
285 if result_high == result_low >> 31 {
286 *flags &= !1 & !FLAG_OVERFLOW
287 } else {
288 *flags |= 1 | FLAG_OVERFLOW
289 }
290 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
291 return result_low;
292}
293
294#[no_mangle]
295pub unsafe fn xadd8(source_operand: i32, reg: i32) -> i32 {
296 let tmp = read_reg8(reg);
297 write_reg8(reg, source_operand);
298 return add(source_operand, tmp, OPSIZE_8);
299}
300#[no_mangle]
301pub unsafe fn xadd16(source_operand: i32, reg: i32) -> i32 {
302 let tmp = read_reg16(reg);
303 write_reg16(reg, source_operand);
304 return add(source_operand, tmp, OPSIZE_16);
305}
306pub unsafe fn xadd32(source_operand: i32, reg: i32) -> i32 {
307 let tmp = read_reg32(reg);
308 write_reg32(reg, source_operand);
309 return add(source_operand, tmp, OPSIZE_32);
310}
311
312#[no_mangle]
313pub unsafe fn cmpxchg8(data: i32, r: i32) -> i32 {
314 cmp8(read_reg8(AL), data);
315 if getzf() {
316 read_reg8(r)
317 } else {
318 write_reg8(AL, data);
319 data
320 }
321}
322#[no_mangle]
323pub unsafe fn cmpxchg16(data: i32, r: i32) -> i32 {
324 cmp16(read_reg16(AX), data);
325 if getzf() {
326 read_reg16(r)
327 } else {
328 write_reg16(AX, data);
329 data
330 }
331}
332pub unsafe fn cmpxchg32(data: i32, r: i32) -> i32 {
333 cmp32(read_reg32(EAX), data);
334 if getzf() {
335 read_reg32(r)
336 } else {
337 write_reg32(EAX, data);
338 data
339 }
340}
341
342#[no_mangle]
343pub unsafe fn bcd_daa() {
344 let old_al = read_reg8(AL);
345 let old_cf = getcf();
346 let old_af = getaf();
347 *flags &= !1 & !FLAG_ADJUST;
348 if old_al & 15 > 9 || old_af {
349 write_reg8(AL, read_reg8(AL) + 6);
350 *flags |= FLAG_ADJUST
351 }
352 if old_al > 153 || old_cf {
353 write_reg8(AL, read_reg8(AL) + 96);
354 *flags |= 1
355 }
356 *last_result = read_reg8(AL);
357 *last_op_size = OPSIZE_8;
358 *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW;
359}
360#[no_mangle]
361pub unsafe fn bcd_das() {
362 let old_al = read_reg8(AL);
363 let old_cf = getcf();
364 *flags &= !1;
365 if old_al & 15 > 9 || getaf() {
366 write_reg8(AL, read_reg8(AL) - 6);
367 *flags |= FLAG_ADJUST;
368 *flags = *flags & !1 | old_cf as i32 | (old_al < 6) as i32
369 } else {
370 *flags &= !FLAG_ADJUST
371 }
372 if old_al > 153 || old_cf {
373 write_reg8(AL, read_reg8(AL) - 96);
374 *flags |= 1
375 }
376 *last_result = read_reg8(AL);
377 *last_op_size = OPSIZE_8;
378 *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW;
379}
380#[no_mangle]
381pub unsafe fn bcd_aad(imm8: i32) {
382 let result = read_reg8(AL) + read_reg8(AH) * imm8;
383 *last_result = result & 255;
384 write_reg16(AX, *last_result);
385 *last_op_size = OPSIZE_8;
386 *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW;
387 *flags &= !1 & !FLAG_ADJUST & !FLAG_OVERFLOW;
388 if result > 0xFFFF {
389 *flags |= 1
390 };
391}
392#[no_mangle]
393pub unsafe fn bcd_aam(imm8: i32) {
394 if imm8 == 0 {
396 trigger_de();
397 } else {
398 let temp = read_reg8(AL);
399 write_reg8(AH, temp as i32 / imm8);
400 write_reg8(AL, temp as i32 % imm8);
401 *last_result = read_reg8(AL);
402 *last_op_size = OPSIZE_8;
403 *flags_changed = FLAGS_ALL & !1 & !FLAG_ADJUST & !FLAG_OVERFLOW;
404 *flags &= !1 & !FLAG_ADJUST & !FLAG_OVERFLOW
405 };
406}
407#[no_mangle]
408pub unsafe fn bcd_aaa() {
409 if read_reg8(AL) & 15 > 9 || getaf() {
410 write_reg16(AX, read_reg16(AX) + 6);
411 write_reg8(AH, read_reg8(AH) + 1);
412 *flags |= FLAG_ADJUST | 1
413 } else {
414 *flags &= !FLAG_ADJUST & !1
415 }
416 write_reg8(AL, read_reg8(AL) & 15);
417 *flags_changed &= !FLAG_ADJUST & !1;
418}
419#[no_mangle]
420pub unsafe fn bcd_aas() {
421 if read_reg8(AL) & 15 > 9 || getaf() {
422 write_reg16(AX, read_reg16(AX) - 6);
423 write_reg8(AH, read_reg8(AH) - 1);
424 *flags |= FLAG_ADJUST | 1
425 } else {
426 *flags &= !FLAG_ADJUST & !1
427 }
428 write_reg8(AL, read_reg8(AL) & 15);
429 *flags_changed &= !FLAG_ADJUST & !1;
430}
431unsafe fn and(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 {
432 let result = dest_operand & source_operand;
433 *last_result = result;
434 *last_op_size = op_size;
435 *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST;
436 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW & !FLAG_ADJUST;
437 return result;
438}
439unsafe fn or(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 {
440 let result = dest_operand | source_operand;
441 *last_result = result;
442 *last_op_size = op_size;
443 *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST;
444 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW & !FLAG_ADJUST;
445 return result;
446}
447unsafe fn xor(dest_operand: i32, source_operand: i32, op_size: i32) -> i32 {
448 let result = dest_operand ^ source_operand;
449 *last_result = result;
450 *last_op_size = op_size;
451 *flags &= !1 & !FLAG_OVERFLOW & !FLAG_ADJUST;
452 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW & !FLAG_ADJUST;
453 return result;
454}
455pub unsafe fn and8(x: i32, y: i32) -> i32 {
456 return and(x, y, OPSIZE_8);
457}
458#[no_mangle]
459pub unsafe fn and16(x: i32, y: i32) -> i32 {
460 return and(x, y, OPSIZE_16);
461}
462pub unsafe fn and32(x: i32, y: i32) -> i32 {
463 return and(x, y, OPSIZE_32);
464}
465pub unsafe fn test8(x: i32, y: i32) {
466 and(x, y, OPSIZE_8);
467}
468pub unsafe fn test16(x: i32, y: i32) {
469 and(x, y, OPSIZE_16);
470}
471pub unsafe fn test32(x: i32, y: i32) {
472 and(x, y, OPSIZE_32);
473}
474pub unsafe fn or8(x: i32, y: i32) -> i32 {
475 return or(x, y, OPSIZE_8);
476}
477#[no_mangle]
478pub unsafe fn or16(x: i32, y: i32) -> i32 {
479 return or(x, y, OPSIZE_16);
480}
481pub unsafe fn or32(x: i32, y: i32) -> i32 {
482 return or(x, y, OPSIZE_32);
483}
484pub unsafe fn xor8(x: i32, y: i32) -> i32 {
485 return xor(x, y, OPSIZE_8);
486}
487#[no_mangle]
488pub unsafe fn xor16(x: i32, y: i32) -> i32 {
489 return xor(x, y, OPSIZE_16);
490}
491pub unsafe fn xor32(x: i32, y: i32) -> i32 {
492 return xor(x, y, OPSIZE_32);
493}
494
495#[no_mangle]
496pub unsafe fn rol8(dest_operand: i32, mut count: i32) -> i32 {
497 dbg_assert!(count >= 0 && count < 32);
498 if 0 == count {
499 return dest_operand;
500 } else {
501 count &= 7;
502 let result = dest_operand << count | dest_operand >> 8 - count;
503 *flags_changed &= !1 & !FLAG_OVERFLOW;
504 *flags = *flags & !1 & !FLAG_OVERFLOW
505 | result & 1
506 | (result << 11 ^ result << 4) & FLAG_OVERFLOW;
507 return result & 0xFF;
508 };
509}
510#[no_mangle]
511pub unsafe fn rol16(dest_operand: i32, mut count: i32) -> i32 {
512 dbg_assert!(count >= 0 && count < 32);
513 if 0 == count {
514 return dest_operand;
515 } else {
516 count &= 15;
517 let result = dest_operand << count | dest_operand >> 16 - count;
518 *flags_changed &= !1 & !FLAG_OVERFLOW;
519 *flags = *flags & !1 & !FLAG_OVERFLOW
520 | result & 1
521 | (result << 11 ^ result >> 4) & FLAG_OVERFLOW;
522 return result & 0xFFFF;
523 };
524}
525#[no_mangle]
526pub unsafe fn rol32(dest_operand: i32, count: i32) -> i32 {
527 dbg_assert!(count >= 0 && count < 32);
528 if 0 == count {
529 return dest_operand;
530 } else {
531 let result = ((dest_operand << count) as u32 | dest_operand as u32 >> 32 - count) as i32;
532 *flags_changed &= !1 & !FLAG_OVERFLOW;
533 *flags = *flags & !1 & !FLAG_OVERFLOW
534 | result & 1
535 | (result << 11 ^ result >> 20) & FLAG_OVERFLOW;
536 return result;
537 };
538}
539#[no_mangle]
540pub unsafe fn rcl8(dest_operand: i32, mut count: i32) -> i32 {
541 dbg_assert!(count >= 0 && count < 32);
542 count %= 9;
543 if 0 == count {
544 return dest_operand;
545 } else {
546 let result =
547 dest_operand << count | (getcf() as i32) << count - 1 | dest_operand >> 9 - count;
548 *flags_changed &= !1 & !FLAG_OVERFLOW;
549 *flags = *flags & !1 & !FLAG_OVERFLOW
550 | result >> 8 & 1
551 | (result << 3 ^ result << 4) & FLAG_OVERFLOW;
552 return result & 0xFF;
553 };
554}
555#[no_mangle]
556pub unsafe fn rcl16(dest_operand: i32, mut count: i32) -> i32 {
557 dbg_assert!(count >= 0 && count < 32);
558 count %= 17;
559 if 0 == count {
560 return dest_operand;
561 } else {
562 let result =
563 dest_operand << count | (getcf() as i32) << count - 1 | dest_operand >> 17 - count;
564 *flags_changed &= !1 & !FLAG_OVERFLOW;
565 *flags = *flags & !1 & !FLAG_OVERFLOW
566 | result >> 16 & 1
567 | (result >> 5 ^ result >> 4) & FLAG_OVERFLOW;
568 return result & 0xFFFF;
569 };
570}
571#[no_mangle]
572pub unsafe fn rcl32(dest_operand: i32, count: i32) -> i32 {
573 dbg_assert!(count >= 0 && count < 32);
574 if 0 == count {
575 return dest_operand;
576 } else {
577 let mut result = dest_operand << count | (getcf() as i32) << count - 1;
578 if count > 1 {
579 result = (result as u32 | dest_operand as u32 >> 33 - count) as i32
580 }
581 *flags_changed &= !1 & !FLAG_OVERFLOW;
582 let b = (dest_operand as u32 >> 32 - count & 1) as i32;
583 *flags = (*flags & !1 & !FLAG_OVERFLOW | b) | (b << 11 ^ result >> 20) & FLAG_OVERFLOW;
584 return result;
585 };
586}
587#[no_mangle]
588pub unsafe fn ror8(dest_operand: i32, mut count: i32) -> i32 {
589 dbg_assert!(count >= 0 && count < 32);
590 if 0 == count {
591 return dest_operand;
592 } else {
593 count &= 7;
594 let result = dest_operand >> count | dest_operand << 8 - count;
595 *flags_changed &= !1 & !FLAG_OVERFLOW;
596 *flags = *flags & !1 & !FLAG_OVERFLOW
597 | result >> 7 & 1
598 | (result << 4 ^ result << 5) & FLAG_OVERFLOW;
599 return result & 0xFF;
600 };
601}
602#[no_mangle]
603pub unsafe fn ror16(dest_operand: i32, mut count: i32) -> i32 {
604 dbg_assert!(count >= 0 && count < 32);
605 if 0 == count {
606 return dest_operand;
607 } else {
608 count &= 15;
609 let result = dest_operand >> count | dest_operand << 16 - count;
610 *flags_changed &= !1 & !FLAG_OVERFLOW;
611 *flags = *flags & !1 & !FLAG_OVERFLOW
612 | result >> 15 & 1
613 | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW;
614 return result & 0xFFFF;
615 };
616}
617#[no_mangle]
618pub unsafe fn ror32(dest_operand: i32, count: i32) -> i32 {
619 dbg_assert!(count >= 0 && count < 32);
620 if 0 == count {
621 return dest_operand;
622 } else {
623 let result = (dest_operand as u32 >> count | (dest_operand << 32 - count) as u32) as i32;
624 *flags_changed &= !1 & !FLAG_OVERFLOW;
625 *flags = *flags & !1 & !FLAG_OVERFLOW
626 | result >> 31 & 1
627 | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW;
628 return result;
629 };
630}
631#[no_mangle]
632pub unsafe fn rcr8(dest_operand: i32, mut count: i32) -> i32 {
633 dbg_assert!(count >= 0 && count < 32);
634 count %= 9;
635 if 0 == count {
636 return dest_operand;
637 } else {
638 let result =
639 dest_operand >> count | (getcf() as i32) << 8 - count | dest_operand << 9 - count;
640 *flags_changed &= !1 & !FLAG_OVERFLOW;
641 *flags = *flags & !1 & !FLAG_OVERFLOW
642 | result >> 8 & 1
643 | (result << 4 ^ result << 5) & FLAG_OVERFLOW;
644 return result & 0xFF;
645 };
646}
647#[no_mangle]
648pub unsafe fn rcr16(dest_operand: i32, mut count: i32) -> i32 {
649 dbg_assert!(count >= 0 && count < 32);
650 count %= 17;
651 if 0 == count {
652 return dest_operand;
653 } else {
654 let result =
655 dest_operand >> count | (getcf() as i32) << 16 - count | dest_operand << 17 - count;
656 *flags_changed &= !1 & !FLAG_OVERFLOW;
657 *flags = *flags & !1 & !FLAG_OVERFLOW
658 | result >> 16 & 1
659 | (result >> 4 ^ result >> 3) & FLAG_OVERFLOW;
660 return result & 0xFFFF;
661 };
662}
663#[no_mangle]
664pub unsafe fn rcr32(dest_operand: i32, count: i32) -> i32 {
665 dbg_assert!(count >= 0 && count < 32);
666 if 0 == count {
667 return dest_operand;
668 } else {
669 let mut result =
670 (dest_operand as u32 >> count | ((getcf() as i32) << 32 - count) as u32) as i32;
671 if count > 1 {
672 result |= dest_operand << 33 - count
673 }
674 *flags_changed &= !1 & !FLAG_OVERFLOW;
675 *flags = *flags & !1 & !FLAG_OVERFLOW
676 | dest_operand >> count - 1 & 1
677 | (result >> 20 ^ result >> 19) & FLAG_OVERFLOW;
678 return result;
679 };
680}
681#[no_mangle]
682pub unsafe fn div8(source_operand: u32) {
683 if source_operand == 0 {
684 trigger_de();
685 return;
686 }
687 let target_operand = read_reg16(AX) as u32;
688 let result = target_operand / source_operand;
689 if result >= 0x100 {
690 trigger_de();
691 return;
692 }
693 write_reg8(AL, result as i32);
694 write_reg8(AH, (target_operand % source_operand) as i32);
695}
696
697#[no_mangle]
698pub unsafe fn idiv8(source_operand: i32) {
699 if source_operand == 0 {
700 trigger_de();
701 return;
702 }
703 let target_operand = read_reg16(AX) << 16 >> 16;
704 let result = target_operand / source_operand;
705 if result >= 0x80 || result < -0x80 {
706 trigger_de();
707 return;
708 }
709 write_reg8(AL, result);
710 write_reg8(AH, target_operand % source_operand);
711}
712
713#[no_mangle]
714pub unsafe fn div16_without_fault(source_operand: u32) -> bool {
715 let target_operand = (read_reg16(AX) | read_reg16(DX) << 16) as u32;
716 let result = match target_operand.checked_div(source_operand) {
717 None => return false,
718 Some(r) => r,
719 };
720 if result >= 0x10000 {
721 return false;
722 }
723 write_reg16(AX, result as i32);
724 write_reg16(DX, (target_operand % source_operand) as i32);
725 return true;
726}
727pub unsafe fn div16(source_operand: u32) {
728 if !div16_without_fault(source_operand) {
729 trigger_de()
730 }
731}
732#[no_mangle]
733pub unsafe fn idiv16_without_fault(source_operand: i32) -> bool {
734 let target_operand = read_reg16(AX) | read_reg16(DX) << 16;
735 let result = match target_operand.checked_div(source_operand) {
736 None => return false,
737 Some(r) => r,
738 };
739 if result >= 0x8000 || result < -0x8000 {
740 return false;
741 }
742 write_reg16(AX, result);
743 write_reg16(DX, (target_operand % source_operand) as i32);
744 return true;
745}
746pub unsafe fn idiv16(source_operand: i32) {
747 if !idiv16_without_fault(source_operand) {
748 trigger_de()
749 }
750}
751
752pub unsafe fn div32_without_fault(source_operand: u32) -> bool {
753 let source_operand = source_operand as u64;
754 let target_low = read_reg32(EAX) as u32;
755 let target_high = read_reg32(EDX) as u32;
756 let target_operand = (target_high as u64) << 32 | target_low as u64;
757 let result = match target_operand.checked_div(source_operand) {
758 None => return false,
759 Some(r) => r,
760 };
761 if result > 0xFFFFFFFF {
762 return false;
763 }
764 let modulo = target_operand % source_operand;
765 write_reg32(EAX, result as i32);
766 write_reg32(EDX, modulo as i32);
767 return true;
768}
769pub unsafe fn div32(source_operand: u32) {
770 if !div32_without_fault(source_operand) {
771 trigger_de()
772 }
773}
774#[no_mangle]
775pub unsafe fn idiv32_without_fault(source_operand: i32) -> bool {
776 let source_operand = source_operand as i64;
777 let target_low = read_reg32(EAX) as u32;
778 let target_high = read_reg32(EDX) as u32;
779 let target_operand = (target_high as i64) << 32 | target_low as i64;
780 let result = match target_operand.checked_div(source_operand) {
781 None => return false,
782 Some(r) => r,
783 };
784 if result < -0x80000000 || result > 0x7FFFFFFF {
785 return false;
786 }
787 let modulo = target_operand % source_operand;
788 write_reg32(EAX, result as i32);
789 write_reg32(EDX, modulo as i32);
790 return true;
791}
792pub unsafe fn idiv32(source_operand: i32) {
793 if !idiv32_without_fault(source_operand) {
794 trigger_de()
795 }
796}
797
798#[no_mangle]
799pub unsafe fn shl8(dest_operand: i32, count: i32) -> i32 {
800 dbg_assert!(count >= 0 && count < 32);
801 if count == 0 {
802 return dest_operand;
803 } else {
804 let result = dest_operand << count;
805 *last_result = result;
806 *last_op_size = OPSIZE_8;
807 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
808 *flags = *flags & !1 & !FLAG_OVERFLOW
809 | result >> 8 & 1
810 | (result << 3 ^ result << 4) & FLAG_OVERFLOW;
811 return result & 0xFF;
812 };
813}
814#[no_mangle]
815pub unsafe fn shl16(dest_operand: i32, count: i32) -> i32 {
816 dbg_assert!(count >= 0 && count < 32);
817 if count == 0 {
818 return dest_operand;
819 } else {
820 let result = dest_operand << count;
821 *last_result = result;
822 *last_op_size = OPSIZE_16;
823 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
824 *flags = *flags & !1 & !FLAG_OVERFLOW
825 | result >> 16 & 1
826 | (result >> 5 ^ result >> 4) & FLAG_OVERFLOW;
827 return result & 0xFFFF;
828 };
829}
830pub unsafe fn shl32(dest_operand: i32, count: i32) -> i32 {
831 dbg_assert!(count >= 0 && count < 32);
832 if count == 0 {
833 return dest_operand;
834 } else {
835 let result = dest_operand << count;
836 *last_result = result;
837 *last_op_size = OPSIZE_32;
838 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
839 let b = dest_operand >> 32 - count & 1;
840 *flags = *flags & !1 & !FLAG_OVERFLOW | b | (b ^ result >> 31) << 11 & FLAG_OVERFLOW;
841 return result;
842 };
843}
844#[no_mangle]
845pub unsafe fn shr8(dest_operand: i32, count: i32) -> i32 {
846 dbg_assert!(count >= 0 && count < 32);
847 if count == 0 {
848 return dest_operand;
849 } else {
850 let result = dest_operand >> count;
851 *last_result = result;
852 *last_op_size = OPSIZE_8;
853 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
854 *flags = *flags & !1 & !FLAG_OVERFLOW
855 | dest_operand >> count - 1 & 1
856 | (dest_operand >> 7 & 1) << 11 & FLAG_OVERFLOW;
857 return result;
858 };
859}
860#[no_mangle]
861pub unsafe fn shr16(dest_operand: i32, count: i32) -> i32 {
862 dbg_assert!(count >= 0 && count < 32);
863 if count == 0 {
864 return dest_operand;
865 } else {
866 let result = dest_operand >> count;
867 *last_result = result;
868 *last_op_size = OPSIZE_16;
869 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
870 *flags = *flags & !1 & !FLAG_OVERFLOW
871 | dest_operand >> count - 1 & 1
872 | dest_operand >> 4 & FLAG_OVERFLOW;
873 return result;
874 };
875}
876pub unsafe fn shr32(dest_operand: i32, count: i32) -> i32 {
877 dbg_assert!(count >= 0 && count < 32);
878 if count == 0 {
879 return dest_operand;
880 } else {
881 let result = (dest_operand as u32 >> count) as i32;
882 *last_result = result;
883 *last_op_size = OPSIZE_32;
884 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
885 *flags = (*flags & !1 & !FLAG_OVERFLOW)
886 | (dest_operand as u32 >> count - 1 & 1) as i32
887 | (dest_operand >> 20 & FLAG_OVERFLOW);
888 return result;
889 };
890}
891#[no_mangle]
892pub unsafe fn sar8(dest_operand: i32, count: i32) -> i32 {
893 dbg_assert!(count >= 0 && count < 32);
894 if count == 0 {
895 return dest_operand;
896 } else {
897 let result;
898 if count < 8 {
899 result = dest_operand << 24 >> count + 24;
900 *flags = *flags & !1 & !FLAG_OVERFLOW | dest_operand >> count - 1 & 1
902 } else {
903 result = dest_operand << 24 >> 31;
904 *flags = *flags & !1 & !FLAG_OVERFLOW | result & 1
905 }
906 *last_result = result;
907 *last_op_size = OPSIZE_8;
908 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
909 return result & 0xFF;
910 };
911}
912#[no_mangle]
913pub unsafe fn sar16(dest_operand: i32, count: i32) -> i32 {
914 dbg_assert!(count >= 0 && count < 32);
915 if count == 0 {
916 return dest_operand;
917 } else {
918 let result;
919 if count < 16 {
920 result = dest_operand << 16 >> count + 16;
921 *flags = *flags & !1 & !FLAG_OVERFLOW | dest_operand >> count - 1 & 1
922 } else {
923 result = dest_operand << 16 >> 31;
924 *flags = *flags & !1 & !FLAG_OVERFLOW | result & 1
925 }
926 *last_result = result;
927 *last_op_size = OPSIZE_16;
928 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
929 return result & 0xFFFF;
930 };
931}
932pub unsafe fn sar32(dest_operand: i32, count: i32) -> i32 {
933 dbg_assert!(count >= 0 && count < 32);
934 if count == 0 {
935 return dest_operand;
936 } else {
937 let result = dest_operand >> count;
938 *last_result = result;
939 *last_op_size = OPSIZE_32;
940 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
941 *flags = (*flags & !1 & !FLAG_OVERFLOW) | (dest_operand as u32 >> count - 1 & 1) as i32;
942 return result;
943 };
944}
945
946#[no_mangle]
947pub unsafe fn shrd16(dest_operand: i32, source_operand: i32, count: i32) -> i32 {
948 dbg_assert!(count >= 0 && count < 32);
949 if count == 0 {
950 return dest_operand;
951 } else {
952 let result;
953 if count <= 16 {
954 result = dest_operand >> count | source_operand << 16 - count;
955 *flags = *flags & !1 | dest_operand >> count - 1 & 1
956 } else {
957 result = dest_operand << 32 - count | source_operand >> count - 16;
958 *flags = *flags & !1 | source_operand >> count - 17 & 1
959 }
960 *last_result = result;
961 *last_op_size = OPSIZE_16;
962 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
963 *flags = *flags & !FLAG_OVERFLOW | (result ^ dest_operand) >> 4 & FLAG_OVERFLOW;
964 return result & 0xFFFF;
965 };
966}
967#[no_mangle]
968pub unsafe fn shrd32(dest_operand: i32, source_operand: i32, count: i32) -> i32 {
969 dbg_assert!(count >= 0 && count < 32);
970 if count == 0 {
971 return dest_operand;
972 } else {
973 let result = (dest_operand as u32 >> count | (source_operand << 32 - count) as u32) as i32;
974 *last_result = result;
975 *last_op_size = OPSIZE_32;
976 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
977 *flags = ((*flags & !1 & !FLAG_OVERFLOW) | (dest_operand as u32 >> count - 1 & 1) as i32)
978 | (result ^ dest_operand) >> 20 & FLAG_OVERFLOW;
979 return result;
980 };
981}
982#[no_mangle]
983pub unsafe fn shld16(dest_operand: i32, source_operand: i32, count: i32) -> i32 {
984 dbg_assert!(count >= 0 && count < 32);
985 if count == 0 {
986 return dest_operand;
987 } else {
988 let result;
989 if count <= 16 {
990 result = ((dest_operand << count) as u32 | source_operand as u32 >> 16 - count) as i32;
991 *flags = (*flags & !1) | (dest_operand as u32 >> 16 - count & 1) as i32;
992 } else {
993 result = dest_operand >> 32 - count | source_operand << count - 16;
994 *flags = (*flags & !1) | (source_operand as u32 >> 32 - count & 1) as i32;
995 }
996 *last_result = result;
997 *last_op_size = OPSIZE_16;
998 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
999 *flags = *flags & !FLAG_OVERFLOW | (*flags & 1 ^ result >> 15 & 1) << 11;
1000 return result & 0xFFFF;
1001 };
1002}
1003#[no_mangle]
1004pub unsafe fn shld32(dest_operand: i32, source_operand: i32, count: i32) -> i32 {
1005 dbg_assert!(count >= 0 && count < 32);
1006 if count == 0 {
1007 return dest_operand;
1008 } else {
1009 let result = ((dest_operand << count) as u32 | source_operand as u32 >> 32 - count) as i32;
1010 *last_result = result;
1011 *last_op_size = OPSIZE_32;
1012 *flags_changed = FLAGS_ALL & !1 & !FLAG_OVERFLOW;
1013 *flags = (*flags & !1) | (dest_operand as u32 >> 32 - count & 1) as i32;
1014 if count == 1 {
1015 *flags = *flags & !FLAG_OVERFLOW | (*flags & 1 ^ result >> 31 & 1) << 11
1016 } else {
1017 *flags &= !FLAG_OVERFLOW
1018 }
1019 return result;
1020 };
1021}
1022
1023pub unsafe fn bt_reg(bit_base: i32, bit_offset: i32) {
1024 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1025 *flags_changed &= !1;
1026}
1027pub unsafe fn btc_reg(bit_base: i32, bit_offset: i32) -> i32 {
1028 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1029 *flags_changed &= !1;
1030 return bit_base ^ 1 << bit_offset;
1031}
1032pub unsafe fn bts_reg(bit_base: i32, bit_offset: i32) -> i32 {
1033 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1034 *flags_changed &= !1;
1035 return bit_base | 1 << bit_offset;
1036}
1037pub unsafe fn btr_reg(bit_base: i32, bit_offset: i32) -> i32 {
1038 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1039 *flags_changed &= !1;
1040 return bit_base & !(1 << bit_offset);
1041}
1042
1043pub unsafe fn bt_mem(virt_addr: i32, mut bit_offset: i32) {
1044 let bit_base = return_on_pagefault!(safe_read8(virt_addr + (bit_offset >> 3)));
1045 bit_offset &= 7;
1046 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1047 *flags_changed &= !1;
1048}
1049pub unsafe fn btc_mem(virt_addr: i32, mut bit_offset: i32) {
1050 let phys_addr = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3)));
1051 let bit_base = memory::read8(phys_addr);
1052 bit_offset &= 7;
1053 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1054 *flags_changed &= !1;
1055 memory::write8(phys_addr, bit_base ^ 1 << bit_offset);
1056}
1057pub unsafe fn btr_mem(virt_addr: i32, mut bit_offset: i32) {
1058 let phys_addr = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3)));
1059 let bit_base = memory::read8(phys_addr);
1060 bit_offset &= 7;
1061 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1062 *flags_changed &= !1;
1063 memory::write8(phys_addr, bit_base & !(1 << bit_offset));
1064}
1065pub unsafe fn bts_mem(virt_addr: i32, mut bit_offset: i32) {
1066 let phys_addr = return_on_pagefault!(translate_address_write(virt_addr + (bit_offset >> 3)));
1067 let bit_base = memory::read8(phys_addr);
1068 bit_offset &= 7;
1069 *flags = *flags & !1 | bit_base >> bit_offset & 1;
1070 *flags_changed &= !1;
1071 memory::write8(phys_addr, bit_base | 1 << bit_offset);
1072}
1073
1074#[no_mangle]
1075pub unsafe fn bsf16(old: i32, bit_base: i32) -> i32 {
1076 *flags_changed = FLAGS_ALL & !FLAG_ZERO & !FLAG_CARRY;
1077 *flags &= !FLAG_CARRY;
1078 *last_op_size = OPSIZE_16;
1079 if bit_base == 0 {
1080 *flags |= FLAG_ZERO;
1081 *last_result = bit_base;
1082 return old;
1084 } else {
1085 *flags &= !FLAG_ZERO;
1086 *last_result = int_log2(bit_base.wrapping_neg() & bit_base);
1087 return *last_result;
1088 };
1089}
1090#[no_mangle]
1091pub unsafe fn bsf32(old: i32, bit_base: i32) -> i32 {
1092 *flags_changed = FLAGS_ALL & !FLAG_ZERO & !FLAG_CARRY;
1093 *flags &= !FLAG_CARRY;
1094 *last_op_size = OPSIZE_32;
1095 if bit_base == 0 {
1096 *flags |= FLAG_ZERO;
1097 *last_result = bit_base;
1098 return old;
1099 } else {
1100 *flags &= !FLAG_ZERO;
1101 *last_result = int_log2(bit_base.wrapping_neg() & bit_base);
1102 return *last_result;
1103 };
1104}
1105#[no_mangle]
1106pub unsafe fn bsr16(old: i32, bit_base: i32) -> i32 {
1107 *flags_changed = FLAGS_ALL & !FLAG_ZERO & !FLAG_CARRY;
1108 *flags &= !FLAG_CARRY;
1109 *last_op_size = OPSIZE_16;
1110 if bit_base == 0 {
1111 *flags |= FLAG_ZERO;
1112 *last_result = bit_base;
1113 return old;
1114 } else {
1115 *flags &= !FLAG_ZERO;
1116 *last_result = int_log2(bit_base);
1117 return *last_result;
1118 };
1119}
1120#[no_mangle]
1121pub unsafe fn bsr32(old: i32, bit_base: i32) -> i32 {
1122 *flags_changed = FLAGS_ALL & !FLAG_ZERO & !FLAG_CARRY;
1123 *flags &= !FLAG_CARRY;
1124 *last_op_size = OPSIZE_32;
1125 if bit_base == 0 {
1126 *flags |= FLAG_ZERO;
1127 *last_result = bit_base;
1128 return old;
1129 } else {
1130 *flags &= !FLAG_ZERO;
1131 *last_result = int_log2(bit_base);
1132 return *last_result;
1133 };
1134}
1135#[no_mangle]
1136pub unsafe fn popcnt(v: i32) -> i32 {
1137 *flags_changed = 0;
1138 *flags &= !FLAGS_ALL;
1139 if 0 != v {
1140 return v.count_ones() as i32;
1141 } else {
1142 *flags |= FLAG_ZERO;
1143 return 0;
1144 };
1145}
1146
1147pub unsafe fn saturate_sw_to_ub(v: u16) -> u8 {
1148 let mut ret = v;
1149 if ret >= 32768 {
1150 ret = 0
1151 } else if ret > 255 {
1152 ret = 255
1153 }
1154 return ret as u8;
1155}
1156pub unsafe fn saturate_sw_to_sb(v: i32) -> u8 {
1157 dbg_assert!(v as u32 & 0xFFFF_0000 == 0);
1158 let mut ret = v;
1159 if ret > 65408 {
1160 ret = ret & 255
1161 } else if ret > 32767 {
1162 ret = 128
1163 } else if ret > 127 {
1164 ret = 127
1165 }
1166 dbg_assert!(ret as u32 & 0xFFFF_FF00 == 0);
1167 return ret as u8;
1168}
1169pub unsafe fn saturate_sd_to_sw(v: u32) -> u16 {
1170 let mut ret = v;
1171 if ret > 4294934528 {
1172 ret = ret & 0xFFFF
1173 } else if ret > 0x7FFFFFFF {
1174 ret = 32768
1175 } else if ret > 32767 {
1176 ret = 32767
1177 }
1178 dbg_assert!(ret & 0xFFFF_0000 == 0);
1179 return ret as u16;
1180}
1181pub unsafe fn saturate_sd_to_sb(v: u32) -> i8 {
1182 let mut ret = v;
1183 if ret > 0xFFFFFF80 {
1184 ret = ret & 255
1185 } else if ret > 0x7FFFFFFF {
1186 ret = 128
1187 } else if ret > 127 {
1188 ret = 127
1189 }
1190 dbg_assert!(ret & 0xFFFF_FF00 == 0);
1191 return ret as i8;
1192}
1193pub unsafe fn saturate_sd_to_ub(v: i32) -> i32 {
1194 let mut ret = v;
1195 if ret < 0 {
1196 ret = 0
1197 }
1198 dbg_assert!(ret as u32 & 0xFFFF_FF00 == 0);
1199 return ret;
1200}
1201pub unsafe fn saturate_ud_to_ub(v: u32) -> u8 {
1202 let mut ret = v;
1203 if ret > 255 {
1204 ret = 255
1205 }
1206 dbg_assert!(ret & 0xFFFF_FF00 == 0);
1207 return ret as u8;
1208}
1209pub unsafe fn saturate_uw(v: u32) -> u16 {
1210 let mut ret = v;
1211 if ret > 0x7FFFFFFF {
1212 ret = 0
1213 } else if ret > 0xFFFF {
1214 ret = 0xFFFF
1215 }
1216 dbg_assert!(ret & 0xFFFF_0000 == 0);
1217 return ret as u16;
1218}