1;; Licensed to the .NET Foundation under one or more agreements.
2;; The .NET Foundation licenses this file to you under the MIT license.
3;; See the LICENSE file in the project root for more information.
4
5
6        .586
7        .model  flat
8        option  casemap:none
9        .code
10
11
12include AsmMacros.inc
13
14EXTERN RhExceptionHandling_ThrowClasslibOverflowException                              : PROC
15EXTERN RhExceptionHandling_ThrowClasslibDivideByZeroException                          : PROC
16EXTERN __alldiv : PROC
17EXTERN __allrem : PROC
18EXTERN __aulldiv : PROC
19EXTERN __aullrem : PROC
20EXTERN __aulldvrm : PROC
21EXTERN __alldvrm : PROC
22
23esp_offsetof_dividend_low     equ 4
24esp_offsetof_dividend_high    equ 8
25esp_offsetof_divisor_low      equ 12
26esp_offsetof_divisor_high     equ 16
27
28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
29;;
30;; RhpLDiv
31;;
32;; INPUT:  [ESP+4]: dividend low
33;;         [ESP+8]: dividend high
34;;         [ESP+12]: divisor low
35;;         [ESP+16]: divisor high
36;;
37;; OUTPUT: EAX: result low
38;;         EDX: result high
39;;
40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
41FASTCALL_FUNC  RhpLDiv, 16
42
43        ;; pretest for the problematic cases of overflow and divide by zero
44        ;; overflow: dividend = 0x80000000`00000000 and divisor = -1l = 0xffffffff`ffffffff
45        ;; divide by zero: divisor = 0x00000000`00000000
46        ;;
47        ;; quick pretest - if the two halves of the divisor are unequal, we cannot
48        ;; have one of the problematic cases
49        mov     eax,[esp+esp_offsetof_divisor_low]
50        cmp     eax,[esp+esp_offsetof_divisor_high]
51        je      LDivDoMoreTests
52LDivOkToDivide:
53        ;; tailcall to the actual divide routine
54        jmp     __alldiv
55LDivDoMoreTests:
56        ;; we know the high and low halves of the divisor are equal
57        ;;
58        ;; check for the divide by zero case
59        test    eax,eax
60        je      ThrowClasslibDivideByZeroException
61        ;;
62        ;; is the divisor == -1l? I.e., can we have the overflow case?
63        cmp     eax,-1
64        jne     LDivOkToDivide
65        ;;
66        ;; is the dividend == 0x80000000`00000000?
67        cmp     dword ptr [esp+esp_offsetof_dividend_low],0
68        jne     LDivOkToDivide
69        cmp     dword ptr [esp+esp_offsetof_dividend_high],80000000h
70        jne     LDivOkToDivide
71FASTCALL_ENDFUNC
72
73        ;; make it look like the managed code called this directly
74        ;; by popping the parameters and putting the return address in the proper place
75ThrowClasslibOverflowException proc
76        pop     ecx
77        add     esp,16
78        push    ecx
79        ;; passing return address in ecx
80        jmp     RhExceptionHandling_ThrowClasslibOverflowException
81ThrowClasslibOverflowException endp
82
83ThrowClasslibDivideByZeroException proc
84        pop     ecx
85        add     esp,16
86        push    ecx
87        ;; passing return address in ecx
88        jmp     RhExceptionHandling_ThrowClasslibDivideByZeroException
89ThrowClasslibDivideByZeroException endp
90
91;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
92;;
93;; RhpLMod
94;;
95;; INPUT:  [ESP+4]: dividend low
96;;         [ESP+8]: dividend high
97;;         [ESP+12]: divisor low
98;;         [ESP+16]: divisor high
99;;
100;; OUTPUT: EAX: result low
101;;         EDX: result high
102;;
103;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
104FASTCALL_FUNC  RhpLMod, 16
105
106        ;; pretest for the problematic cases of overflow and divide by zero
107        ;; overflow: dividend = 0x80000000`00000000 and divisor = -1l = 0xffffffff`ffffffff
108        ;; divide by zero: divisor = 0x00000000`00000000
109        ;;
110        ;; quick pretest - if the two halves of the divisor are unequal, we cannot
111        ;; have one of the problematic cases
112        mov     eax,[esp+esp_offsetof_divisor_low]
113        cmp     eax,[esp+esp_offsetof_divisor_high]
114        je      LModDoMoreTests
115LModOkToDivide:
116        jmp     __allrem
117LModDoMoreTests:
118        ;; we know the high and low halves of the divisor are equal
119        ;;
120        ;; check for the divide by zero case
121        test    eax,eax
122        je      ThrowClasslibDivideByZeroException
123        ;;
124        ;; is the divisor == -1l? I.e., can we have the overflow case?
125        cmp     eax,-1
126        jne     LModOkToDivide
127        ;;
128        ;; is the dividend == 0x80000000`00000000?
129        cmp     dword ptr [esp+esp_offsetof_dividend_low],0
130        jne     LModOkToDivide
131        cmp     dword ptr [esp+esp_offsetof_dividend_high],80000000h
132        jne     LModOkToDivide
133        jmp     ThrowClasslibOverflowException
134
135FASTCALL_ENDFUNC
136
137;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
138;;
139;; RhpLDivMod
140;;
141;; INPUT:  [ESP+4]: dividend low
142;;         [ESP+8]: dividend high
143;;         [ESP+12]: divisor low
144;;         [ESP+16]: divisor high
145;;
146;; OUTPUT: EAX: quotient low
147;;         EDX: quotient high
148;;         ECX: remainder high
149;;         EBX: remainder high
150;;
151;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
152FASTCALL_FUNC  RhpLDivMod, 16
153
154        ;; pretest for the problematic cases of overflow and divide by zero
155        ;; overflow: dividend = 0x80000000`00000000 and divisor = -1l = 0xffffffff`ffffffff
156        ;; divide by zero: divisor = 0x00000000`00000000
157        ;;
158        ;; quick pretest - if the two halves of the divisor are unequal, we cannot
159        ;; have one of the problematic cases
160        mov     eax,[esp+esp_offsetof_divisor_low]
161        cmp     eax,[esp+esp_offsetof_divisor_high]
162        je      LDivModDoMoreTests
163LDivModOkToDivide:
164        jmp     __alldvrm
165LDivModDoMoreTests:
166        ;; we know the high and low halves of the divisor are equal
167        ;;
168        ;; check for the divide by zero case
169        test    eax,eax
170        je      ThrowClasslibDivideByZeroException
171        ;;
172        ;; is the divisor == -1l? I.e., can we have the overflow case?
173        cmp     eax,-1
174        jne     LDivModOkToDivide
175        ;;
176        ;; is the dividend == 0x80000000`00000000?
177        cmp     dword ptr [esp+esp_offsetof_dividend_low],0
178        jne     LDivModOkToDivide
179        cmp     dword ptr [esp+esp_offsetof_dividend_high],80000000h
180        jne     LDivModOkToDivide
181        jmp     ThrowClasslibOverflowException
182
183FASTCALL_ENDFUNC
184
185;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
186;;
187;; RhpULDiv
188;;
189;; INPUT:  [ESP+4]: dividend low
190;;         [ESP+8]: dividend high
191;;         [ESP+12]: divisor low
192;;         [ESP+16]: divisor high
193;;
194;; OUTPUT: EAX: result low
195;;         EDX: result high
196;;
197;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
198FASTCALL_FUNC  RhpULDiv, 16
199
200        ;; pretest for divide by zero
201        mov     eax,[esp+esp_offsetof_divisor_low]
202        or      eax,[esp+esp_offsetof_divisor_high]
203        jne     __aulldiv
204        jmp     ThrowClasslibDivideByZeroException
205
206FASTCALL_ENDFUNC
207
208;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
209;;
210;; RhpULMod
211;;
212;; INPUT:  [ESP+4]: dividend low
213;;         [ESP+8]: dividend high
214;;         [ESP+12]: divisor low
215;;         [ESP+16]: divisor high
216;;
217;; OUTPUT: EAX: result low
218;;         EDX: result high
219;;
220;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
221FASTCALL_FUNC  RhpULMod, 16
222
223        ;; pretest for divide by zero
224        mov     eax,[esp+esp_offsetof_divisor_low]
225        or      eax,[esp+esp_offsetof_divisor_high]
226        jne     __aullrem
227        jmp     ThrowClasslibDivideByZeroException
228
229FASTCALL_ENDFUNC
230
231;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
232;;
233;; RhpULDivMod
234;;
235;; INPUT:  [ESP+4]: dividend low
236;;         [ESP+8]: dividend high
237;;         [ESP+12]: divisor low
238;;         [ESP+16]: divisor high
239;;
240;; OUTPUT: EAX: quotient low
241;;         EDX: quotient high
242;;         ECX: remainder high
243;;         EBX: remainder high
244;;
245;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
246FASTCALL_FUNC  RhpULDivMod, 16
247
248        ;; pretest for divide by zero
249        mov     eax,[esp+esp_offsetof_divisor_low]
250        or      eax,[esp+esp_offsetof_divisor_high]
251        jne     __aulldvrm
252        jmp     ThrowClasslibDivideByZeroException
253
254FASTCALL_ENDFUNC
255
256
257        end
258