blob: 212673f8028d05983f632630c1773f66ef791824 [file] [log] [blame]
njnf536bbb2005-06-13 04:21:38 +00001/*--------------------------------------------------------------------*/
2/*--- Machine-related stuff. m_machine.c ---*/
3/*--------------------------------------------------------------------*/
4
5/*
6 This file is part of Valgrind, a dynamic binary instrumentation
7 framework.
8
sewardj0f157dd2013-10-18 14:27:36 +00009 Copyright (C) 2000-2013 Julian Seward
njnf536bbb2005-06-13 04:21:38 +000010 jseward@acm.org
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 02111-1307, USA.
26
27 The GNU General Public License is contained in the file COPYING.
28*/
29
njnc7561b92005-06-19 01:24:32 +000030#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000031#include "pub_core_vki.h"
sewardj6c591e12011-04-11 16:17:51 +000032#include "pub_core_libcsetjmp.h" // setjmp facilities
njnc7561b92005-06-19 01:24:32 +000033#include "pub_core_threadstate.h"
njnf536bbb2005-06-13 04:21:38 +000034#include "pub_core_libcassert.h"
35#include "pub_core_libcbase.h"
sewardj2c3f2ea2011-04-13 15:40:10 +000036#include "pub_core_libcfile.h"
floriandf14eea2012-12-09 17:30:45 +000037#include "pub_core_libcprint.h"
sewardj2c3f2ea2011-04-13 15:40:10 +000038#include "pub_core_mallocfree.h"
njnf536bbb2005-06-13 04:21:38 +000039#include "pub_core_machine.h"
sewardje2d1e672005-11-12 23:10:48 +000040#include "pub_core_cpuid.h"
bart1581e742009-01-13 07:49:14 +000041#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL and SIGFPE
sewardj3b0cae72009-05-28 17:15:41 +000042#include "pub_core_debuglog.h"
sewardje3826cf2005-11-13 00:30:22 +000043
njnf536bbb2005-06-13 04:21:38 +000044
njnaf839f52005-06-23 03:27:57 +000045#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
46#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
47#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
njnf536bbb2005-06-13 04:21:38 +000048
sewardj1dbd3372010-08-22 12:21:14 +000049Addr VG_(get_IP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000050 return INSTR_PTR( VG_(threads)[tid].arch );
51}
sewardj1dbd3372010-08-22 12:21:14 +000052Addr VG_(get_SP) ( ThreadId tid ) {
53 return STACK_PTR( VG_(threads)[tid].arch );
54}
55Addr VG_(get_FP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000056 return FRAME_PTR( VG_(threads)[tid].arch );
57}
58
sewardj1dbd3372010-08-22 12:21:14 +000059void VG_(set_IP) ( ThreadId tid, Addr ip ) {
njnf536bbb2005-06-13 04:21:38 +000060 INSTR_PTR( VG_(threads)[tid].arch ) = ip;
61}
sewardj1dbd3372010-08-22 12:21:14 +000062void VG_(set_SP) ( ThreadId tid, Addr sp ) {
63 STACK_PTR( VG_(threads)[tid].arch ) = sp;
64}
sewardj59570ff2010-01-01 11:59:33 +000065
66void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
67 ThreadId tid )
68{
69# if defined(VGA_x86)
70 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_EIP;
71 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_ESP;
72 regs->misc.X86.r_ebp
73 = VG_(threads)[tid].arch.vex.guest_EBP;
74# elif defined(VGA_amd64)
75 regs->r_pc = VG_(threads)[tid].arch.vex.guest_RIP;
76 regs->r_sp = VG_(threads)[tid].arch.vex.guest_RSP;
77 regs->misc.AMD64.r_rbp
78 = VG_(threads)[tid].arch.vex.guest_RBP;
79# elif defined(VGA_ppc32)
80 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000081 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000082 regs->misc.PPC32.r_lr
83 = VG_(threads)[tid].arch.vex.guest_LR;
carllcae0cc22014-08-07 23:17:29 +000084# elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
sewardj59570ff2010-01-01 11:59:33 +000085 regs->r_pc = VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000086 regs->r_sp = VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000087 regs->misc.PPC64.r_lr
88 = VG_(threads)[tid].arch.vex.guest_LR;
89# elif defined(VGA_arm)
sewardj1dbd3372010-08-22 12:21:14 +000090 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_R15T;
sewardj59570ff2010-01-01 11:59:33 +000091 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_R13;
92 regs->misc.ARM.r14
93 = VG_(threads)[tid].arch.vex.guest_R14;
94 regs->misc.ARM.r12
95 = VG_(threads)[tid].arch.vex.guest_R12;
96 regs->misc.ARM.r11
97 = VG_(threads)[tid].arch.vex.guest_R11;
sewardjfa5ce562010-09-23 22:05:59 +000098 regs->misc.ARM.r7
99 = VG_(threads)[tid].arch.vex.guest_R7;
sewardjf0c12502014-01-12 12:54:00 +0000100# elif defined(VGA_arm64)
101 regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
sewardj03451882014-01-15 10:25:55 +0000102 regs->r_sp = VG_(threads)[tid].arch.vex.guest_XSP;
sewardjf0c12502014-01-12 12:54:00 +0000103 regs->misc.ARM64.x29 = VG_(threads)[tid].arch.vex.guest_X29;
104 regs->misc.ARM64.x30 = VG_(threads)[tid].arch.vex.guest_X30;
sewardjb5b87402011-03-07 16:05:35 +0000105# elif defined(VGA_s390x)
106 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_IA;
107 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_SP;
108 regs->misc.S390X.r_fp
109 = VG_(threads)[tid].arch.vex.guest_r11;
110 regs->misc.S390X.r_lr
111 = VG_(threads)[tid].arch.vex.guest_r14;
sewardj5db15402012-06-07 09:13:21 +0000112# elif defined(VGA_mips32)
113 regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
114 regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
115 regs->misc.MIPS32.r30
116 = VG_(threads)[tid].arch.vex.guest_r30;
117 regs->misc.MIPS32.r31
118 = VG_(threads)[tid].arch.vex.guest_r31;
119 regs->misc.MIPS32.r28
120 = VG_(threads)[tid].arch.vex.guest_r28;
petarj4df0bfc2013-02-27 23:17:33 +0000121# elif defined(VGA_mips64)
122 regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
123 regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
124 regs->misc.MIPS64.r30
125 = VG_(threads)[tid].arch.vex.guest_r30;
126 regs->misc.MIPS64.r31
127 = VG_(threads)[tid].arch.vex.guest_r31;
128 regs->misc.MIPS64.r28
129 = VG_(threads)[tid].arch.vex.guest_r28;
sewardj59570ff2010-01-01 11:59:33 +0000130# else
131# error "Unknown arch"
132# endif
133}
134
sewardj7cf4e6b2008-05-01 20:24:26 +0000135void
136VG_(get_shadow_regs_area) ( ThreadId tid,
137 /*DST*/UChar* dst,
njnc4431bf2009-01-15 21:29:24 +0000138 /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size )
njnf536bbb2005-06-13 04:21:38 +0000139{
sewardj7cf4e6b2008-05-01 20:24:26 +0000140 void* src;
njnf536bbb2005-06-13 04:21:38 +0000141 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000142 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000143 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000144 // Bounds check
145 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
146 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000147 // Copy
148 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000149 src = NULL;
150 switch (shadowNo) {
151 case 0: src = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
152 case 1: src = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
153 case 2: src = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
154 }
floriane2800c92014-09-15 20:57:45 +0000155 vg_assert(src != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000156 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000157}
158
sewardj7cf4e6b2008-05-01 20:24:26 +0000159void
160VG_(set_shadow_regs_area) ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +0000161 /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
sewardj7cf4e6b2008-05-01 20:24:26 +0000162 /*SRC*/const UChar* src )
njnf536bbb2005-06-13 04:21:38 +0000163{
sewardj7cf4e6b2008-05-01 20:24:26 +0000164 void* dst;
njnf536bbb2005-06-13 04:21:38 +0000165 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000166 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000167 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000168 // Bounds check
169 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
170 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000171 // Copy
172 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000173 dst = NULL;
174 switch (shadowNo) {
175 case 0: dst = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
176 case 1: dst = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
177 case 2: dst = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
178 }
floriane2800c92014-09-15 20:57:45 +0000179 vg_assert(dst != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000180 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000181}
182
183
florian6bd9dc12012-11-23 16:17:43 +0000184static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId,
185 const HChar*, Addr))
njn6ace3ea2005-06-17 03:06:27 +0000186{
philippea22f59d2012-01-26 23:13:52 +0000187 VexGuestArchState* vex = &(VG_(get_ThreadState)(tid)->arch.vex);
philippeb8ba0312013-10-21 19:57:08 +0000188 VG_(debugLog)(2, "machine", "apply_to_GPs_of_tid %d\n", tid);
njn6ace3ea2005-06-17 03:06:27 +0000189#if defined(VGA_x86)
philippea22f59d2012-01-26 23:13:52 +0000190 (*f)(tid, "EAX", vex->guest_EAX);
191 (*f)(tid, "ECX", vex->guest_ECX);
192 (*f)(tid, "EDX", vex->guest_EDX);
193 (*f)(tid, "EBX", vex->guest_EBX);
194 (*f)(tid, "ESI", vex->guest_ESI);
195 (*f)(tid, "EDI", vex->guest_EDI);
196 (*f)(tid, "ESP", vex->guest_ESP);
197 (*f)(tid, "EBP", vex->guest_EBP);
njn6ace3ea2005-06-17 03:06:27 +0000198#elif defined(VGA_amd64)
philippea22f59d2012-01-26 23:13:52 +0000199 (*f)(tid, "RAX", vex->guest_RAX);
200 (*f)(tid, "RCX", vex->guest_RCX);
201 (*f)(tid, "RDX", vex->guest_RDX);
202 (*f)(tid, "RBX", vex->guest_RBX);
203 (*f)(tid, "RSI", vex->guest_RSI);
204 (*f)(tid, "RDI", vex->guest_RDI);
205 (*f)(tid, "RSP", vex->guest_RSP);
206 (*f)(tid, "RBP", vex->guest_RBP);
207 (*f)(tid, "R8" , vex->guest_R8 );
208 (*f)(tid, "R9" , vex->guest_R9 );
209 (*f)(tid, "R10", vex->guest_R10);
210 (*f)(tid, "R11", vex->guest_R11);
211 (*f)(tid, "R12", vex->guest_R12);
212 (*f)(tid, "R13", vex->guest_R13);
213 (*f)(tid, "R14", vex->guest_R14);
214 (*f)(tid, "R15", vex->guest_R15);
carllcae0cc22014-08-07 23:17:29 +0000215#elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
philippea22f59d2012-01-26 23:13:52 +0000216 (*f)(tid, "GPR0" , vex->guest_GPR0 );
217 (*f)(tid, "GPR1" , vex->guest_GPR1 );
218 (*f)(tid, "GPR2" , vex->guest_GPR2 );
219 (*f)(tid, "GPR3" , vex->guest_GPR3 );
220 (*f)(tid, "GPR4" , vex->guest_GPR4 );
221 (*f)(tid, "GPR5" , vex->guest_GPR5 );
222 (*f)(tid, "GPR6" , vex->guest_GPR6 );
223 (*f)(tid, "GPR7" , vex->guest_GPR7 );
224 (*f)(tid, "GPR8" , vex->guest_GPR8 );
225 (*f)(tid, "GPR9" , vex->guest_GPR9 );
226 (*f)(tid, "GPR10", vex->guest_GPR10);
227 (*f)(tid, "GPR11", vex->guest_GPR11);
228 (*f)(tid, "GPR12", vex->guest_GPR12);
229 (*f)(tid, "GPR13", vex->guest_GPR13);
230 (*f)(tid, "GPR14", vex->guest_GPR14);
231 (*f)(tid, "GPR15", vex->guest_GPR15);
232 (*f)(tid, "GPR16", vex->guest_GPR16);
233 (*f)(tid, "GPR17", vex->guest_GPR17);
234 (*f)(tid, "GPR18", vex->guest_GPR18);
235 (*f)(tid, "GPR19", vex->guest_GPR19);
236 (*f)(tid, "GPR20", vex->guest_GPR20);
237 (*f)(tid, "GPR21", vex->guest_GPR21);
238 (*f)(tid, "GPR22", vex->guest_GPR22);
239 (*f)(tid, "GPR23", vex->guest_GPR23);
240 (*f)(tid, "GPR24", vex->guest_GPR24);
241 (*f)(tid, "GPR25", vex->guest_GPR25);
242 (*f)(tid, "GPR26", vex->guest_GPR26);
243 (*f)(tid, "GPR27", vex->guest_GPR27);
244 (*f)(tid, "GPR28", vex->guest_GPR28);
245 (*f)(tid, "GPR29", vex->guest_GPR29);
246 (*f)(tid, "GPR30", vex->guest_GPR30);
247 (*f)(tid, "GPR31", vex->guest_GPR31);
248 (*f)(tid, "CTR" , vex->guest_CTR );
249 (*f)(tid, "LR" , vex->guest_LR );
sewardj59570ff2010-01-01 11:59:33 +0000250#elif defined(VGA_arm)
philippea22f59d2012-01-26 23:13:52 +0000251 (*f)(tid, "R0" , vex->guest_R0 );
252 (*f)(tid, "R1" , vex->guest_R1 );
253 (*f)(tid, "R2" , vex->guest_R2 );
254 (*f)(tid, "R3" , vex->guest_R3 );
255 (*f)(tid, "R4" , vex->guest_R4 );
256 (*f)(tid, "R5" , vex->guest_R5 );
257 (*f)(tid, "R6" , vex->guest_R6 );
258 (*f)(tid, "R8" , vex->guest_R8 );
259 (*f)(tid, "R9" , vex->guest_R9 );
260 (*f)(tid, "R10", vex->guest_R10);
261 (*f)(tid, "R11", vex->guest_R11);
262 (*f)(tid, "R12", vex->guest_R12);
263 (*f)(tid, "R13", vex->guest_R13);
264 (*f)(tid, "R14", vex->guest_R14);
sewardjb5b87402011-03-07 16:05:35 +0000265#elif defined(VGA_s390x)
philippea22f59d2012-01-26 23:13:52 +0000266 (*f)(tid, "r0" , vex->guest_r0 );
267 (*f)(tid, "r1" , vex->guest_r1 );
268 (*f)(tid, "r2" , vex->guest_r2 );
269 (*f)(tid, "r3" , vex->guest_r3 );
270 (*f)(tid, "r4" , vex->guest_r4 );
271 (*f)(tid, "r5" , vex->guest_r5 );
272 (*f)(tid, "r6" , vex->guest_r6 );
273 (*f)(tid, "r7" , vex->guest_r7 );
274 (*f)(tid, "r8" , vex->guest_r8 );
275 (*f)(tid, "r9" , vex->guest_r9 );
276 (*f)(tid, "r10", vex->guest_r10);
277 (*f)(tid, "r11", vex->guest_r11);
278 (*f)(tid, "r12", vex->guest_r12);
279 (*f)(tid, "r13", vex->guest_r13);
280 (*f)(tid, "r14", vex->guest_r14);
281 (*f)(tid, "r15", vex->guest_r15);
petarj4df0bfc2013-02-27 23:17:33 +0000282#elif defined(VGA_mips32) || defined(VGA_mips64)
sewardj5db15402012-06-07 09:13:21 +0000283 (*f)(tid, "r0" , vex->guest_r0 );
284 (*f)(tid, "r1" , vex->guest_r1 );
285 (*f)(tid, "r2" , vex->guest_r2 );
286 (*f)(tid, "r3" , vex->guest_r3 );
287 (*f)(tid, "r4" , vex->guest_r4 );
288 (*f)(tid, "r5" , vex->guest_r5 );
289 (*f)(tid, "r6" , vex->guest_r6 );
290 (*f)(tid, "r7" , vex->guest_r7 );
291 (*f)(tid, "r8" , vex->guest_r8 );
292 (*f)(tid, "r9" , vex->guest_r9 );
293 (*f)(tid, "r10", vex->guest_r10);
294 (*f)(tid, "r11", vex->guest_r11);
295 (*f)(tid, "r12", vex->guest_r12);
296 (*f)(tid, "r13", vex->guest_r13);
297 (*f)(tid, "r14", vex->guest_r14);
298 (*f)(tid, "r15", vex->guest_r15);
299 (*f)(tid, "r16", vex->guest_r16);
300 (*f)(tid, "r17", vex->guest_r17);
301 (*f)(tid, "r18", vex->guest_r18);
302 (*f)(tid, "r19", vex->guest_r19);
303 (*f)(tid, "r20", vex->guest_r20);
304 (*f)(tid, "r21", vex->guest_r21);
305 (*f)(tid, "r22", vex->guest_r22);
306 (*f)(tid, "r23", vex->guest_r23);
307 (*f)(tid, "r24", vex->guest_r24);
308 (*f)(tid, "r25", vex->guest_r25);
309 (*f)(tid, "r26", vex->guest_r26);
310 (*f)(tid, "r27", vex->guest_r27);
311 (*f)(tid, "r28", vex->guest_r28);
312 (*f)(tid, "r29", vex->guest_r29);
313 (*f)(tid, "r30", vex->guest_r30);
314 (*f)(tid, "r31", vex->guest_r31);
sewardjf0c12502014-01-12 12:54:00 +0000315#elif defined(VGA_arm64)
philippeb8afd6f2014-02-12 20:50:03 +0000316 (*f)(tid, "x0" , vex->guest_X0 );
317 (*f)(tid, "x1" , vex->guest_X1 );
318 (*f)(tid, "x2" , vex->guest_X2 );
319 (*f)(tid, "x3" , vex->guest_X3 );
320 (*f)(tid, "x4" , vex->guest_X4 );
321 (*f)(tid, "x5" , vex->guest_X5 );
322 (*f)(tid, "x6" , vex->guest_X6 );
323 (*f)(tid, "x7" , vex->guest_X7 );
324 (*f)(tid, "x8" , vex->guest_X8 );
325 (*f)(tid, "x9" , vex->guest_X9 );
326 (*f)(tid, "x10", vex->guest_X10);
327 (*f)(tid, "x11", vex->guest_X11);
328 (*f)(tid, "x12", vex->guest_X12);
329 (*f)(tid, "x13", vex->guest_X13);
330 (*f)(tid, "x14", vex->guest_X14);
331 (*f)(tid, "x15", vex->guest_X15);
332 (*f)(tid, "x16", vex->guest_X16);
333 (*f)(tid, "x17", vex->guest_X17);
334 (*f)(tid, "x18", vex->guest_X18);
335 (*f)(tid, "x19", vex->guest_X19);
336 (*f)(tid, "x20", vex->guest_X20);
337 (*f)(tid, "x21", vex->guest_X21);
338 (*f)(tid, "x22", vex->guest_X22);
339 (*f)(tid, "x23", vex->guest_X23);
340 (*f)(tid, "x24", vex->guest_X24);
341 (*f)(tid, "x25", vex->guest_X25);
342 (*f)(tid, "x26", vex->guest_X26);
343 (*f)(tid, "x27", vex->guest_X27);
344 (*f)(tid, "x28", vex->guest_X28);
345 (*f)(tid, "x29", vex->guest_X29);
346 (*f)(tid, "x30", vex->guest_X30);
njn6ace3ea2005-06-17 03:06:27 +0000347#else
348# error Unknown arch
349#endif
350}
351
352
florian6bd9dc12012-11-23 16:17:43 +0000353void VG_(apply_to_GP_regs)(void (*f)(ThreadId, const HChar*, UWord))
njn6ace3ea2005-06-17 03:06:27 +0000354{
355 ThreadId tid;
356
357 for (tid = 1; tid < VG_N_THREADS; tid++) {
philippeb8ba0312013-10-21 19:57:08 +0000358 if (VG_(is_valid_tid)(tid)
359 || VG_(threads)[tid].exitreason == VgSrc_ExitProcess) {
360 // live thread or thread instructed to die by another thread that
361 // called exit.
philippea22f59d2012-01-26 23:13:52 +0000362 apply_to_GPs_of_tid(tid, f);
njn6ace3ea2005-06-17 03:06:27 +0000363 }
364 }
365}
366
sewardjb8b79ad2008-03-03 01:35:41 +0000367void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
njnb506bd82005-06-21 04:01:51 +0000368{
sewardjb8b79ad2008-03-03 01:35:41 +0000369 *tid = (ThreadId)(-1);
njnb506bd82005-06-21 04:01:51 +0000370}
njn6ace3ea2005-06-17 03:06:27 +0000371
sewardjb8b79ad2008-03-03 01:35:41 +0000372Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
373 /*OUT*/Addr* stack_min,
374 /*OUT*/Addr* stack_max)
njn1d0cb0d2005-08-15 01:52:02 +0000375{
376 ThreadId i;
sewardjb8b79ad2008-03-03 01:35:41 +0000377 for (i = (*tid)+1; i < VG_N_THREADS; i++) {
378 if (i == VG_INVALID_THREADID)
379 continue;
njn1d0cb0d2005-08-15 01:52:02 +0000380 if (VG_(threads)[i].status != VgTs_Empty) {
381 *tid = i;
382 *stack_min = VG_(get_SP)(i);
philippe38a74d22014-08-29 22:53:19 +0000383 *stack_max = VG_(threads)[i].client_stack_highest_byte;
njn1d0cb0d2005-08-15 01:52:02 +0000384 return True;
385 }
386 }
387 return False;
388}
sewardj7821e2e2005-08-08 00:35:46 +0000389
sewardjbbec7722007-11-25 14:08:53 +0000390Addr VG_(thread_get_stack_max)(ThreadId tid)
391{
392 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
393 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
philippe38a74d22014-08-29 22:53:19 +0000394 return VG_(threads)[tid].client_stack_highest_byte;
sewardjbbec7722007-11-25 14:08:53 +0000395}
396
bart0fb03202008-03-29 09:25:53 +0000397SizeT VG_(thread_get_stack_size)(ThreadId tid)
398{
399 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
400 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
401 return VG_(threads)[tid].client_stack_szB;
402}
403
bart83c5a922010-09-02 14:38:38 +0000404Addr VG_(thread_get_altstack_min)(ThreadId tid)
405{
406 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
407 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
408 return (Addr)VG_(threads)[tid].altstack.ss_sp;
409}
410
411SizeT VG_(thread_get_altstack_size)(ThreadId tid)
412{
413 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
414 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
415 return VG_(threads)[tid].altstack.ss_size;
416}
417
sewardje2d1e672005-11-12 23:10:48 +0000418//-------------------------------------------------------------
419/* Details about the capabilities of the underlying (host) CPU. These
420 details are acquired by (1) enquiring with the CPU at startup, or
421 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
422 line size). It's a bit nasty in the sense that there's no obvious
423 way to stop uses of some of this info before it's ready to go.
florian0daa4e32012-04-22 02:48:20 +0000424 See pub_core_machine.h for more information about that.
sewardjb5b87402011-03-07 16:05:35 +0000425
sewardje2d1e672005-11-12 23:10:48 +0000426 VG_(machine_get_hwcaps) may use signals (although it attempts to
427 leave signal state unchanged) and therefore should only be
428 called before m_main sets up the client's signal state.
429*/
430
431/* --------- State --------- */
sewardj59570ff2010-01-01 11:59:33 +0000432static Bool hwcaps_done = False;
sewardje2d1e672005-11-12 23:10:48 +0000433
434/* --- all archs --- */
sewardj98763d52012-06-03 22:40:07 +0000435static VexArch va = VexArch_INVALID;
sewardje2d1e672005-11-12 23:10:48 +0000436static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000437
sewardj7821e2e2005-08-08 00:35:46 +0000438#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000439UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000440#endif
sewardje2d1e672005-11-12 23:10:48 +0000441#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000442UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000443UInt VG_(machine_ppc32_has_VMX) = 0;
444#endif
carllcae0cc22014-08-07 23:17:29 +0000445#if defined(VGA_ppc64be) || defined(VGA_ppc64le)
sewardj2c48c7b2005-11-29 13:05:56 +0000446ULong VG_(machine_ppc64_has_VMX) = 0;
447#endif
sewardj1dbd3372010-08-22 12:21:14 +0000448#if defined(VGA_arm)
449Int VG_(machine_arm_archlevel) = 4;
450#endif
sewardje2d1e672005-11-12 23:10:48 +0000451
452
sewardj2c3f2ea2011-04-13 15:40:10 +0000453/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
sewardj6c591e12011-04-11 16:17:51 +0000454 testing, so we need a VG_MINIMAL_JMP_BUF. */
carllcae0cc22014-08-07 23:17:29 +0000455#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
dejanj5f790e82013-07-25 08:22:08 +0000456 || defined(VGA_arm) || defined(VGA_s390x) || defined(VGA_mips32)
florianc91f5842013-09-15 10:42:26 +0000457#include "pub_core_libcsetjmp.h"
sewardj97d3ebb2011-04-11 18:36:34 +0000458static VG_MINIMAL_JMP_BUF(env_unsup_insn);
sewardj6c591e12011-04-11 16:17:51 +0000459static void handler_unsup_insn ( Int x ) {
460 VG_MINIMAL_LONGJMP(env_unsup_insn);
461}
sewardj5ae70ce2010-09-08 15:12:33 +0000462#endif
463
sewardjb9c815b2010-09-03 15:51:34 +0000464
465/* Helper function for VG_(machine_get_hwcaps), assumes the SIGILL/etc
466 * handlers are installed. Determines the the sizes affected by dcbz
467 * and dcbzl instructions and updates the given VexArchInfo structure
468 * accordingly.
469 *
470 * Not very defensive: assumes that as long as the dcbz/dcbzl
471 * instructions don't raise a SIGILL, that they will zero an aligned,
472 * contiguous block of memory of a sensible size. */
carllcae0cc22014-08-07 23:17:29 +0000473#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
sewardjb9c815b2010-09-03 15:51:34 +0000474static void find_ppc_dcbz_sz(VexArchInfo *arch_info)
475{
sewardjdcb3a592010-09-04 00:43:14 +0000476 Int dcbz_szB = 0;
sewardjb9c815b2010-09-03 15:51:34 +0000477 Int dcbzl_szB;
sewardj5ae70ce2010-09-08 15:12:33 +0000478# define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
sewardjb9c815b2010-09-03 15:51:34 +0000479 char test_block[4*MAX_DCBZL_SZB];
480 char *aligned = test_block;
481 Int i;
482
483 /* round up to next max block size, assumes MAX_DCBZL_SZB is pof2 */
484 aligned = (char *)(((HWord)aligned + MAX_DCBZL_SZB) & ~(MAX_DCBZL_SZB - 1));
485 vg_assert((aligned + MAX_DCBZL_SZB) <= &test_block[sizeof(test_block)]);
486
487 /* dcbz often clears 32B, although sometimes whatever the native cache
488 * block size is */
489 VG_(memset)(test_block, 0xff, sizeof(test_block));
490 __asm__ __volatile__("dcbz 0,%0"
491 : /*out*/
492 : "r" (aligned) /*in*/
493 : "memory" /*clobber*/);
494 for (dcbz_szB = 0, i = 0; i < sizeof(test_block); ++i) {
495 if (!test_block[i])
496 ++dcbz_szB;
497 }
sewardj643d5012013-10-14 11:41:46 +0000498 vg_assert(dcbz_szB == 16 || dcbz_szB == 32 || dcbz_szB == 64 || dcbz_szB == 128);
sewardjb9c815b2010-09-03 15:51:34 +0000499
500 /* dcbzl clears 128B on G5/PPC970, and usually 32B on other platforms */
sewardj6c591e12011-04-11 16:17:51 +0000501 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb9c815b2010-09-03 15:51:34 +0000502 dcbzl_szB = 0; /* indicates unsupported */
503 }
504 else {
505 VG_(memset)(test_block, 0xff, sizeof(test_block));
506 /* some older assemblers won't understand the dcbzl instruction
507 * variant, so we directly emit the instruction ourselves */
508 __asm__ __volatile__("mr 9, %0 ; .long 0x7C204FEC" /*dcbzl 0,9*/
509 : /*out*/
510 : "r" (aligned) /*in*/
511 : "memory", "r9" /*clobber*/);
512 for (dcbzl_szB = 0, i = 0; i < sizeof(test_block); ++i) {
513 if (!test_block[i])
514 ++dcbzl_szB;
515 }
sewardj643d5012013-10-14 11:41:46 +0000516 vg_assert(dcbzl_szB == 16 || dcbzl_szB == 32 || dcbzl_szB == 64 || dcbzl_szB == 128);
sewardjb9c815b2010-09-03 15:51:34 +0000517 }
518
519 arch_info->ppc_dcbz_szB = dcbz_szB;
520 arch_info->ppc_dcbzl_szB = dcbzl_szB;
521
522 VG_(debugLog)(1, "machine", "dcbz_szB=%d dcbzl_szB=%d\n",
523 dcbz_szB, dcbzl_szB);
sewardj5ae70ce2010-09-08 15:12:33 +0000524# undef MAX_DCBZL_SZB
sewardjb9c815b2010-09-03 15:51:34 +0000525}
carllcae0cc22014-08-07 23:17:29 +0000526#endif /* defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) */
sewardj5ae70ce2010-09-08 15:12:33 +0000527
sewardj2c3f2ea2011-04-13 15:40:10 +0000528#ifdef VGA_s390x
sewardj5ae70ce2010-09-08 15:12:33 +0000529
sewardj2c3f2ea2011-04-13 15:40:10 +0000530/* Read /proc/cpuinfo. Look for lines like these
531
532 processor 0: version = FF, identification = 0117C9, machine = 2064
533
florian4e63b8e2012-04-22 03:50:20 +0000534 and return the machine model. If the machine model could not be determined
535 or it is an unknown model, return VEX_S390X_MODEL_UNKNOWN. */
sewardj2c3f2ea2011-04-13 15:40:10 +0000536
537static UInt VG_(get_machine_model)(void)
538{
539 static struct model_map {
540 HChar name[5];
541 UInt id;
542 } model_map[] = {
543 { "2064", VEX_S390X_MODEL_Z900 },
544 { "2066", VEX_S390X_MODEL_Z800 },
545 { "2084", VEX_S390X_MODEL_Z990 },
546 { "2086", VEX_S390X_MODEL_Z890 },
547 { "2094", VEX_S390X_MODEL_Z9_EC },
548 { "2096", VEX_S390X_MODEL_Z9_BC },
549 { "2097", VEX_S390X_MODEL_Z10_EC },
550 { "2098", VEX_S390X_MODEL_Z10_BC },
551 { "2817", VEX_S390X_MODEL_Z196 },
florian258ede72011-09-02 22:20:41 +0000552 { "2818", VEX_S390X_MODEL_Z114 },
florian87a25cf2012-08-28 13:33:10 +0000553 { "2827", VEX_S390X_MODEL_ZEC12 },
florian3b411c12013-07-28 15:29:36 +0000554 { "2828", VEX_S390X_MODEL_ZBC12 },
sewardj2c3f2ea2011-04-13 15:40:10 +0000555 };
556
557 Int model, n, fh;
558 SysRes fd;
559 SizeT num_bytes, file_buf_size;
560 HChar *p, *m, *model_name, *file_buf;
561
562 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
563 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
florian4e63b8e2012-04-22 03:50:20 +0000564 if ( sr_isError(fd) ) return VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000565
566 fh = sr_Res(fd);
567
568 /* Determine the size of /proc/cpuinfo.
569 Work around broken-ness in /proc file system implementation.
570 fstat returns a zero size for /proc/cpuinfo although it is
571 claimed to be a regular file. */
572 num_bytes = 0;
573 file_buf_size = 1000;
574 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
575 while (42) {
576 n = VG_(read)(fh, file_buf, file_buf_size);
577 if (n < 0) break;
578
579 num_bytes += n;
580 if (n < file_buf_size) break; /* reached EOF */
581 }
582
583 if (n < 0) num_bytes = 0; /* read error; ignore contents */
584
585 if (num_bytes > file_buf_size) {
586 VG_(free)( file_buf );
587 VG_(lseek)( fh, 0, VKI_SEEK_SET );
588 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
589 n = VG_(read)( fh, file_buf, num_bytes );
590 if (n < 0) num_bytes = 0;
591 }
592
593 file_buf[num_bytes] = '\0';
594 VG_(close)(fh);
595
596 /* Parse file */
florian4e63b8e2012-04-22 03:50:20 +0000597 model = VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000598 for (p = file_buf; *p; ++p) {
599 /* Beginning of line */
600 if (VG_(strncmp)( p, "processor", sizeof "processor" - 1 ) != 0) continue;
601
602 m = VG_(strstr)( p, "machine" );
603 if (m == NULL) continue;
604
605 p = m + sizeof "machine" - 1;
606 while ( VG_(isspace)( *p ) || *p == '=') {
607 if (*p == '\n') goto next_line;
608 ++p;
609 }
610
611 model_name = p;
612 for (n = 0; n < sizeof model_map / sizeof model_map[0]; ++n) {
613 struct model_map *mm = model_map + n;
614 SizeT len = VG_(strlen)( mm->name );
615 if ( VG_(strncmp)( mm->name, model_name, len ) == 0 &&
616 VG_(isspace)( model_name[len] )) {
617 if (mm->id < model) model = mm->id;
618 p = model_name + len;
619 break;
620 }
621 }
622 /* Skip until end-of-line */
623 while (*p != '\n')
624 ++p;
625 next_line: ;
626 }
627
628 VG_(free)( file_buf );
florian00164922011-10-25 21:37:15 +0000629 VG_(debugLog)(1, "machine", "model = %s\n",
florian4e63b8e2012-04-22 03:50:20 +0000630 model == VEX_S390X_MODEL_UNKNOWN ? "UNKNOWN"
florian00164922011-10-25 21:37:15 +0000631 : model_map[model].name);
sewardj2c3f2ea2011-04-13 15:40:10 +0000632 return model;
633}
634
635#endif /* VGA_s390x */
sewardj5ae70ce2010-09-08 15:12:33 +0000636
petarj4df0bfc2013-02-27 23:17:33 +0000637#if defined(VGA_mips32) || defined(VGA_mips64)
sewardj5db15402012-06-07 09:13:21 +0000638
639/* Read /proc/cpuinfo and return the machine model. */
640static UInt VG_(get_machine_model)(void)
641{
petarj4df0bfc2013-02-27 23:17:33 +0000642 const char *search_MIPS_str = "MIPS";
643 const char *search_Broadcom_str = "Broadcom";
644 const char *search_Netlogic_str = "Netlogic";
petarj96ee38d2013-09-16 18:16:13 +0000645 const char *search_Cavium_str= "Cavium";
sewardj5db15402012-06-07 09:13:21 +0000646 Int n, fh;
647 SysRes fd;
648 SizeT num_bytes, file_buf_size;
649 HChar *file_buf;
650
651 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
652 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
653 if ( sr_isError(fd) ) return -1;
654
655 fh = sr_Res(fd);
656
657 /* Determine the size of /proc/cpuinfo.
658 Work around broken-ness in /proc file system implementation.
659 fstat returns a zero size for /proc/cpuinfo although it is
660 claimed to be a regular file. */
661 num_bytes = 0;
662 file_buf_size = 1000;
663 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
664 while (42) {
665 n = VG_(read)(fh, file_buf, file_buf_size);
666 if (n < 0) break;
667
668 num_bytes += n;
669 if (n < file_buf_size) break; /* reached EOF */
670 }
671
672 if (n < 0) num_bytes = 0; /* read error; ignore contents */
673
674 if (num_bytes > file_buf_size) {
675 VG_(free)( file_buf );
676 VG_(lseek)( fh, 0, VKI_SEEK_SET );
677 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
678 n = VG_(read)( fh, file_buf, num_bytes );
679 if (n < 0) num_bytes = 0;
680 }
681
682 file_buf[num_bytes] = '\0';
683 VG_(close)(fh);
684
685 /* Parse file */
686 if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL)
687 return VEX_PRID_COMP_BROADCOM;
petarj4df0bfc2013-02-27 23:17:33 +0000688 if (VG_(strstr) (file_buf, search_Netlogic_str) != NULL)
689 return VEX_PRID_COMP_NETLOGIC;
petarj96ee38d2013-09-16 18:16:13 +0000690 if (VG_(strstr)(file_buf, search_Cavium_str) != NULL)
691 return VEX_PRID_COMP_CAVIUM;
sewardj5db15402012-06-07 09:13:21 +0000692 if (VG_(strstr) (file_buf, search_MIPS_str) != NULL)
693 return VEX_PRID_COMP_MIPS;
694
695 /* Did not find string in the proc file. */
696 return -1;
697}
698
699#endif
700
sewardj5ae70ce2010-09-08 15:12:33 +0000701/* Determine what insn set and insn set variant the host has, and
702 record it. To be called once at system startup. Returns False if
florian78627012012-10-07 19:47:04 +0000703 this a CPU incapable of running Valgrind.
704 Also determine information about the caches on this host. */
sewardje3826cf2005-11-13 00:30:22 +0000705
sewardje2d1e672005-11-12 23:10:48 +0000706Bool VG_(machine_get_hwcaps)( void )
707{
708 vg_assert(hwcaps_done == False);
709 hwcaps_done = True;
710
711 // Whack default settings into vai, so that we only need to fill in
712 // any interesting bits.
713 LibVEX_default_VexArchInfo(&vai);
714
715#if defined(VGA_x86)
mjw7c6a0002013-08-27 10:23:23 +0000716 { Bool have_sse1, have_sse2, have_cx8, have_lzcnt, have_mmxext;
sewardjc7ffc942011-03-28 16:26:42 +0000717 UInt eax, ebx, ecx, edx, max_extended;
sewardj66826ec2012-11-19 14:55:15 +0000718 HChar vstr[13];
sewardj40d91c72010-07-29 15:40:32 +0000719 vstr[0] = 0;
sewardje2d1e672005-11-12 23:10:48 +0000720
721 if (!VG_(has_cpuid)())
722 /* we can't do cpuid at all. Give up. */
723 return False;
724
tomad8a5912011-06-10 15:04:22 +0000725 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000726 if (eax < 1)
727 /* we can't ask for cpuid(x) for x > 0. Give up. */
728 return False;
729
sewardj40d91c72010-07-29 15:40:32 +0000730 /* Get processor ID string, and max basic/extended index
731 values. */
sewardj40d91c72010-07-29 15:40:32 +0000732 VG_(memcpy)(&vstr[0], &ebx, 4);
733 VG_(memcpy)(&vstr[4], &edx, 4);
734 VG_(memcpy)(&vstr[8], &ecx, 4);
735 vstr[12] = 0;
736
tomad8a5912011-06-10 15:04:22 +0000737 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000738 max_extended = eax;
739
sewardje2d1e672005-11-12 23:10:48 +0000740 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000741 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000742
743 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
744 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
745
sewardj1c0ce7a2009-07-01 08:10:49 +0000746 /* cmpxchg8b is a minimum requirement now; if we don't have it we
747 must simply give up. But all CPUs since Pentium-I have it, so
748 that doesn't seem like much of a restriction. */
749 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
750 if (!have_cx8)
751 return False;
752
sewardj37dd8f62014-05-13 14:10:44 +0000753 /* Figure out if this is an AMD that can do MMXEXT. */
mjw7c6a0002013-08-27 10:23:23 +0000754 have_mmxext = False;
sewardj40d91c72010-07-29 15:40:32 +0000755 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
756 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000757 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
mjw7c6a0002013-08-27 10:23:23 +0000758 /* Some older AMD processors support a sse1 subset (Integer SSE). */
759 have_mmxext = !have_sse1 && ((edx & (1<<22)) != 0);
sewardj40d91c72010-07-29 15:40:32 +0000760 }
761
sewardj37dd8f62014-05-13 14:10:44 +0000762 /* Figure out if this is an AMD or Intel that can do LZCNT. */
763 have_lzcnt = False;
764 if ((0 == VG_(strcmp)(vstr, "AuthenticAMD")
765 || 0 == VG_(strcmp)(vstr, "GenuineIntel"))
766 && max_extended >= 0x80000001) {
767 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
768 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
769 }
770
mjw7c6a0002013-08-27 10:23:23 +0000771 /* Intel processors don't define the mmxext extension, but since it
772 is just a sse1 subset always define it when we have sse1. */
773 if (have_sse1)
774 have_mmxext = True;
775
florian78627012012-10-07 19:47:04 +0000776 va = VexArchX86;
sewardj59731422014-07-24 12:45:24 +0000777 vai.endness = VexEndnessLE;
mjw7c6a0002013-08-27 10:23:23 +0000778 if (have_sse2 && have_sse1 && have_mmxext) {
779 vai.hwcaps = VEX_HWCAPS_X86_MMXEXT;
780 vai.hwcaps |= VEX_HWCAPS_X86_SSE1;
sewardje3121f32006-01-27 21:23:23 +0000781 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardj40d91c72010-07-29 15:40:32 +0000782 if (have_lzcnt)
783 vai.hwcaps |= VEX_HWCAPS_X86_LZCNT;
sewardje2d1e672005-11-12 23:10:48 +0000784 VG_(machine_x86_have_mxcsr) = 1;
mjw7c6a0002013-08-27 10:23:23 +0000785 } else if (have_sse1 && have_mmxext) {
786 vai.hwcaps = VEX_HWCAPS_X86_MMXEXT;
787 vai.hwcaps |= VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000788 VG_(machine_x86_have_mxcsr) = 1;
mjw7c6a0002013-08-27 10:23:23 +0000789 } else if (have_mmxext) {
790 vai.hwcaps = VEX_HWCAPS_X86_MMXEXT; /*integer only sse1 subset*/
791 VG_(machine_x86_have_mxcsr) = 0;
florian78627012012-10-07 19:47:04 +0000792 } else {
793 vai.hwcaps = 0; /*baseline - no sse at all*/
794 VG_(machine_x86_have_mxcsr) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000795 }
796
florian78627012012-10-07 19:47:04 +0000797 VG_(machine_get_cache_info)(&vai);
798
sewardje2d1e672005-11-12 23:10:48 +0000799 return True;
800 }
801
802#elif defined(VGA_amd64)
sewardjc7ffc942011-03-28 16:26:42 +0000803 { Bool have_sse3, have_cx8, have_cx16;
sewardjfda50af2013-03-27 11:43:20 +0000804 Bool have_lzcnt, have_avx, have_bmi, have_avx2;
sewardje653b032013-03-26 13:57:48 +0000805 Bool have_rdtscp;
sewardjfda50af2013-03-27 11:43:20 +0000806 UInt eax, ebx, ecx, edx, max_basic, max_extended;
florian19f91bb2012-11-10 22:29:54 +0000807 HChar vstr[13];
sewardj40d91c72010-07-29 15:40:32 +0000808 vstr[0] = 0;
sewardj1c0ce7a2009-07-01 08:10:49 +0000809
810 if (!VG_(has_cpuid)())
811 /* we can't do cpuid at all. Give up. */
812 return False;
813
tomad8a5912011-06-10 15:04:22 +0000814 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardjfda50af2013-03-27 11:43:20 +0000815 max_basic = eax;
816 if (max_basic < 1)
sewardj1c0ce7a2009-07-01 08:10:49 +0000817 /* we can't ask for cpuid(x) for x > 0. Give up. */
818 return False;
819
sewardj40d91c72010-07-29 15:40:32 +0000820 /* Get processor ID string, and max basic/extended index
821 values. */
sewardj40d91c72010-07-29 15:40:32 +0000822 VG_(memcpy)(&vstr[0], &ebx, 4);
823 VG_(memcpy)(&vstr[4], &edx, 4);
824 VG_(memcpy)(&vstr[8], &ecx, 4);
825 vstr[12] = 0;
826
tomad8a5912011-06-10 15:04:22 +0000827 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000828 max_extended = eax;
829
sewardj1c0ce7a2009-07-01 08:10:49 +0000830 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000831 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000832
sewardjc7ffc942011-03-28 16:26:42 +0000833 // we assume that SSE1 and SSE2 are available by default
sewardj598971e2009-07-12 13:19:04 +0000834 have_sse3 = (ecx & (1<<0)) != 0; /* True => have sse3 insns */
sewardjee1a8972012-04-26 14:17:50 +0000835 // ssse3 is ecx:9
836 // sse41 is ecx:19
837 // sse42 is ecx:20
838
839 // osxsave is ecx:27
840 // avx is ecx:28
841 // fma is ecx:12
842 have_avx = False;
843 /* have_fma = False; */
844 if ( (ecx & ((1<<27)|(1<<28))) == ((1<<27)|(1<<28)) ) {
845 /* processor supports AVX instructions and XGETBV is enabled
846 by OS */
847 ULong w;
848 __asm__ __volatile__("movq $0,%%rcx ; "
849 ".byte 0x0F,0x01,0xD0 ; " /* xgetbv */
850 "movq %%rax,%0"
851 :/*OUT*/"=r"(w) :/*IN*/
852 :/*TRASH*/"rdx","rcx");
853 if ((w & 6) == 6) {
854 /* OS has enabled both XMM and YMM state support */
855 have_avx = True;
856 /* have_fma = (ecx & (1<<12)) != 0; */
857 /* have_fma: Probably correct, but gcc complains due to
858 unusedness. &*/
859 }
860 }
861
sewardj1c0ce7a2009-07-01 08:10:49 +0000862 /* cmpxchg8b is a minimum requirement now; if we don't have it we
863 must simply give up. But all CPUs since Pentium-I have it, so
864 that doesn't seem like much of a restriction. */
865 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
866 if (!have_cx8)
867 return False;
868
869 /* on amd64 we tolerate older cpus, which don't have cmpxchg16b */
870 have_cx16 = (ecx & (1<<13)) != 0; /* True => have cmpxchg16b */
871
sewardjfda50af2013-03-27 11:43:20 +0000872 /* Figure out if this CPU can do LZCNT. */
sewardj40d91c72010-07-29 15:40:32 +0000873 have_lzcnt = False;
sewardjfda50af2013-03-27 11:43:20 +0000874 if (max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000875 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000876 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
877 }
sewardjfda50af2013-03-27 11:43:20 +0000878
sewardje653b032013-03-26 13:57:48 +0000879 /* Can we do RDTSCP? */
880 have_rdtscp = False;
881 if (max_extended >= 0x80000001) {
882 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
883 have_rdtscp = (edx & (1<<27)) != 0; /* True => have RDTSVCP */
884 }
sewardj40d91c72010-07-29 15:40:32 +0000885
mjw787e8dc2013-10-18 13:11:05 +0000886 /* Check for BMI1 and AVX2. If we have AVX1 (plus OS support). */
sewardjfda50af2013-03-27 11:43:20 +0000887 have_bmi = False;
888 have_avx2 = False;
mjw787e8dc2013-10-18 13:11:05 +0000889 if (have_avx && max_basic >= 7) {
sewardjfda50af2013-03-27 11:43:20 +0000890 VG_(cpuid)(7, 0, &eax, &ebx, &ecx, &edx);
891 have_bmi = (ebx & (1<<3)) != 0; /* True => have BMI1 */
mjw787e8dc2013-10-18 13:11:05 +0000892 have_avx2 = (ebx & (1<<5)) != 0; /* True => have AVX2 */
sewardjfda50af2013-03-27 11:43:20 +0000893 }
894
sewardj59731422014-07-24 12:45:24 +0000895 va = VexArchAMD64;
896 vai.endness = VexEndnessLE;
897 vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
898 | (have_cx16 ? VEX_HWCAPS_AMD64_CX16 : 0)
899 | (have_lzcnt ? VEX_HWCAPS_AMD64_LZCNT : 0)
900 | (have_avx ? VEX_HWCAPS_AMD64_AVX : 0)
901 | (have_bmi ? VEX_HWCAPS_AMD64_BMI : 0)
902 | (have_avx2 ? VEX_HWCAPS_AMD64_AVX2 : 0)
903 | (have_rdtscp ? VEX_HWCAPS_AMD64_RDTSCP : 0);
florian78627012012-10-07 19:47:04 +0000904
905 VG_(machine_get_cache_info)(&vai);
906
sewardj1c0ce7a2009-07-01 08:10:49 +0000907 return True;
908 }
sewardje2d1e672005-11-12 23:10:48 +0000909
910#elif defined(VGA_ppc32)
bart1581e742009-01-13 07:49:14 +0000911 {
912 /* Find out which subset of the ppc32 instruction set is supported by
913 verifying whether various ppc32 instructions generate a SIGILL
914 or a SIGFPE. An alternative approach is to check the AT_HWCAP and
915 AT_PLATFORM entries in the ELF auxiliary table -- see also
916 the_iifii.client_auxv in m_main.c.
917 */
njncda2f0f2009-05-18 02:12:08 +0000918 vki_sigset_t saved_set, tmp_set;
919 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
920 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000921
sewardj5ba075a2012-04-02 21:25:14 +0000922 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
carlldfbf2942013-08-12 18:04:22 +0000923 volatile Bool have_isa_2_07;
sewardj7637e9e2006-02-21 17:11:11 +0000924 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000925
njncda2f0f2009-05-18 02:12:08 +0000926 /* This is a kludge. Really we ought to back-convert saved_act
927 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
928 since that's a no-op on all ppc32 platforms so far supported,
929 it's not worth the typing effort. At least include most basic
930 sanity check: */
931 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
932
sewardje3826cf2005-11-13 00:30:22 +0000933 VG_(sigemptyset)(&tmp_set);
934 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000935 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardje3826cf2005-11-13 00:30:22 +0000936
sewardj7637e9e2006-02-21 17:11:11 +0000937 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
938 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000939
bart1581e742009-01-13 07:49:14 +0000940 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
sewardj7637e9e2006-02-21 17:11:11 +0000941 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000942 tmp_sigill_act = saved_sigill_act;
943
944 r = VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
945 vg_assert(r == 0);
946 tmp_sigfpe_act = saved_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000947
sewardj7637e9e2006-02-21 17:11:11 +0000948 /* NODEFER: signal handler does not return (from the kernel's point of
949 view), hence if it is to successfully catch a signal more than once,
950 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000951 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
952 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
953 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
954 tmp_sigill_act.ksa_handler = handler_unsup_insn;
955 r = VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
956 vg_assert(r == 0);
957
958 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
959 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
960 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
961 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
962 r = VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
963 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000964
sewardje3121f32006-01-27 21:23:23 +0000965 /* standard FP insns */
966 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000967 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000968 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000969 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000970 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000971 }
972
sewardje3121f32006-01-27 21:23:23 +0000973 /* Altivec insns */
974 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000975 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000976 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000977 } else {
sewardj71592122006-04-04 03:29:48 +0000978 /* Unfortunately some older assemblers don't speak Altivec (or
979 choose not to), so to be safe we directly emit the 32-bit
980 word corresponding to "vor 0,0,0". This fixes a build
981 problem that happens on Debian 3.1 (ppc32), and probably
982 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000983 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000984 }
985
sewardje3121f32006-01-27 21:23:23 +0000986 /* General-Purpose optional (fsqrt, fsqrts) */
987 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000988 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000989 have_FX = False;
990 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000991 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000992 }
993
994 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
995 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000996 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000997 have_GX = False;
998 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000999 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +00001000 }
1001
sewardjf34eb492011-04-15 11:57:05 +00001002 /* VSX support implies Power ISA 2.06 */
1003 have_VX = True;
1004 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1005 have_VX = False;
1006 } else {
1007 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
1008 }
1009
sewardj5ba075a2012-04-02 21:25:14 +00001010 /* Check for Decimal Floating Point (DFP) support. */
1011 have_DFP = True;
1012 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1013 have_DFP = False;
1014 } else {
1015 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
1016 }
sewardjf34eb492011-04-15 11:57:05 +00001017
carlldfbf2942013-08-12 18:04:22 +00001018 /* Check for ISA 2.07 support. */
1019 have_isa_2_07 = True;
1020 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1021 have_isa_2_07 = False;
1022 } else {
1023 __asm__ __volatile__(".long 0x7c000166"); /* mtvsrd XT,RA */
1024 }
1025
sewardjb9c815b2010-09-03 15:51:34 +00001026 /* determine dcbz/dcbzl sizes while we still have the signal
1027 * handlers registered */
1028 find_ppc_dcbz_sz(&vai);
1029
bart1581e742009-01-13 07:49:14 +00001030 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1031 vg_assert(r == 0);
1032 r = VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj7637e9e2006-02-21 17:11:11 +00001033 vg_assert(r == 0);
1034 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1035 vg_assert(r == 0);
carlldfbf2942013-08-12 18:04:22 +00001036 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d ISA2.07 %d\n",
sewardjf34eb492011-04-15 11:57:05 +00001037 (Int)have_F, (Int)have_V, (Int)have_FX,
carlldfbf2942013-08-12 18:04:22 +00001038 (Int)have_GX, (Int)have_VX, (Int)have_DFP,
1039 (Int)have_isa_2_07);
sewardje3121f32006-01-27 21:23:23 +00001040 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
1041 if (have_V && !have_F)
1042 have_V = False;
1043 if (have_FX && !have_F)
1044 have_FX = False;
1045 if (have_GX && !have_F)
1046 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +00001047
sewardje3121f32006-01-27 21:23:23 +00001048 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
1049 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +00001050
1051 va = VexArchPPC32;
sewardj59731422014-07-24 12:45:24 +00001052 vai.endness = VexEndnessBE;
sewardje3826cf2005-11-13 00:30:22 +00001053
sewardje3121f32006-01-27 21:23:23 +00001054 vai.hwcaps = 0;
1055 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
1056 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
1057 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
1058 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardjf34eb492011-04-15 11:57:05 +00001059 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC32_VX;
sewardj5ba075a2012-04-02 21:25:14 +00001060 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC32_DFP;
carlldfbf2942013-08-12 18:04:22 +00001061 if (have_isa_2_07) vai.hwcaps |= VEX_HWCAPS_PPC32_ISA2_07;
sewardj5ba075a2012-04-02 21:25:14 +00001062
florian78627012012-10-07 19:47:04 +00001063 VG_(machine_get_cache_info)(&vai);
sewardje3826cf2005-11-13 00:30:22 +00001064
1065 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
1066 called before we're ready to go. */
1067 return True;
1068 }
sewardje2d1e672005-11-12 23:10:48 +00001069
carllcae0cc22014-08-07 23:17:29 +00001070#elif defined(VGA_ppc64be)|| defined(VGA_ppc64le)
bart1581e742009-01-13 07:49:14 +00001071 {
1072 /* Same instruction set detection algorithm as for ppc32. */
njncda2f0f2009-05-18 02:12:08 +00001073 vki_sigset_t saved_set, tmp_set;
1074 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
1075 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardj2c48c7b2005-11-29 13:05:56 +00001076
sewardj5ba075a2012-04-02 21:25:14 +00001077 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
carlldfbf2942013-08-12 18:04:22 +00001078 volatile Bool have_isa_2_07;
njncda2f0f2009-05-18 02:12:08 +00001079 Int r;
1080
1081 /* This is a kludge. Really we ought to back-convert saved_act
1082 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1083 since that's a no-op on all ppc64 platforms so far supported,
1084 it's not worth the typing effort. At least include most basic
1085 sanity check: */
1086 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
sewardj2c48c7b2005-11-29 13:05:56 +00001087
1088 VG_(sigemptyset)(&tmp_set);
1089 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +00001090 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardj2c48c7b2005-11-29 13:05:56 +00001091
njncda2f0f2009-05-18 02:12:08 +00001092 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1093 vg_assert(r == 0);
sewardj2c48c7b2005-11-29 13:05:56 +00001094
njncda2f0f2009-05-18 02:12:08 +00001095 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1096 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +00001097 tmp_sigill_act = saved_sigill_act;
1098
1099 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1100 tmp_sigfpe_act = saved_sigfpe_act;
1101
sewardj7637e9e2006-02-21 17:11:11 +00001102 /* NODEFER: signal handler does not return (from the kernel's point of
1103 view), hence if it is to successfully catch a signal more than once,
1104 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +00001105 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1106 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1107 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1108 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1109 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1110
1111 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1112 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1113 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1114 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1115 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001116
sewardje3121f32006-01-27 21:23:23 +00001117 /* standard FP insns */
1118 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +00001119 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001120 have_F = False;
1121 } else {
1122 __asm__ __volatile__("fmr 0,0");
1123 }
1124
1125 /* Altivec insns */
1126 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +00001127 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001128 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +00001129 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001130 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +00001131 }
1132
sewardje3121f32006-01-27 21:23:23 +00001133 /* General-Purpose optional (fsqrt, fsqrts) */
1134 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +00001135 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001136 have_FX = False;
1137 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001138 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001139 }
1140
1141 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
1142 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +00001143 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001144 have_GX = False;
1145 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001146 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001147 }
1148
sewardjf34eb492011-04-15 11:57:05 +00001149 /* VSX support implies Power ISA 2.06 */
1150 have_VX = True;
1151 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1152 have_VX = False;
1153 } else {
1154 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
1155 }
1156
sewardj5ba075a2012-04-02 21:25:14 +00001157 /* Check for Decimal Floating Point (DFP) support. */
1158 have_DFP = True;
1159 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1160 have_DFP = False;
1161 } else {
1162 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
1163 }
1164
carlldfbf2942013-08-12 18:04:22 +00001165 /* Check for ISA 2.07 support. */
1166 have_isa_2_07 = True;
1167 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1168 have_isa_2_07 = False;
1169 } else {
1170 __asm__ __volatile__(".long 0x7c000166"); /* mtvsrd XT,RA */
1171 }
1172
sewardjb9c815b2010-09-03 15:51:34 +00001173 /* determine dcbz/dcbzl sizes while we still have the signal
1174 * handlers registered */
1175 find_ppc_dcbz_sz(&vai);
1176
bart1581e742009-01-13 07:49:14 +00001177 VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1178 VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001179 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
carlldfbf2942013-08-12 18:04:22 +00001180 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d ISA2.07 %d\n",
sewardjf34eb492011-04-15 11:57:05 +00001181 (Int)have_F, (Int)have_V, (Int)have_FX,
carlldfbf2942013-08-12 18:04:22 +00001182 (Int)have_GX, (Int)have_VX, (Int)have_DFP,
1183 (Int)have_isa_2_07);
carllcae0cc22014-08-07 23:17:29 +00001184 /* on ppc64be, if we don't even have FP, just give up. */
sewardje3121f32006-01-27 21:23:23 +00001185 if (!have_F)
1186 return False;
1187
1188 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +00001189
1190 va = VexArchPPC64;
carll582d5822014-08-07 23:35:54 +00001191# if defined(VKI_LITTLE_ENDIAN)
1192 vai.endness = VexEndnessLE;
1193# elif defined(VKI_BIG_ENDIAN)
sewardj59731422014-07-24 12:45:24 +00001194 vai.endness = VexEndnessBE;
carll582d5822014-08-07 23:35:54 +00001195# else
1196 vai.endness = VexEndness_INVALID;
1197# endif
sewardje3121f32006-01-27 21:23:23 +00001198
1199 vai.hwcaps = 0;
1200 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
1201 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
1202 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardjf34eb492011-04-15 11:57:05 +00001203 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC64_VX;
sewardj5ba075a2012-04-02 21:25:14 +00001204 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC64_DFP;
carlldfbf2942013-08-12 18:04:22 +00001205 if (have_isa_2_07) vai.hwcaps |= VEX_HWCAPS_PPC64_ISA2_07;
sewardj2c48c7b2005-11-29 13:05:56 +00001206
florian78627012012-10-07 19:47:04 +00001207 VG_(machine_get_cache_info)(&vai);
1208
sewardj2c48c7b2005-11-29 13:05:56 +00001209 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
1210 called before we're ready to go. */
1211 return True;
1212 }
1213
sewardjb5b87402011-03-07 16:05:35 +00001214#elif defined(VGA_s390x)
floriandf14eea2012-12-09 17:30:45 +00001215
sewardjf0c12502014-01-12 12:54:00 +00001216# include "libvex_s390x_common.h"
floriandf14eea2012-12-09 17:30:45 +00001217
sewardjb5b87402011-03-07 16:05:35 +00001218 {
1219 /* Instruction set detection code borrowed from ppc above. */
1220 vki_sigset_t saved_set, tmp_set;
1221 vki_sigaction_fromK_t saved_sigill_act;
1222 vki_sigaction_toK_t tmp_sigill_act;
1223
floriandf14eea2012-12-09 17:30:45 +00001224 volatile Bool have_LDISP, have_STFLE;
1225 Int i, r, model;
1226
1227 /* If the model is "unknown" don't treat this as an error. Assume
1228 this is a brand-new machine model for which we don't have the
1229 identification yet. Keeping fingers crossed. */
1230 model = VG_(get_machine_model)();
sewardjb5b87402011-03-07 16:05:35 +00001231
1232 /* Unblock SIGILL and stash away the old action for that signal */
1233 VG_(sigemptyset)(&tmp_set);
1234 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1235
1236 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1237 vg_assert(r == 0);
1238
1239 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1240 vg_assert(r == 0);
1241 tmp_sigill_act = saved_sigill_act;
1242
1243 /* NODEFER: signal handler does not return (from the kernel's point of
1244 view), hence if it is to successfully catch a signal more than once,
1245 we need the NODEFER flag. */
1246 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1247 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1248 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1249 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1250 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1251
1252 /* Determine hwcaps. Note, we cannot use the stfle insn because it
1253 is not supported on z900. */
1254
1255 have_LDISP = True;
sewardj6c591e12011-04-11 16:17:51 +00001256 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001257 have_LDISP = False;
1258 } else {
1259 /* BASR loads the address of the next insn into r1. Needed to avoid
1260 a segfault in XY. */
1261 __asm__ __volatile__("basr %%r1,%%r0\n\t"
1262 ".long 0xe3001000\n\t" /* XY 0,0(%r1) */
1263 ".short 0x0057" : : : "r0", "r1", "cc", "memory");
1264 }
1265
floriandf14eea2012-12-09 17:30:45 +00001266 /* Check availability og STFLE. If available store facility bits
1267 in hoststfle. */
1268 ULong hoststfle[S390_NUM_FACILITY_DW];
sewardjb5b87402011-03-07 16:05:35 +00001269
floriandf14eea2012-12-09 17:30:45 +00001270 for (i = 0; i < S390_NUM_FACILITY_DW; ++i)
1271 hoststfle[i] = 0;
sewardjb5b87402011-03-07 16:05:35 +00001272
floriand19733c2012-01-15 21:02:44 +00001273 have_STFLE = True;
floriand19733c2012-01-15 21:02:44 +00001274 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1275 have_STFLE = False;
1276 } else {
floriandf14eea2012-12-09 17:30:45 +00001277 register ULong reg0 asm("0") = S390_NUM_FACILITY_DW - 1;
floriand19733c2012-01-15 21:02:44 +00001278
1279 __asm__ __volatile__(" .insn s,0xb2b00000,%0\n" /* stfle */
1280 : "=m" (hoststfle), "+d"(reg0)
1281 : : "cc", "memory");
floriand19733c2012-01-15 21:02:44 +00001282 }
1283
sewardjb5b87402011-03-07 16:05:35 +00001284 /* Restore signals */
1285 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1286 vg_assert(r == 0);
1287 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1288 vg_assert(r == 0);
sewardjb5b87402011-03-07 16:05:35 +00001289 va = VexArchS390X;
sewardj59731422014-07-24 12:45:24 +00001290 vai.endness = VexEndnessBE;
sewardjb5b87402011-03-07 16:05:35 +00001291
sewardj2c3f2ea2011-04-13 15:40:10 +00001292 vai.hwcaps = model;
floriandf14eea2012-12-09 17:30:45 +00001293 if (have_STFLE) vai.hwcaps |= VEX_HWCAPS_S390X_STFLE;
sewardj2c3f2ea2011-04-13 15:40:10 +00001294 if (have_LDISP) {
floriandf14eea2012-12-09 17:30:45 +00001295 /* Use long displacement only on machines >= z990. For all other
1296 machines it is millicoded and therefore slow. */
sewardj2c3f2ea2011-04-13 15:40:10 +00001297 if (model >= VEX_S390X_MODEL_Z990)
1298 vai.hwcaps |= VEX_HWCAPS_S390X_LDISP;
1299 }
sewardjb5b87402011-03-07 16:05:35 +00001300
floriandf14eea2012-12-09 17:30:45 +00001301 /* Detect presence of certain facilities using the STFLE insn.
1302 Note, that these facilities were introduced at the same time or later
1303 as STFLE, so the absence of STLFE implies the absence of the facility
1304 we're trying to detect. */
1305 struct fac_hwcaps_map {
1306 UInt installed;
1307 UInt facility_bit;
1308 UInt hwcaps_bit;
1309 const HChar name[6]; // may need adjustment for new facility names
1310 } fac_hwcaps[] = {
1311 { False, S390_FAC_EIMM, VEX_HWCAPS_S390X_EIMM, "EIMM" },
1312 { False, S390_FAC_GIE, VEX_HWCAPS_S390X_GIE, "GIE" },
1313 { False, S390_FAC_DFP, VEX_HWCAPS_S390X_DFP, "DFP" },
1314 { False, S390_FAC_FPSE, VEX_HWCAPS_S390X_FGX, "FGX" },
1315 { False, S390_FAC_ETF2, VEX_HWCAPS_S390X_ETF2, "ETF2" },
1316 { False, S390_FAC_ETF3, VEX_HWCAPS_S390X_ETF3, "ETF3" },
1317 { False, S390_FAC_STCKF, VEX_HWCAPS_S390X_STCKF, "STCKF" },
1318 { False, S390_FAC_FPEXT, VEX_HWCAPS_S390X_FPEXT, "FPEXT" },
1319 { False, S390_FAC_LSC, VEX_HWCAPS_S390X_LSC, "LSC" },
florian11066922013-05-11 15:05:04 +00001320 { False, S390_FAC_PFPO, VEX_HWCAPS_S390X_PFPO, "PFPO" },
floriandf14eea2012-12-09 17:30:45 +00001321 };
1322
1323 /* Set hwcaps according to the detected facilities */
1324 for (i=0; i < sizeof fac_hwcaps / sizeof fac_hwcaps[0]; ++i) {
1325 vg_assert(fac_hwcaps[i].facility_bit <= 63); // for now
1326 if (hoststfle[0] & (1ULL << (63 - fac_hwcaps[i].facility_bit))) {
1327 fac_hwcaps[i].installed = True;
1328 vai.hwcaps |= fac_hwcaps[i].hwcaps_bit;
1329 }
1330 }
1331
1332 /* Build up a string showing the probed-for facilities */
1333 HChar fac_str[(sizeof fac_hwcaps / sizeof fac_hwcaps[0]) *
1334 (sizeof fac_hwcaps[0].name + 3) + // %s %d
1335 7 + 1 + 4 + 2 // machine %4d
1336 + 1]; // \0
1337 HChar *p = fac_str;
1338 p += VG_(sprintf)(p, "machine %4d ", model);
1339 for (i=0; i < sizeof fac_hwcaps / sizeof fac_hwcaps[0]; ++i) {
1340 p += VG_(sprintf)(p, " %s %1d", fac_hwcaps[i].name,
1341 fac_hwcaps[i].installed);
1342 }
1343 *p++ = '\0';
1344
1345 VG_(debugLog)(1, "machine", "%s\n", fac_str);
sewardj2c3f2ea2011-04-13 15:40:10 +00001346 VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
1347
florian78627012012-10-07 19:47:04 +00001348 VG_(machine_get_cache_info)(&vai);
1349
sewardjb5b87402011-03-07 16:05:35 +00001350 return True;
1351 }
1352
sewardj59570ff2010-01-01 11:59:33 +00001353#elif defined(VGA_arm)
1354 {
sewardj1dbd3372010-08-22 12:21:14 +00001355 /* Same instruction set detection algorithm as for ppc32. */
1356 vki_sigset_t saved_set, tmp_set;
1357 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
1358 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
1359
1360 volatile Bool have_VFP, have_VFP2, have_VFP3, have_NEON;
1361 volatile Int archlevel;
1362 Int r;
1363
1364 /* This is a kludge. Really we ought to back-convert saved_act
1365 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1366 since that's a no-op on all ppc64 platforms so far supported,
1367 it's not worth the typing effort. At least include most basic
1368 sanity check: */
1369 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
1370
1371 VG_(sigemptyset)(&tmp_set);
1372 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1373 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
1374
1375 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1376 vg_assert(r == 0);
1377
1378 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1379 vg_assert(r == 0);
1380 tmp_sigill_act = saved_sigill_act;
1381
1382 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1383 tmp_sigfpe_act = saved_sigfpe_act;
1384
1385 /* NODEFER: signal handler does not return (from the kernel's point of
1386 view), hence if it is to successfully catch a signal more than once,
1387 we need the NODEFER flag. */
1388 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1389 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1390 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1391 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1392 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1393
1394 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1395 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1396 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1397 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1398 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1399
1400 /* VFP insns */
1401 have_VFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001402 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001403 have_VFP = False;
1404 } else {
1405 __asm__ __volatile__(".word 0xEEB02B42"); /* VMOV.F64 d2, d2 */
1406 }
1407 /* There are several generation of VFP extension but they differs very
1408 little so for now we will not distinguish them. */
1409 have_VFP2 = have_VFP;
1410 have_VFP3 = have_VFP;
1411
1412 /* NEON insns */
1413 have_NEON = True;
sewardj6c591e12011-04-11 16:17:51 +00001414 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001415 have_NEON = False;
1416 } else {
1417 __asm__ __volatile__(".word 0xF2244154"); /* VMOV q2, q2 */
1418 }
1419
1420 /* ARM architecture level */
1421 archlevel = 5; /* v5 will be base level */
1422 if (archlevel < 7) {
1423 archlevel = 7;
sewardj6c591e12011-04-11 16:17:51 +00001424 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001425 archlevel = 5;
1426 } else {
1427 __asm__ __volatile__(".word 0xF45FF000"); /* PLI [PC,#-0] */
1428 }
1429 }
1430 if (archlevel < 6) {
1431 archlevel = 6;
sewardj6c591e12011-04-11 16:17:51 +00001432 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001433 archlevel = 5;
1434 } else {
1435 __asm__ __volatile__(".word 0xE6822012"); /* PKHBT r2, r2, r2 */
1436 }
1437 }
1438
1439 VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
1440 VG_(convert_sigaction_fromK_to_toK)(&saved_sigfpe_act, &tmp_sigfpe_act);
1441 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1442 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1443 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1444
1445 VG_(debugLog)(1, "machine", "ARMv%d VFP %d VFP2 %d VFP3 %d NEON %d\n",
1446 archlevel, (Int)have_VFP, (Int)have_VFP2, (Int)have_VFP3,
1447 (Int)have_NEON);
1448
1449 VG_(machine_arm_archlevel) = archlevel;
1450
sewardj59570ff2010-01-01 11:59:33 +00001451 va = VexArchARM;
sewardj59731422014-07-24 12:45:24 +00001452 vai.endness = VexEndnessLE;
sewardj1dbd3372010-08-22 12:21:14 +00001453
1454 vai.hwcaps = VEX_ARM_ARCHLEVEL(archlevel);
1455 if (have_VFP3) vai.hwcaps |= VEX_HWCAPS_ARM_VFP3;
1456 if (have_VFP2) vai.hwcaps |= VEX_HWCAPS_ARM_VFP2;
1457 if (have_VFP) vai.hwcaps |= VEX_HWCAPS_ARM_VFP;
1458 if (have_NEON) vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1459
florian78627012012-10-07 19:47:04 +00001460 VG_(machine_get_cache_info)(&vai);
1461
sewardj59570ff2010-01-01 11:59:33 +00001462 return True;
1463 }
1464
sewardjf0c12502014-01-12 12:54:00 +00001465#elif defined(VGA_arm64)
1466 {
1467 va = VexArchARM64;
sewardj59731422014-07-24 12:45:24 +00001468 vai.endness = VexEndnessLE;
sewardjf0c12502014-01-12 12:54:00 +00001469
1470 /* So far there are no variants. */
1471 vai.hwcaps = 0;
1472
1473 VG_(machine_get_cache_info)(&vai);
1474
sewardjc76d0e52014-05-03 21:22:55 +00001475 /* 0 denotes 'not set'. The range of legitimate values here,
1476 after being set that is, is 2 though 17 inclusive. */
1477 vg_assert(vai.arm64_dMinLine_lg2_szB == 0);
1478 vg_assert(vai.arm64_iMinLine_lg2_szB == 0);
1479 ULong ctr_el0;
1480 __asm__ __volatile__("mrs %0, ctr_el0" : "=r"(ctr_el0));
1481 vai.arm64_dMinLine_lg2_szB = ((ctr_el0 >> 16) & 0xF) + 2;
1482 vai.arm64_iMinLine_lg2_szB = ((ctr_el0 >> 0) & 0xF) + 2;
1483 VG_(debugLog)(1, "machine", "ARM64: ctr_el0.dMinLine_szB = %d, "
1484 "ctr_el0.iMinLine_szB = %d\n",
1485 1 << vai.arm64_dMinLine_lg2_szB,
1486 1 << vai.arm64_iMinLine_lg2_szB);
1487
sewardjf0c12502014-01-12 12:54:00 +00001488 return True;
1489 }
1490
sewardj5db15402012-06-07 09:13:21 +00001491#elif defined(VGA_mips32)
1492 {
dejanj24f0c3a2014-02-19 11:57:22 +00001493 /* Define the position of F64 bit in FIR register. */
1494# define FP64 22
sewardj5db15402012-06-07 09:13:21 +00001495 va = VexArchMIPS32;
1496 UInt model = VG_(get_machine_model)();
dejanj5f790e82013-07-25 08:22:08 +00001497 if (model == -1)
sewardj5db15402012-06-07 09:13:21 +00001498 return False;
1499
1500 vai.hwcaps = model;
florian78627012012-10-07 19:47:04 +00001501
sewardj59731422014-07-24 12:45:24 +00001502# if defined(VKI_LITTLE_ENDIAN)
1503 vai.endness = VexEndnessLE;
1504# elif defined(VKI_BIG_ENDIAN)
1505 vai.endness = VexEndnessBE;
1506# else
1507 vai.endness = VexEndness_INVALID;
1508# endif
1509
dejanj5f790e82013-07-25 08:22:08 +00001510 /* Same instruction set detection algorithm as for ppc32/arm... */
1511 vki_sigset_t saved_set, tmp_set;
1512 vki_sigaction_fromK_t saved_sigill_act;
1513 vki_sigaction_toK_t tmp_sigill_act;
1514
1515 volatile Bool have_DSP, have_DSPr2;
1516 Int r;
1517
1518 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
1519
1520 VG_(sigemptyset)(&tmp_set);
1521 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1522
1523 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1524 vg_assert(r == 0);
1525
1526 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1527 vg_assert(r == 0);
1528 tmp_sigill_act = saved_sigill_act;
1529
1530 /* NODEFER: signal handler does not return (from the kernel's point of
1531 view), hence if it is to successfully catch a signal more than once,
1532 we need the NODEFER flag. */
1533 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1534 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1535 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1536 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1537 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1538
petarj96ee38d2013-09-16 18:16:13 +00001539 if (model == VEX_PRID_COMP_MIPS) {
1540 /* DSPr2 instructions. */
1541 have_DSPr2 = True;
1542 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1543 have_DSPr2 = False;
1544 } else {
1545 __asm__ __volatile__(".word 0x7d095351"); /* precr.qb.ph t2, t0, t1 */
1546 }
1547 if (have_DSPr2) {
1548 /* We assume it's 74K, since it can run DSPr2. */
1549 vai.hwcaps |= VEX_PRID_IMP_74K;
1550 } else {
1551 /* DSP instructions. */
1552 have_DSP = True;
1553 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1554 have_DSP = False;
1555 } else {
1556 __asm__ __volatile__(".word 0x7c3f44b8"); /* rddsp t0, 0x3f */
1557 }
1558 if (have_DSP) {
1559 /* We assume it's 34K, since it has support for DSP. */
1560 vai.hwcaps |= VEX_PRID_IMP_34K;
1561 }
1562 }
dejanj5f790e82013-07-25 08:22:08 +00001563 }
1564
dejanj24f0c3a2014-02-19 11:57:22 +00001565 /* Check if CPU has FPU and 32 dbl. prec. FP registers */
1566 int FIR = 0;
1567 __asm__ __volatile__(
1568 "cfc1 %0, $0" "\n\t"
1569 : "=r" (FIR)
1570 );
1571 if (FIR & (1 << FP64)) {
1572 vai.hwcaps |= VEX_PRID_CPU_32FPR;
1573 }
1574
dejanj5f790e82013-07-25 08:22:08 +00001575 VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
1576 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1577 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1578
dejanj5f790e82013-07-25 08:22:08 +00001579 VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
florian78627012012-10-07 19:47:04 +00001580 VG_(machine_get_cache_info)(&vai);
1581
sewardj5db15402012-06-07 09:13:21 +00001582 return True;
1583 }
1584
petarj4df0bfc2013-02-27 23:17:33 +00001585#elif defined(VGA_mips64)
1586 {
1587 va = VexArchMIPS64;
1588 UInt model = VG_(get_machine_model)();
sewardj59731422014-07-24 12:45:24 +00001589 if (model == -1)
petarj4df0bfc2013-02-27 23:17:33 +00001590 return False;
1591
1592 vai.hwcaps = model;
1593
sewardj59731422014-07-24 12:45:24 +00001594# if defined(VKI_LITTLE_ENDIAN)
1595 vai.endness = VexEndnessLE;
1596# elif defined(VKI_BIG_ENDIAN)
1597 vai.endness = VexEndnessBE;
1598# else
1599 vai.endness = VexEndness_INVALID;
1600# endif
1601
petarj4df0bfc2013-02-27 23:17:33 +00001602 VG_(machine_get_cache_info)(&vai);
1603
1604 return True;
1605 }
1606
sewardje2d1e672005-11-12 23:10:48 +00001607#else
1608# error "Unknown arch"
1609#endif
1610}
1611
florian1a59a922013-09-11 18:43:26 +00001612/* Notify host cpu instruction cache line size. */
sewardje3826cf2005-11-13 00:30:22 +00001613#if defined(VGA_ppc32)
1614void VG_(machine_ppc32_set_clszB)( Int szB )
1615{
1616 vg_assert(hwcaps_done);
1617
1618 /* Either the value must not have been set yet (zero) or we can
1619 tolerate it being set to the same value multiple times, as the
1620 stack scanning logic in m_main is a bit stupid. */
florian353d8b82013-08-03 19:37:55 +00001621 vg_assert(vai.ppc_icache_line_szB == 0
1622 || vai.ppc_icache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +00001623
sewardj643d5012013-10-14 11:41:46 +00001624 vg_assert(szB == 16 || szB == 32 || szB == 64 || szB == 128);
florian353d8b82013-08-03 19:37:55 +00001625 vai.ppc_icache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +00001626}
1627#endif
1628
sewardje2d1e672005-11-12 23:10:48 +00001629
florian1a59a922013-09-11 18:43:26 +00001630/* Notify host cpu instruction cache line size. */
carllcae0cc22014-08-07 23:17:29 +00001631#if defined(VGA_ppc64be)|| defined(VGA_ppc64le)
sewardj2c48c7b2005-11-29 13:05:56 +00001632void VG_(machine_ppc64_set_clszB)( Int szB )
1633{
1634 vg_assert(hwcaps_done);
1635
1636 /* Either the value must not have been set yet (zero) or we can
1637 tolerate it being set to the same value multiple times, as the
1638 stack scanning logic in m_main is a bit stupid. */
florian353d8b82013-08-03 19:37:55 +00001639 vg_assert(vai.ppc_icache_line_szB == 0
1640 || vai.ppc_icache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +00001641
sewardj643d5012013-10-14 11:41:46 +00001642 vg_assert(szB == 16 || szB == 32 || szB == 64 || szB == 128);
florian353d8b82013-08-03 19:37:55 +00001643 vai.ppc_icache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +00001644}
1645#endif
1646
1647
sewardja3551be2010-09-09 07:25:58 +00001648/* Notify host's ability to handle NEON instructions. */
1649#if defined(VGA_arm)
1650void VG_(machine_arm_set_has_NEON)( Bool has_neon )
1651{
1652 vg_assert(hwcaps_done);
1653 /* There's nothing else we can sanity check. */
1654
1655 if (has_neon) {
1656 vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1657 } else {
1658 vai.hwcaps &= ~VEX_HWCAPS_ARM_NEON;
1659 }
1660}
1661#endif
1662
1663
sewardje2d1e672005-11-12 23:10:48 +00001664/* Fetch host cpu info, once established. */
1665void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
1666 /*OUT*/VexArchInfo* pVai )
1667{
1668 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +00001669 if (pVa) *pVa = va;
1670 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +00001671}
sewardj7821e2e2005-08-08 00:35:46 +00001672
1673
sewardj98763d52012-06-03 22:40:07 +00001674/* Returns the size of the largest guest register that we will
1675 simulate in this run. This depends on both the guest architecture
1676 and on the specific capabilities we are simulating for that guest
1677 (eg, AVX or non-AVX ?, for amd64). Should return either 4, 8, 16
1678 or 32. General rule: if in doubt, return a value larger than
1679 reality.
1680
1681 This information is needed by Cachegrind and Callgrind to decide
1682 what the minimum cache line size they are prepared to simulate is.
1683 Basically require that the minimum cache line size is at least as
1684 large as the largest register that might get transferred to/from
1685 memory, so as to guarantee that any such transaction can straddle
1686 at most 2 cache lines.
1687*/
1688Int VG_(machine_get_size_of_largest_guest_register) ( void )
1689{
1690 vg_assert(hwcaps_done);
1691 /* Once hwcaps_done is True, we can fish around inside va/vai to
1692 find the information we need. */
1693
1694# if defined(VGA_x86)
1695 vg_assert(va == VexArchX86);
1696 /* We don't support AVX, so 32 is out. At the other end, even if
1697 we don't support any SSE, the X87 can generate 10 byte
1698 transfers, so let's say 16 to be on the safe side. Hence the
1699 answer is always 16. */
1700 return 16;
1701
1702# elif defined(VGA_amd64)
1703 /* if AVX then 32 else 16 */
1704 return (vai.hwcaps & VEX_HWCAPS_AMD64_AVX) ? 32 : 16;
1705
1706# elif defined(VGA_ppc32)
1707 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1708 if (vai.hwcaps & VEX_HWCAPS_PPC32_V) return 16;
1709 if (vai.hwcaps & VEX_HWCAPS_PPC32_VX) return 16;
1710 if (vai.hwcaps & VEX_HWCAPS_PPC32_DFP) return 16;
1711 return 8;
1712
carllcae0cc22014-08-07 23:17:29 +00001713# elif defined(VGA_ppc64be) || defined(VGA_ppc64le)
sewardj98763d52012-06-03 22:40:07 +00001714 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1715 if (vai.hwcaps & VEX_HWCAPS_PPC64_V) return 16;
1716 if (vai.hwcaps & VEX_HWCAPS_PPC64_VX) return 16;
1717 if (vai.hwcaps & VEX_HWCAPS_PPC64_DFP) return 16;
1718 return 8;
1719
1720# elif defined(VGA_s390x)
1721 return 8;
1722
1723# elif defined(VGA_arm)
1724 /* Really it depends whether or not we have NEON, but let's just
1725 assume we always do. */
1726 return 16;
1727
sewardjf0c12502014-01-12 12:54:00 +00001728# elif defined(VGA_arm64)
1729 /* ARM64 always has Neon, AFAICS. */
1730 return 16;
1731
sewardj5db15402012-06-07 09:13:21 +00001732# elif defined(VGA_mips32)
1733 /* The guest state implies 4, but that can't really be true, can
1734 it? */
1735 return 8;
1736
petarj4df0bfc2013-02-27 23:17:33 +00001737# elif defined(VGA_mips64)
1738 return 8;
1739
sewardj98763d52012-06-03 22:40:07 +00001740# else
1741# error "Unknown arch"
1742# endif
1743}
1744
1745
sewardj53ee1fc2005-12-23 02:29:58 +00001746// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +00001747// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +00001748void* VG_(fnptr_to_fnentry)( void* f )
1749{
sewardj6e9de462011-06-28 07:25:29 +00001750# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
carllcae0cc22014-08-07 23:17:29 +00001751 || defined(VGP_arm_linux) || defined(VGO_darwin) \
1752 || defined(VGP_ppc32_linux) || defined(VGP_ppc64le_linux) \
petarj4df0bfc2013-02-27 23:17:33 +00001753 || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
sewardjf0c12502014-01-12 12:54:00 +00001754 || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
sewardj53ee1fc2005-12-23 02:29:58 +00001755 return f;
carllcae0cc22014-08-07 23:17:29 +00001756# elif defined(VGP_ppc64be_linux)
sewardj6e9de462011-06-28 07:25:29 +00001757 /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
1758 3-word function descriptor, of which the first word is the entry
1759 address. */
sewardjf1c91e02006-10-17 01:35:58 +00001760 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +00001761 return (void*)(descr[0]);
sewardj6e9de462011-06-28 07:25:29 +00001762# else
1763# error "Unknown platform"
1764# endif
sewardj53ee1fc2005-12-23 02:29:58 +00001765}
1766
njnf536bbb2005-06-13 04:21:38 +00001767/*--------------------------------------------------------------------*/
1768/*--- end ---*/
1769/*--------------------------------------------------------------------*/