1const builtin = @import("builtin");
2
3const compiler_rt = @import("../compiler_rt.zig");
4const symbol = compiler_rt.symbol;
5
6comptime {
7 if (compiler_rt.want_windows_x86_msvc_abi) {
8 // Don't let LLVM apply the stdcall name mangling on those MSVC builtins
9 symbol(&_alldiv, "\x01__alldiv");
10 symbol(&_aulldiv, "\x01__aulldiv");
11 }
12}
13
14pub fn _alldiv(a: i64, b: i64) callconv(.{ .x86_stdcall = .{} }) i64 {
15 const s_a = a >> (64 - 1);
16 const s_b = b >> (64 - 1);
17
18 const an = (a ^ s_a) -% s_a;
19 const bn = (b ^ s_b) -% s_b;
20
21 const r = @as(u64, @bitCast(an)) / @as(u64, @bitCast(bn));
22 const s = s_a ^ s_b;
23 return (@as(i64, @bitCast(r)) ^ s) -% s;
24}
25
26pub fn _aulldiv() callconv(.naked) void {
27 @setRuntimeSafety(false);
28
29 // The stack layout is:
30 // ESP+16 divisor (hi)
31 // ESP+12 divisor (low)
32 // ESP+8 dividend (hi)
33 // ESP+4 dividend (low)
34 // ESP return address
35
36 asm volatile (
37 \\ push %%ebx
38 \\ push %%esi
39 \\ mov 0x18(%%esp),%%eax
40 \\ or %%eax,%%eax
41 \\ jne 1f
42 \\ mov 0x14(%%esp),%%ecx
43 \\ mov 0x10(%%esp),%%eax
44 \\ xor %%edx,%%edx
45 \\ div %%ecx
46 \\ mov %%eax,%%ebx
47 \\ mov 0xc(%%esp),%%eax
48 \\ div %%ecx
49 \\ mov %%ebx,%%edx
50 \\ jmp 5f
51 \\ 1:
52 \\ mov %%eax,%%ecx
53 \\ mov 0x14(%%esp),%%ebx
54 \\ mov 0x10(%%esp),%%edx
55 \\ mov 0xc(%%esp),%%eax
56 \\ 2:
57 \\ shr %%ecx
58 \\ rcr %%ebx
59 \\ shr %%edx
60 \\ rcr %%eax
61 \\ or %%ecx,%%ecx
62 \\ jne 2b
63 \\ div %%ebx
64 \\ mov %%eax,%%esi
65 \\ mull 0x18(%%esp)
66 \\ mov %%eax,%%ecx
67 \\ mov 0x14(%%esp),%%eax
68 \\ mul %%esi
69 \\ add %%ecx,%%edx
70 \\ jb 3f
71 \\ cmp 0x10(%%esp),%%edx
72 \\ ja 3f
73 \\ jb 4f
74 \\ cmp 0xc(%%esp),%%eax
75 \\ jbe 4f
76 \\ 3:
77 \\ dec %%esi
78 \\ 4:
79 \\ xor %%edx,%%edx
80 \\ mov %%esi,%%eax
81 \\ 5:
82 \\ pop %%esi
83 \\ pop %%ebx
84 \\ ret $0x10
85 );
86}