aboutsummaryrefslogtreecommitdiff
path: root/src/libmpg123/getcpuflags.S
blob: 29ab08de63ca3195874431f38c9d38aa453fb7e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
	getcpucpuflags: get cpuflags for ia32

	copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1
	see COPYING and AUTHORS files in distribution or http:#mpg123.org
	initially written by KIMURA Takuhiro (for 3DNow!)
	extended for general use by Thomas Orgis

	 extern int getcpuid(struct cpuflags*)
	or just 
	 extern int getcpuid(unsigned int*)
	where there is memory for 4 ints
	 -> the first set of idflags (basic cpu family info)
	    and the idflags, stdflags, std2flags, extflags written to the parameter
	 -> 0x00000000 (CPUID instruction not supported)
*/

#include "mangle.h"

.text
	ALIGN4

.globl ASM_NAME(getcpuflags)
/*	.type ASM_NAME(getcpuflags),@function */
ASM_NAME(getcpuflags):
	pushl %ebp
	movl %esp,%ebp
	pushl %edx
	pushl %ecx
	pushl %ebx
	pushl %esi
/* get the int pointer for storing the flags */
	movl 8(%ebp), %esi
/* does that one make sense? */
	movl $0x80000000,%eax
/* now save the flags and do a check for cpuid availability */
	pushfl
	pushfl
	popl %eax
	movl %eax,%ebx
/* set that bit... */
	xorl $0x00200000,%eax
	pushl %eax
	popfl
/* ...and read back the flags to see if it is understood */
	pushfl
	popl %eax
	popfl
	cmpl %ebx,%eax
	je .Lnocpuid
/* In principle, I would have to check the CPU's identify first to be sure how to interpret the extended flags. */
/* now get the info, first extended */
	movl $0x0, 12(%esi) /* clear value */
/* only if supported... */
	movl $0x80000000, %eax
	cpuid
/* IDT CPUs should not change EAX, generally I hope that non-3DNow cpus do not set a bogus support level here. */
	cmpl $0x80000001, %eax
	jb .Lnoextended /* Skip ext check without minimal support level. */
/* is supported, get flags value */
	movl $0x80000001,%eax
	cpuid
	movl %edx,12(%esi)
.Lnoextended:
/* then the other ones, called last to get the id flags in %eax for ret */
	movl $0x00000001,%eax
	cpuid
	movl %eax, (%esi)
	movl %ecx, 4(%esi)
	movl %edx, 8(%esi)
	jmp .Lend
	ALIGN4
.Lnocpuid:
/* error: set everything to zero */
	movl $0, %eax
	movl $0, (%esi)
	movl $0, 4(%esi)
	movl $0, 8(%esi)
	movl $0, 12(%esi)
	ALIGN4
.Lend:
/* return value are the id flags, still stored in %eax */
	popl %esi
	popl %ebx
	popl %ecx
	popl %edx
	movl %ebp,%esp
	popl %ebp
	ret

/* Mark non-executable stack. */
#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif