@@ -78,6 +78,87 @@ GLOBL _rt0_amd64_lib_argc<>(SB),NOPTR, $8
78
78
DATA _rt0_amd64_lib_argv<>(SB)/8 , $0
79
79
GLOBL _rt0_amd64_lib_argv<>(SB),NOPTR, $8
80
80
81
+ #ifdef GOAMD64_v2
82
+ DATA bad_cpu_msg<>+0x00 (SB)/84 , $"This program can only be run on AMD64 processors with v2 microarchitecture support.\n"
83
+ #endif
84
+
85
+ #ifdef GOAMD64_v3
86
+ DATA bad_cpu_msg<>+0x00 (SB)/84 , $"This program can only be run on AMD64 processors with v3 microarchitecture support.\n"
87
+ #endif
88
+
89
+ #ifdef GOAMD64_v4
90
+ DATA bad_cpu_msg<>+0x00 (SB)/84 , $"This program can only be run on AMD64 processors with v4 microarchitecture support.\n"
91
+ #endif
92
+
93
+ GLOBL bad_cpu_msg<>(SB), RODATA, $84
94
+
95
+ // Define a list of AMD64 microarchitecture level features
96
+ // https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels
97
+
98
+ // SSE3 SSSE3 CMPXCHNG16 SSE4.1 SSE4.2 POPCNT
99
+ #define V2_FEATURES_CX (1 << 0 | 1 << 9 | 1 << 13 | 1 << 19 | 1 << 20 | 1 << 23 )
100
+ // LAHF/SAHF
101
+ #define V2_EXT_FEATURES_CX (1 << 0 )
102
+ // FMA MOVBE OSXSAVE AVX F16C
103
+ #define V3_FEATURES_CX (V2_FEATURES_CX | 1 << 12 | 1 << 22 | 1 << 27 | 1 << 28 | 1 << 29 )
104
+ // ABM (FOR LZNCT)
105
+ #define V3_EXT_FEATURES_CX (V2_EXT_FEATURES_CX | 1 << 5 )
106
+ // BMI1 AVX2 BMI2
107
+ #define V3_EXT_FEATURES_BX (1 << 3 | 1 << 5 | 1 << 8 )
108
+ // XMM YMM
109
+ #define V3_OS_SUPPORT_AX (1 << 1 | 1 << 2 )
110
+
111
+ #define V4_FEATURES_CX V3_FEATURES_CX
112
+
113
+ #define V4_EXT_FEATURES_CX V3_EXT_FEATURES_CX
114
+ // AVX512F AVX512DQ AVX512CD AVX512BW AVX512VL
115
+ #define V4_EXT_FEATURES_BX (V3_EXT_FEATURES_BX | 1 << 16 | 1 << 17 | 1 << 28 | 1 << 30 | 1 << 31 )
116
+ // OPMASK ZMM
117
+ #define V4_OS_SUPPORT_AX (V3_OS_SUPPORT_AX | 1 << 5 | (1 << 6 | 1 << 7 ))
118
+
119
+ #ifdef GOAMD64_v2
120
+ #define NEED_MAX_CPUID 0x80000001
121
+ #define NEED_FEATURES_CX V2_FEATURES_CX
122
+ #define NEED_EXT_FEATURES_CX V2_EXT_FEATURES_CX
123
+ #endif
124
+
125
+ #ifdef GOAMD64_v3
126
+ #define NEED_MAX_CPUID 0x80000001
127
+ #define NEED_FEATURES_CX V3_FEATURES_CX
128
+ #define NEED_EXT_FEATURES_CX V3_EXT_FEATURES_CX
129
+ #define NEED_EXT_FEATURES_BX V3_EXT_FEATURES_BX
130
+ #define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX
131
+ #endif
132
+
133
+ #ifdef GOAMD64_v4
134
+ #define NEED_MAX_CPUID 0x80000001
135
+ #define NEED_FEATURES_CX V4_FEATURES_CX
136
+ #define NEED_EXT_FEATURES_CX V4_EXT_FEATURES_CX
137
+ #define NEED_EXT_FEATURES_BX V4_EXT_FEATURES_BX
138
+
139
+ // Downgrading v4 OS checks on Darwin for now, see CL 285572.
140
+ #ifdef GOOS_darwin
141
+ #define NEED_OS_SUPPORT_AX V3_OS_SUPPORT_AX
142
+ #else
143
+ #define NEED_OS_SUPPORT_AX V4_OS_SUPPORT_AX
144
+ #endif
145
+
146
+ #endif
147
+
148
+ #ifdef GOAMD64_v1
149
+ #define SKIP_GOAMD64_CHECK
150
+ #endif
151
+
152
+ #ifndef GOAMD64_v1
153
+ #ifndef GOAMD64_v2
154
+ #ifndef GOAMD64_v3
155
+ #ifndef GOAMD64_v4
156
+ #define SKIP_GOAMD64_CHECK
157
+ #endif
158
+ #endif
159
+ #endif
160
+ #endif
161
+
81
162
TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
82
163
// copy arguments forward on an even stack
83
164
MOVQ DI, AX // argc
@@ -99,24 +180,76 @@ TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0
99
180
// find out information about the processor we're on
100
181
MOVL $0 , AX
101
182
CPUID
102
- MOVL AX, SI
103
183
CMPL AX, $0
184
+ #ifdef SKIP_GOAMD64_CHECK
104
185
JE nocpuinfo
186
+ #else
187
+ JNE has_cpuinfo
105
188
189
+ bad_cpu: // show that the program requires a certain microarchitecture level.
190
+ MOVQ $2 , 0 (SP)
191
+ MOVQ $bad_cpu_msg<>(SB), AX
192
+ MOVQ AX, 8 (SP)
193
+ MOVQ $84 , 16 (SP)
194
+ CALL runtime·write(SB)
195
+ MOVQ $1 , 0 (SP)
196
+ CALL runtime·exit(SB)
197
+ CALL runtime·abort(SB)
198
+ #endif
199
+
200
+ has_cpuinfo:
106
201
CMPL BX, $0x756E6547 // "Genu"
107
202
JNE notintel
108
203
CMPL DX, $0x49656E69 // "ineI"
109
204
JNE notintel
110
205
CMPL CX, $0x6C65746E // "ntel"
111
206
JNE notintel
112
207
MOVB $1 , runtime·isIntel(SB)
113
- notintel:
114
208
209
+ notintel:
115
210
// Load EAX=1 cpuid flags
116
211
MOVL $1 , AX
117
212
CPUID
118
213
MOVL AX, runtime·processorVersionInfo(SB)
119
214
215
+ #ifdef NEED_FEATURES_CX
216
+ ANDL $NEED_FEATURES_CX, CX
217
+ CMPL CX, $NEED_FEATURES_CX
218
+ JNE bad_cpu
219
+ #endif
220
+
221
+ #ifdef NEED_MAX_CPUID
222
+ MOVL $0x80000000 , AX
223
+ CPUID
224
+ CMPL AX, $NEED_MAX_CPUID
225
+ JL bad_cpu
226
+ #endif
227
+
228
+ #ifdef NEED_EXT_FEATURES_BX
229
+ MOVL $7 , AX
230
+ MOVL $0 , CX
231
+ CPUID
232
+ ANDL $NEED_EXT_FEATURES_BX, BX
233
+ CMPL BX, $NEED_EXT_FEATURES_BX
234
+ JNE bad_cpu
235
+ #endif
236
+
237
+ #ifdef NEED_EXT_FEATURES_CX
238
+ MOVL $0x80000001 , AX
239
+ CPUID
240
+ ANDL $NEED_EXT_FEATURES_CX, CX
241
+ CMPL CX, $NEED_EXT_FEATURES_CX
242
+ JNE bad_cpu
243
+ #endif
244
+
245
+ #ifdef NEED_OS_SUPPORT_AX
246
+ XORL CX, CX
247
+ XGETBV
248
+ ANDL $NEED_OS_SUPPORT_AX, AX
249
+ CMPL AX, $NEED_OS_SUPPORT_AX
250
+ JNE bad_cpu
251
+ #endif
252
+
120
253
nocpuinfo:
121
254
// if there is an _cgo_init, call it.
122
255
MOVQ _cgo_init(SB), AX
0 commit comments