Cleanups that will hopefully allow compilation in more strict environments
[tpg/acess2.git] / Kernel / arch / x86 / lib.c
1 /*
2  * AcessOS Microkernel Version
3  * lib.c
4  */
5 #include <acess.h>
6
7 // === CODE ===
8 void Spinlock(int *lock)
9 {
10          int    v = 1;
11         while(v)        __asm__ __volatile__ ("lock xchgl %%eax, (%%edi)":"=a"(v):"a"(1),"D"(lock));
12 }
13
14 void Release(int *lock)
15 {
16         __asm__ __volatile__ ("lock andl $0, (%0)"::"r"(lock));
17 }
18
19 // === IO Commands ===
20 void outb(Uint16 Port, Uint8 Data)
21 {
22         __asm__ __volatile__ ("outb %%al, %%dx"::"d"(Port),"a"(Data));
23 }
24 void outw(Uint16 Port, Uint16 Data)
25 {
26         __asm__ __volatile__ ("outw %%ax, %%dx"::"d"(Port),"a"(Data));
27 }
28 void outd(Uint16 Port, Uint32 Data)
29 {
30         __asm__ __volatile__ ("outl %%eax, %%dx"::"d"(Port),"a"(Data));
31 }
32 Uint8 inb(Uint16 Port)
33 {
34         Uint8   ret;
35         __asm__ __volatile__ ("inb %%dx, %%al":"=a"(ret):"d"(Port));
36         return ret;
37 }
38 Uint16 inw(Uint16 Port)
39 {
40         Uint16  ret;
41         __asm__ __volatile__ ("inw %%dx, %%ax":"=a"(ret):"d"(Port));
42         return ret;
43 }
44 Uint32 ind(Uint16 Port)
45 {
46         Uint32  ret;
47         __asm__ __volatile__ ("inl %%dx, %%eax":"=a"(ret):"d"(Port));
48         return ret;
49 }
50
51 /**
52  * \fn void *memset(void *Dest, int Val, size_t Num)
53  * \brief Do a byte granuality set of Dest
54  */
55 void *memset(void *Dest, int Val, size_t Num)
56 {
57         __asm__ __volatile__ (
58                 "rep stosl;\n\t"
59                 "mov %3, %%ecx;\n\t"
60                 "rep stosb"
61                 :: "D" (Dest), "a" (Val), "c" (Num/4), "r" (Num&3));
62         return Dest;
63 }
64 /**
65  * \brief Set double words
66  */
67 void *memsetd(void *Dest, Uint32 Val, size_t Num)
68 {
69         __asm__ __volatile__ ("rep stosl" :: "D" (Dest), "a" (Val), "c" (Num));
70         return Dest;
71 }
72
73 /**
74  * \fn int memcmp(const void *m1, const void *m2, size_t Num)
75  * \brief Compare two pieces of memory
76  */
77 int memcmp(const void *m1, const void *m2, size_t Num)
78 {
79         while(Num--)
80         {
81                 if(*(Uint8*)m1 != *(Uint8*)m2)  break;
82                 m1 ++;
83                 m2 ++;
84         }
85         return *(Uint8*)m1 - *(Uint8*)m2;
86 }
87
88 /**
89  * \fn void *memcpy(void *Dest, const void *Src, size_t Num)
90  * \brief Copy \a Num bytes from \a Src to \a Dest
91  */
92 void *memcpy(void *Dest, const void *Src, size_t Num)
93 {
94         if((Uint)Dest & 3 || (Uint)Src & 3)
95                 __asm__ __volatile__ ("rep movsb" :: "D" (Dest), "S" (Src), "c" (Num));
96         else {
97                 __asm__ __volatile__ (
98                         "rep movsl;\n\t"
99                         "mov %3, %%ecx;\n\t"
100                         "rep movsb"
101                         :: "D" (Dest), "S" (Src), "c" (Num/4), "r" (Num&3));
102         }
103         return Dest;
104 }
105 /**
106  * \fn void *memcpyd(void *Dest, const void *Src, size_t Num)
107  * \brief Copy \a Num DWORDs from \a Src to \a Dest
108  */
109 void *memcpyd(void *Dest, const void *Src, size_t Num)
110 {
111         __asm__ __volatile__ ("rep movsl" :: "D" (Dest), "S" (Src), "c" (Num));
112         return Dest;
113 }
114
115 /**
116  * \fn Uint64 __udivdi3(Uint64 Num, Uint64 Den)
117  * \brief Divide two 64-bit integers
118  */
119 Uint64 __udivdi3(Uint64 Num, Uint64 Den)
120 {
121         Uint64  ret = 0;
122         
123         if(Den == 0)    __asm__ __volatile__ ("int $0x0");      // Call Div by Zero Error
124         if(Den == 1)    return Num;     // Speed Hacks
125         if(Den == 2)    return Num >> 1;        // Speed Hacks
126         if(Den == 4)    return Num >> 2;        // Speed Hacks
127         if(Den == 8)    return Num >> 3;        // Speed Hacks
128         if(Den == 16)   return Num >> 4;        // Speed Hacks
129         if(Den == 32)   return Num >> 5;        // Speed Hacks
130         if(Den == 1024) return Num >> 10;       // Speed Hacks
131         if(Den == 2048) return Num >> 11;       // Speed Hacks
132         if(Den == 4096) return Num >> 12;
133         
134         if(Num >> 32 == 0 && Den >> 32 == 0)
135                 return (Uint32)Num / (Uint32)Den;
136         
137         //Log("__udivdi3: (Num={0x%x:%x}, Den={0x%x:%x})",
138         //      Num>>32, Num&0xFFFFFFFF,
139         //      Den>>32, Den&0xFFFFFFFF);
140         
141         while(Num > Den) {
142                 ret ++;
143                 Num -= Den;
144         }
145         return ret;
146 }
147
148 /**
149  * \fn Uint64 __umoddi3(Uint64 Num, Uint64 Den)
150  * \brief Get the modulus of two 64-bit integers
151  */
152 Uint64 __umoddi3(Uint64 Num, Uint64 Den)
153 {
154         if(Den == 0)    __asm__ __volatile__ ("int $0x0");      // Call Div by Zero Error
155         if(Den == 1)    return 0;       // Speed Hacks
156         if(Den == 2)    return Num & 1; // Speed Hacks
157         if(Den == 4)    return Num & 3; // Speed Hacks
158         if(Den == 8)    return Num & 7; // Speed Hacks
159         if(Den == 16)   return Num & 15;        // Speed Hacks
160         if(Den == 32)   return Num & 31;        // Speed Hacks
161         if(Den == 1024) return Num & 1023;      // Speed Hacks
162         if(Den == 2048) return Num & 2047;      // Speed Hacks
163         if(Den == 4096) return Num & 4095;      // Speed Hacks
164         
165         if(Num >> 32 == 0 && Den >> 32 == 0)
166                 return (Uint32)Num % (Uint32)Den;
167         
168         while(Num > Den)
169                 Num -= Den;
170         return Num;
171 }
172
173 Uint16 LittleEndian16(Uint16 Val)
174 {
175         return Val;
176 }
177 Uint16 BigEndian16(Uint16 Val)
178 {
179         return ((Val&0xFF)<<8) | ((Val>>8)&0xFF);
180 }
181 Uint32 LittleEndian32(Uint32 Val)
182 {
183         return Val;
184 }
185 Uint32 BigEndian32(Uint32 Val)
186 {
187         return ((Val&0xFF)<<24) | ((Val&0xFF00)<<8) | ((Val>>8)&0xFF00) | ((Val>>24)&0xFF);
188 }
189
190 // --- EXPORTS ---
191 EXPORT(memcpy); EXPORT(memset);
192 EXPORT(memcmp);
193 //EXPORT(memcpyw);      EXPORT(memsetw);
194 EXPORT(memcpyd);        EXPORT(memsetd);
195 EXPORT(inb);    EXPORT(inw);    EXPORT(ind);
196 EXPORT(outb);   EXPORT(outw);   EXPORT(outd);
197 EXPORT(__udivdi3);      EXPORT(__umoddi3);
198
199 EXPORT(LittleEndian16); EXPORT(BigEndian16);
200 EXPORT(LittleEndian32); EXPORT(BigEndian32);

UCC git Repository :: git.ucc.asn.au