《操作系统》的实验代码。
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

191 рядки
5.5 KiB

12 роки тому
  1. #ifndef __LIBS_X86_H__
  2. #define __LIBS_X86_H__
  3. #include <defs.h>
  4. #define do_div(n, base) ({ \
  5. unsigned long __upper, __low, __high, __mod, __base; \
  6. __base = (base); \
  7. asm("" : "=a" (__low), "=d" (__high) : "A" (n)); \
  8. __upper = __high; \
  9. if (__high != 0) { \
  10. __upper = __high % __base; \
  11. __high = __high / __base; \
  12. } \
  13. asm("divl %2" : "=a" (__low), "=d" (__mod) \
  14. : "rm" (__base), "0" (__low), "1" (__upper)); \
  15. asm("" : "=A" (n) : "a" (__low), "d" (__high)); \
  16. __mod; \
  17. })
  18. static inline uint8_t inb(uint16_t port) __attribute__((always_inline));
  19. static inline void insl(uint32_t port, void *addr, int cnt) __attribute__((always_inline));
  20. static inline void outb(uint16_t port, uint8_t data) __attribute__((always_inline));
  21. static inline void outw(uint16_t port, uint16_t data) __attribute__((always_inline));
  22. static inline uint32_t read_ebp(void) __attribute__((always_inline));
  23. /* Pseudo-descriptors used for LGDT, LLDT(not used) and LIDT instructions. */
  24. struct pseudodesc {
  25. uint16_t pd_lim; // Limit
  26. uint32_t pd_base; // Base address
  27. } __attribute__ ((packed));
  28. static inline void lidt(struct pseudodesc *pd) __attribute__((always_inline));
  29. static inline void sti(void) __attribute__((always_inline));
  30. static inline void cli(void) __attribute__((always_inline));
  31. static inline void ltr(uint16_t sel) __attribute__((always_inline));
  32. static inline uint8_t
  33. inb(uint16_t port) {
  34. uint8_t data;
  35. asm volatile ("inb %1, %0" : "=a" (data) : "d" (port));
  36. return data;
  37. }
  38. static inline void
  39. insl(uint32_t port, void *addr, int cnt) {
  40. asm volatile (
  41. "cld;"
  42. "repne; insl;"
  43. : "=D" (addr), "=c" (cnt)
  44. : "d" (port), "0" (addr), "1" (cnt)
  45. : "memory", "cc");
  46. }
  47. static inline void
  48. outb(uint16_t port, uint8_t data) {
  49. asm volatile ("outb %0, %1" :: "a" (data), "d" (port));
  50. }
  51. static inline void
  52. outw(uint16_t port, uint16_t data) {
  53. asm volatile ("outw %0, %1" :: "a" (data), "d" (port));
  54. }
  55. static inline uint32_t
  56. read_ebp(void) {
  57. uint32_t ebp;
  58. asm volatile ("movl %%ebp, %0" : "=r" (ebp));
  59. return ebp;
  60. }
  61. static inline void
  62. lidt(struct pseudodesc *pd) {
  63. asm volatile ("lidt (%0)" :: "r" (pd));
  64. }
  65. static inline void
  66. sti(void) {
  67. asm volatile ("sti");
  68. }
  69. static inline void
  70. cli(void) {
  71. asm volatile ("cli");
  72. }
  73. static inline void
  74. ltr(uint16_t sel) {
  75. asm volatile ("ltr %0" :: "r" (sel));
  76. }
  77. static inline int __strcmp(const char *s1, const char *s2) __attribute__((always_inline));
  78. static inline char *__strcpy(char *dst, const char *src) __attribute__((always_inline));
  79. static inline void *__memset(void *s, char c, size_t n) __attribute__((always_inline));
  80. static inline void *__memmove(void *dst, const void *src, size_t n) __attribute__((always_inline));
  81. static inline void *__memcpy(void *dst, const void *src, size_t n) __attribute__((always_inline));
  82. #ifndef __HAVE_ARCH_STRCMP
  83. #define __HAVE_ARCH_STRCMP
  84. static inline int
  85. __strcmp(const char *s1, const char *s2) {
  86. int d0, d1, ret;
  87. asm volatile (
  88. "1: lodsb;"
  89. "scasb;"
  90. "jne 2f;"
  91. "testb %%al, %%al;"
  92. "jne 1b;"
  93. "xorl %%eax, %%eax;"
  94. "jmp 3f;"
  95. "2: sbbl %%eax, %%eax;"
  96. "orb $1, %%al;"
  97. "3:"
  98. : "=a" (ret), "=&S" (d0), "=&D" (d1)
  99. : "1" (s1), "2" (s2)
  100. : "memory");
  101. return ret;
  102. }
  103. #endif /* __HAVE_ARCH_STRCMP */
  104. #ifndef __HAVE_ARCH_STRCPY
  105. #define __HAVE_ARCH_STRCPY
  106. static inline char *
  107. __strcpy(char *dst, const char *src) {
  108. int d0, d1, d2;
  109. asm volatile (
  110. "1: lodsb;"
  111. "stosb;"
  112. "testb %%al, %%al;"
  113. "jne 1b;"
  114. : "=&S" (d0), "=&D" (d1), "=&a" (d2)
  115. : "0" (src), "1" (dst) : "memory");
  116. return dst;
  117. }
  118. #endif /* __HAVE_ARCH_STRCPY */
  119. #ifndef __HAVE_ARCH_MEMSET
  120. #define __HAVE_ARCH_MEMSET
  121. static inline void *
  122. __memset(void *s, char c, size_t n) {
  123. int d0, d1;
  124. asm volatile (
  125. "rep; stosb;"
  126. : "=&c" (d0), "=&D" (d1)
  127. : "0" (n), "a" (c), "1" (s)
  128. : "memory");
  129. return s;
  130. }
  131. #endif /* __HAVE_ARCH_MEMSET */
  132. #ifndef __HAVE_ARCH_MEMMOVE
  133. #define __HAVE_ARCH_MEMMOVE
  134. static inline void *
  135. __memmove(void *dst, const void *src, size_t n) {
  136. if (dst < src) {
  137. return __memcpy(dst, src, n);
  138. }
  139. int d0, d1, d2;
  140. asm volatile (
  141. "std;"
  142. "rep; movsb;"
  143. "cld;"
  144. : "=&c" (d0), "=&S" (d1), "=&D" (d2)
  145. : "0" (n), "1" (n - 1 + src), "2" (n - 1 + dst)
  146. : "memory");
  147. return dst;
  148. }
  149. #endif /* __HAVE_ARCH_MEMMOVE */
  150. #ifndef __HAVE_ARCH_MEMCPY
  151. #define __HAVE_ARCH_MEMCPY
  152. static inline void *
  153. __memcpy(void *dst, const void *src, size_t n) {
  154. int d0, d1, d2;
  155. asm volatile (
  156. "rep; movsl;"
  157. "movl %4, %%ecx;"
  158. "andl $3, %%ecx;"
  159. "jz 1f;"
  160. "rep; movsb;"
  161. "1:"
  162. : "=&c" (d0), "=&D" (d1), "=&S" (d2)
  163. : "0" (n / 4), "g" (n), "1" (dst), "2" (src)
  164. : "memory");
  165. return dst;
  166. }
  167. #endif /* __HAVE_ARCH_MEMCPY */
  168. #endif /* !__LIBS_X86_H__ */