source: trunk/src/emx/include/386/builtin.h@ 902

Last change on this file since 902 was 659, checked in by bird, 22 years ago

Changed to doxygen for header status.

  • Property cvs2svn:cvs-rev set to 1.4
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 6.2 KB
Line 
1/* 386/builtin.h (emx+gcc) */
2/** @file
3 * EMX 0.9d-fix04
4 */
5
6#ifndef _I386_BUILTIN_H
7#define _I386_BUILTIN_H
8
9#if defined (__cplusplus)
10extern "C" {
11#endif
12
13static __inline__ signed char __cxchg (__volatile__ signed char *p,
14 signed char v)
15{
16 __asm__ __volatile__ ("xchgb %0, %1" : "=m"(*p), "=r"(v) : "1"(v));
17 return v;
18}
19
20static __inline__ short __sxchg (__volatile__ short *p, short v)
21{
22 __asm__ __volatile__ ("xchgw %0, %1" : "=m"(*p), "=r"(v) : "1"(v));
23 return v;
24}
25
26static __inline__ int __lxchg (__volatile__ int *p, int v)
27{
28 __asm__ __volatile__ ("xchgl %0, %1" : "=m"(*p), "=r"(v) : "1"(v));
29 return v;
30}
31
32static __inline__ void __enable (void)
33{
34 __asm__ __volatile__ ("sti");
35}
36
37static __inline__ void __disable (void)
38{
39 __asm__ __volatile__ ("cli");
40}
41
42#define __ROTATE_FUN(F,I,T) \
43 static __inline__ T F (T value, int shift) \
44 { \
45 __asm__ (I " %b2, %0" : "=g"(value) : "0"(value), "c"(shift) : "cc"); \
46 return value; \
47 } \
48 static __inline__ T F##1 (T value) \
49 { \
50 __asm__ (I " $1, %0" : "=g"(value) : "0"(value) : "cc"); \
51 return value; \
52 }
53
54#define __ROTATE(V,S,F) ((__builtin_constant_p (S) && (int)(S) == 1) \
55 ? F##1 (V) : F (V, S))
56
57__ROTATE_FUN (__crotr, "rorb", unsigned char)
58__ROTATE_FUN (__srotr, "rorw", unsigned short)
59__ROTATE_FUN (__lrotr, "rorl", unsigned long)
60
61__ROTATE_FUN (__crotl, "rolb", unsigned char)
62__ROTATE_FUN (__srotl, "rolw", unsigned short)
63__ROTATE_FUN (__lrotl, "roll", unsigned long)
64
65#define _crotr(V,S) __ROTATE (V, S, __crotr)
66#define _srotr(V,S) __ROTATE (V, S, __srotr)
67#define _lrotr(V,S) __ROTATE (V, S, __lrotr)
68#define _crotl(V,S) __ROTATE (V, S, __crotl)
69#define _srotl(V,S) __ROTATE (V, S, __srotl)
70#define _lrotl(V,S) __ROTATE (V, S, __lrotl)
71
72#define _rotr(V,S) _lrotr (V, S)
73#define _rotl(V,S) _lrotl (V, S)
74
75
76static __inline__ int __fls (int v)
77{
78 int r;
79
80 __asm__ __volatile__ ("bsrl %1, %0;"
81 "jnz 1f;"
82 "movl $-1, %0;"
83 ".align 2, 0x90;"
84 "1:"
85 : "=r"(r) : "r"(v) : "cc");
86 return r + 1;
87}
88
89/* Quick routines similar to div() and friends, but inline */
90
91static __inline__ long __ldivmod (long num, long den, long *rem)
92{
93 long q, r;
94 __asm__ ("cltd; idivl %2"
95 : "=a" (q), "=&d" (r)
96 : "r?m" (den), "a" (num));
97 *rem = r;
98 return q;
99}
100
101static __inline__ unsigned long __uldivmod (unsigned long num,
102 unsigned long den, unsigned long *rem)
103{
104 unsigned long q, r;
105 __asm__ ("xorl %%edx,%%edx; divl %2"
106 : "=a" (q), "=&d" (r)
107 : "r?m" (den), "a" (num));
108 *rem = r;
109 return q;
110}
111
112/*
113 Divide a 64-bit integer by a 32-bit one:
114
115 A*2^32 + B A B + (A mod 32)
116 ---------- = --- * 2^32 + ----------------
117 C C C
118*/
119static __inline__ long long __lldivmod (long long num, long den, long *rem)
120{
121 long long q;
122 long r;
123 __asm__ (" movl %%eax,%%esi;"
124 " movl %%edx,%%eax;"
125 " pushl %%edx;"
126 " cltd;"
127 " idivl %2;"
128 " ;"
129/* Now ensure remainder is smallest of possible two values (negative and
130 positive). For this we compare the remainder with positive and negative
131 denominator/2; if it is smaller than one and bigger than another we
132 consider it optimal, otherwise it can be made smaller by adding or
133 subtracting denominator to it. This is done to ensure no overflow
134 will occur at next division. */
135 " movl %2,%%ecx;"
136 " sarl $1,%%ecx;" /* ecx = den/2 */
137 " cmpl %%ecx,%%edx;"
138 " setl %%bl;"
139 " negl %%ecx;"
140 " cmpl %%ecx,%%edx;"
141 " setl %%bh;"
142 " xorb %%bh,%%bl;"
143 " jnz 1f;" /* Remainder is between -den/2...den/2 */
144 " ;"
145/* If remainder has same sign as denominator, we have to do r -= den; q++;
146 otherwise we have to do r += den; q--; */
147 " movl %2,%%ebx;" /* ebx = den */
148 " xorl %%edx,%%ebx;" /* r ^ den */
149 " js 0f;" /* Different signs */
150 " subl %2,%%edx;" /* r -= den */
151 " addl $1,%%eax;" /* q++ */
152 " adcl $0,%%edx;"
153 " jmp 1f;"
154 " ;"
155 "0: addl %2,%%edx;" /* r += den */
156 " subl $1,%%eax;" /* q-- */
157 " sbbl $0,%%edx;"
158 " ;"
159 "1: xchgl %%eax,%%esi;"
160 " idivl %2;"
161 " ;"
162 " movl %%edx,%1;"
163 " cltd;"
164 " addl %%esi,%%edx;"
165 " ;"
166/* Check if numerator has the same sign as remainder; if they have different
167 sign we should make the remainder have same sign as numerator to comply
168 with ANSI standard, which says we always should truncate the quotient
169 towards zero. */
170 " popl %%ebx;" /* ebx = num >> 32 */
171 " xorl %1,%%ebx;" /* sign(r) ^ sign(num) */
172 " jns 3f;" /* jump if same sign */
173 " ;"
174/* If remainder has same sign as denominator, we have to do r -= den; q++;
175 otherwise we have to do r += den; q--; */
176 " movl %2,%%ebx;"
177 " xorl %1,%%ebx;" /* r ^ den */
178 " js 2f;" /* Different signs */
179 " subl %2,%1;" /* r -= den */
180 " addl $1,%%eax;" /* q++ */
181 " adcl $0,%%edx;"
182 " jmp 3f;"
183 " ;"
184 "2: addl %2,%1;" /* r += den */
185 " subl $1,%%eax;" /* q-- */
186 " sbbl $0,%%edx;"
187 " ;"
188 "3: ;"
189 : "=A" (q), "=&c" (r)
190 : "r" (den), "A" (num)
191 : "ebx", "esi");
192 *rem = r;
193 return q;
194}
195
196/*
197 Same as __lldivmod except that if A < C, we can do just one division
198 instead of two because the result is always a 32-bit integer.
199*/
200static __inline__ unsigned long long __ulldivmod (unsigned long long num,
201 unsigned long den, unsigned long *rem)
202{
203 unsigned long long q;
204 unsigned long r;
205 __asm__ (" movl %%eax,%1;"
206 " movl %%edx,%%eax;"
207 " xorl %%edx,%%edx;"
208 " divl %2;"
209 " xchgl %%eax,%%ecx;"
210 " divl %2;"
211 " xchgl %%edx,%1;"
212 : "=A" (q), "=c" (r)
213 : "r?m" (den), "A" (num));
214 *rem = r;
215 return q;
216}
217
218#if defined (__cplusplus)
219}
220#endif
221
222#endif /* not _I386_BUILTIN_H */
Note: See TracBrowser for help on using the repository browser.