1/*
2	getcpucpuflags: get cpuflags for ia32
3
4	copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
5	see COPYING and AUTHORS files in distribution or http:#mpg123.org
6	initially written by KIMURA Takuhiro (for 3DNow!)
7	extended for general use by Thomas Orgis
8
9	 extern int getcpuid(struct cpuflags*)
10	or just
11	 extern int getcpuid(unsigned int*)
12	where there is memory for 4 ints
13	 -> the first set of idflags (basic cpu family info)
14	    and the idflags, stdflags, std2flags, extflags written to the parameter
15	 -> 0x00000000 (CPUID instruction not supported)
16*/
17
18#include "mangle.h"
19
20.text
21	ALIGN4
22
23.globl ASM_NAME(getcpuflags)
24/*	.type ASM_NAME(getcpuflags),@function */
25ASM_NAME(getcpuflags):
26	pushl %ebp
27	movl %esp,%ebp
28	pushl %edx
29	pushl %ecx
30	pushl %ebx
31	pushl %esi
32/* get the int pointer for storing the flags */
33	movl 8(%ebp), %esi
34/* does that one make sense? */
35	movl $0x80000000,%eax
36/* now save the flags and do a check for cpuid availability */
37	pushfl
38	pushfl
39	popl %eax
40	movl %eax,%ebx
41/* set that bit... */
42	xorl $0x00200000,%eax
43	pushl %eax
44	popfl
45/* ...and read back the flags to see if it is understood */
46	pushfl
47	popl %eax
48	popfl
49	cmpl %ebx,%eax
50	je .Lnocpuid
51/* In principle, I would have to check the CPU's identify first to be sure how to interpret the extended flags. */
52/* now get the info, first extended */
53	movl $0x0, 12(%esi) /* clear value */
54	movl $0x0, 16(%esi) /* clear value */
55/* only if supported... */
56	movl $0x80000000, %eax
57	cpuid
58/* IDT CPUs should not change EAX, generally I hope that non-3DNow cpus do not set a bogus support level here. */
59	cmpl $0x80000001, %eax
60	jb .Lnoextended /* Skip ext check without minimal support level. */
61/* is supported, get flags value */
62	movl $0x80000001,%eax
63	cpuid
64	movl %edx,12(%esi)
65.Lnoextended:
66/* then the other ones, called last to get the id flags in %eax for ret */
67	movl $0x00000001,%eax
68	cpuid
69	movl %eax, (%esi)
70	movl %ecx, 4(%esi)
71	movl %edx, 8(%esi)
72/* check if xgetbv instruction is available */
73	test	$0x04000000, %ecx
74	jz		.Lend
75	test	$0x08000000, %ecx
76	jz		.Lend
77	xor		%ecx, %ecx
78	.byte	0x0f, 0x01, 0xd0 /* xgetbv instruction */
79	movl	%eax, 16(%esi)
80	movl	(%esi), %eax
81	jmp .Lend
82	ALIGN4
83.Lnocpuid:
84/* error: set everything to zero */
85	movl $0, %eax
86	movl $0, (%esi)
87	movl $0, 4(%esi)
88	movl $0, 8(%esi)
89	movl $0, 12(%esi)
90	movl $0, 16(%esi)
91	ALIGN4
92.Lend:
93/* return value are the id flags, still stored in %eax */
94	popl %esi
95	popl %ebx
96	popl %ecx
97	popl %edx
98	movl %ebp,%esp
99	popl %ebp
100	ret
101
102NONEXEC_STACK
103