[AMD64]
[reactos.git] / reactos / boot / freeldr / freeldr / arch / amd64 / i386cpu.S
1 /*
2 * FreeLoader
3 * Copyright (C) 2003 Eric Kohl
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 .text
21 .code16
22
23 #define ASM
24
25 #include <arch.h>
26
27 /*
28 * U32 CpuidSupported(VOID);
29 *
30 * RETURNS:
31 * 0x00000001: CPU supports the CPUID instruction
32 * 0x00000300: Found 80386 CPU
33 * 0x00000400: Found 80486 CPU without CPUID support
34 */
35
36 EXTERN(CpuidSupported)
37 .code32
38
39 pushl %ecx /* save ECX */
40
41 pushfl /* push original EFLAGS */
42 popl %eax /* get original EFLAGS */
43 movl %eax,%ecx /* save original EFLAGS */
44 xorl $0x40000,%eax /* flip AC bit in EFLAGS */
45 pushl %eax /* save new EFLAGS value on stack */
46 popfl /* replace current EFLAGS value */
47
48 pushfl /* get new EFLAGS */
49 popl %eax /* store new EFLAGS in EAX */
50 xorl %ecx, %eax /* can't toggle AC bit, processor=80386 */
51
52 movl $0x300,%eax /* return processor id */
53 jz NoCpuid /* jump if 80386 processor */
54
55 pushl %ecx
56 popfl /* restore AC bit in EFLAGS first */
57
58 movl %ecx,%eax /* get original EFLAGS */
59 xorl $0x200000,%eax /* flip ID bit in EFLAGS */
60 pushl %eax /* save new EFLAGS value on stack */
61 popfl /* replace current EFLAGS value */
62 pushfl /* get new EFLAGS */
63 popl %eax /* store new EFLAGS in EAX */
64 xorl %ecx,%eax /* can't toggle ID bit, */
65
66 movl $0x400,%eax /* return processor id */
67 je NoCpuid /* processor=80486 */
68
69 movl $1,%eax /* CPUID supported */
70
71 NoCpuid:
72 pushl %ecx
73 popfl /* restore EFLAGS */
74 popl %ecx /* retore ECX */
75
76 ret
77
78
79 /*
80 * VOID GetCpuid(U32 Level, U32 *eax, U32 *ebx, U32 *ecx, U32 *edx);
81 */
82
83 EXTERN(GetCpuid)
84 .code32
85
86 pushl %ebp
87 movl %esp,%ebp
88
89 pushl %eax
90 pushl %ebx
91 pushl %ecx
92 pushl %edx
93 pushl %esi
94
95 movl 0x08(%ebp),%eax
96
97 cpuid
98
99 movl 0x0C(%ebp),%esi
100 movl %eax,(%esi)
101
102 movl 0x10(%ebp),%esi
103 movl %ebx,(%esi)
104
105 movl 0x14(%ebp),%esi
106 movl %ecx,(%esi)
107
108 movl 0x18(%ebp),%esi
109 movl %edx,(%esi)
110
111 popl %esi
112 popl %edx
113 popl %ecx
114 popl %ebx
115 popl %eax
116
117 movl %ebp,%esp
118 popl %ebp
119 ret
120
121
122 /*
123 * U64 RDTSC(VOID);
124 */
125
126 EXTERN(RDTSC)
127 .code32
128 rdtsc
129 ret
130
131 /* EOF */