@aptre/v86 0.5.0

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