Splits x86 into 32 and 64 bit (XCC)
[akaros.git] / user / parlib / include / x86 / arch.h
1 #ifndef PARLIB_ARCH_H
2 #define PARLIB_ARCH_H
3
4 #include <ros/trapframe.h>
5 #include <ros/arch/mmu.h>
6 #include <ros/common.h>
7 #include <string.h>
8
9 #define internal_function   __attribute ((regparm (3), stdcall))
10
11 #define ARCH_CL_SIZE 64
12 #ifdef __x86_64__
13
14 #define X86_REG_BP                                      "rbp"
15 #define X86_REG_SP                                      "rsp"
16 #define X86_REG_IP                                      "rip"
17 #define X86_REG_AX                                      "rax"
18 #define X86_REG_BX                                      "rbx"
19 #define X86_REG_CX                                      "rcx"
20 #define X86_REG_DX                                      "rdx"
21
22 #else /* 32 bit */
23
24 #define X86_REG_BP                                      "ebp"
25 #define X86_REG_SP                                      "esp"
26 #define X86_REG_IP                                      "eip"
27 #define X86_REG_AX                                      "eax"
28 #define X86_REG_BX                                      "ebx"
29 #define X86_REG_CX                                      "ecx"
30 #define X86_REG_DX                                      "edx"
31
32 #endif /* 64bit / 32bit */
33
34 /* Make sure you subtract off/save enough space at the top of the stack for
35  * whatever you compiler might want to use when calling a noreturn function or
36  * to handle a HW spill or whatever. */
37 static inline void __attribute__((always_inline))
38 set_stack_pointer(void *sp)
39 {
40         asm volatile("mov %0,%%"X86_REG_SP"" : : "r"(sp) : "memory", X86_REG_SP);
41 }
42
43 static inline void breakpoint(void)
44 {
45         asm volatile("int3");
46 }
47
48 static inline uint64_t read_tsc(void)
49 {
50         uint32_t edx, eax;
51         asm volatile("rdtsc" : "=d"(edx), "=a"(eax));
52         return (uint64_t)edx << 32 | eax;
53 }
54
55 /* non-core-id reporting style (it is in ecx) */
56 static inline uint64_t read_tscp(void)
57 {
58         uint32_t edx, eax;
59         asm volatile("rdtscp" : "=d"(edx), "=a"(eax) : : X86_REG_CX);
60         return (uint64_t)edx << 32 | eax;
61 }
62
63 static inline void cpuid(uint32_t info1, uint32_t info2, uint32_t *eaxp,
64                          uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
65 {
66         uint32_t eax, ebx, ecx, edx;
67         /* Can select with both eax (info1) and ecx (info2) */
68         asm volatile("cpuid" 
69                 : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
70                 : "a" (info1), "c" (info2));
71         if (eaxp)
72                 *eaxp = eax;
73         if (ebxp)
74                 *ebxp = ebx;
75         if (ecxp)
76                 *ecxp = ecx;
77         if (edxp)
78                 *edxp = edx;
79 }
80
81
82 /* Check out k/a/x86/rdtsc_test.c for more info */
83 static inline uint64_t read_tsc_serialized(void)
84 {
85         asm volatile("lfence"); /* mfence on amd */
86         return read_tsc();
87 }
88
89 static inline void cpu_relax(void)
90 {
91         asm volatile("pause" : : : "memory");
92 }
93
94 static inline uint64_t read_pmc(uint32_t index)
95 {
96         uint32_t edx, eax;
97         asm volatile("rdpmc" : "=d"(edx), "=a"(eax) : "c"(index));
98         return (uint64_t)edx << 32 | eax;
99 }
100
101 static inline void save_fp_state(struct ancillary_state *silly)
102 {
103         asm volatile("fxsave %0" : : "m"(*silly));
104 }
105
106 static inline void restore_fp_state(struct ancillary_state *silly)
107 {
108         asm volatile("fxrstor %0" : : "m"(*silly));
109 }
110
111 #endif /* PARLIB_ARCH_H */