Subversion Repositories HelenOS

Rev

Rev 2726 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2726 vana 1
/*++
2
 
3
Copyright (c) 1998  Intel Corporation
4
 
5
Module Name:
6
 
7
    math.c
8
 
9
Abstract:
10
 
11
 
12
 
13
 
14
Revision History
15
 
16
--*/
17
 
18
#include "lib.h"
19
 
20
 
21
//
22
// Declare runtime functions
23
//
24
 
25
#ifdef RUNTIME_CODE
26
#pragma RUNTIME_CODE(LShiftU64)
27
#pragma RUNTIME_CODE(RShiftU64)
28
#pragma RUNTIME_CODE(MultU64x32)
29
#pragma RUNTIME_CODE(DivU64x32)
30
#endif
31
 
32
//
33
//
34
//
35
 
36
UINT64
37
LShiftU64 (
38
    IN UINT64   Operand,
39
    IN UINTN    Count
40
    )
41
// Left shift 64bit by 32bit and get a 64bit result
42
{
43
#ifdef __GNUC__
44
    return Operand << Count;
45
#else
46
    UINT64      Result;
47
    _asm {
48
        mov     eax, dword ptr Operand[0]
49
        mov     edx, dword ptr Operand[4]
50
        mov     ecx, Count
51
        and     ecx, 63
52
 
53
        shld    edx, eax, cl
54
        shl     eax, cl
55
 
56
        cmp     ecx, 32
57
        jc      short ls10
58
 
59
        mov     edx, eax
60
        xor     eax, eax
61
 
62
ls10:
63
        mov     dword ptr Result[0], eax
64
        mov     dword ptr Result[4], edx
65
    }
66
 
67
    return Result;
68
#endif
69
}
70
 
71
UINT64
72
RShiftU64 (
73
    IN UINT64   Operand,
74
    IN UINTN    Count
75
    )
76
// Right shift 64bit by 32bit and get a 64bit result
77
{
78
#ifdef __GNUC__
79
    return Operand >> Count;
80
#else
81
    UINT64      Result;
82
    _asm {
83
        mov     eax, dword ptr Operand[0]
84
        mov     edx, dword ptr Operand[4]
85
        mov     ecx, Count
86
        and     ecx, 63
87
 
88
        shrd    eax, edx, cl
89
        shr     edx, cl
90
 
91
        cmp     ecx, 32
92
        jc      short rs10
93
 
94
        mov     eax, edx
95
        xor     edx, edx
96
 
97
rs10:
98
        mov     dword ptr Result[0], eax
99
        mov     dword ptr Result[4], edx
100
    }
101
 
102
    return Result;
103
#endif
104
}
105
 
106
 
107
UINT64
108
MultU64x32 (
109
    IN UINT64   Multiplicand,
110
    IN UINTN    Multiplier
111
    )
112
// Multiple 64bit by 32bit and get a 64bit result
113
{
114
#ifdef __GNUC__
115
    return Multiplicand * Multiplier;
116
#else
117
    UINT64      Result;
118
    _asm {
119
        mov     eax, dword ptr Multiplicand[0]
120
        mul     Multiplier
121
        mov     dword ptr Result[0], eax
122
        mov     dword ptr Result[4], edx
123
        mov     eax, dword ptr Multiplicand[4]
124
        mul     Multiplier
125
        add     dword ptr Result[4], eax
126
    }
127
 
128
    return Result;
129
#endif
130
}
131
 
132
UINT64
133
DivU64x32 (
134
    IN UINT64   Dividend,
135
    IN UINTN    Divisor,
136
    OUT UINTN   *Remainder OPTIONAL
137
    )
138
// divide 64bit by 32bit and get a 64bit result
139
// N.B. only works for 31bit divisors!!
140
{
141
#ifdef __GNUC__
142
    if (Remainder)
143
    *Remainder = Dividend % Divisor;
144
    return Dividend / Divisor;
145
#else
146
    UINT32      Rem;
147
    UINT32      bit;        
148
 
149
    ASSERT (Divisor != 0);
150
    ASSERT ((Divisor >> 31) == 0);
151
 
152
    //
153
    // For each bit in the dividend
154
    //
155
 
156
    Rem = 0;
157
    for (bit=0; bit < 64; bit++) {
158
        _asm {
159
            shl     dword ptr Dividend[0], 1    ; shift rem:dividend left one
160
            rcl     dword ptr Dividend[4], 1    
161
            rcl     dword ptr Rem, 1            
162
 
163
            mov     eax, Rem
164
            cmp     eax, Divisor                ; Is Rem >= Divisor?
165
            cmc                                 ; No - do nothing
166
            sbb     eax, eax                    ; Else,
167
            sub     dword ptr Dividend[0], eax  ;   set low bit in dividen
168
            and     eax, Divisor                ; and
169
            sub     Rem, eax                    ;   subtract divisor
170
        }
171
    }
172
 
173
    if (Remainder) {
174
        *Remainder = Rem;
175
    }
176
 
177
    return Dividend;
178
#endif
179
}