blob: f2d90a211e792acee673c9a1bb25a54e27f7e560 [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
sewardj03f8d3f2012-08-05 15:46:46 +00009 Copyright (C) 2000-2012 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"
37#include "pub_core_mallocfree.h"
njnf536bbb2005-06-13 04:21:38 +000038#include "pub_core_machine.h"
sewardje2d1e672005-11-12 23:10:48 +000039#include "pub_core_cpuid.h"
bart1581e742009-01-13 07:49:14 +000040#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL and SIGFPE
sewardj3b0cae72009-05-28 17:15:41 +000041#include "pub_core_debuglog.h"
sewardje3826cf2005-11-13 00:30:22 +000042
njnf536bbb2005-06-13 04:21:38 +000043
njnaf839f52005-06-23 03:27:57 +000044#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
45#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
46#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
njnf536bbb2005-06-13 04:21:38 +000047
sewardj1dbd3372010-08-22 12:21:14 +000048Addr VG_(get_IP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000049 return INSTR_PTR( VG_(threads)[tid].arch );
50}
sewardj1dbd3372010-08-22 12:21:14 +000051Addr VG_(get_SP) ( ThreadId tid ) {
52 return STACK_PTR( VG_(threads)[tid].arch );
53}
54Addr VG_(get_FP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000055 return FRAME_PTR( VG_(threads)[tid].arch );
56}
57
sewardj1dbd3372010-08-22 12:21:14 +000058void VG_(set_IP) ( ThreadId tid, Addr ip ) {
njnf536bbb2005-06-13 04:21:38 +000059 INSTR_PTR( VG_(threads)[tid].arch ) = ip;
60}
sewardj1dbd3372010-08-22 12:21:14 +000061void VG_(set_SP) ( ThreadId tid, Addr sp ) {
62 STACK_PTR( VG_(threads)[tid].arch ) = sp;
63}
sewardj59570ff2010-01-01 11:59:33 +000064
65void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
66 ThreadId tid )
67{
68# if defined(VGA_x86)
69 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_EIP;
70 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_ESP;
71 regs->misc.X86.r_ebp
72 = VG_(threads)[tid].arch.vex.guest_EBP;
73# elif defined(VGA_amd64)
74 regs->r_pc = VG_(threads)[tid].arch.vex.guest_RIP;
75 regs->r_sp = VG_(threads)[tid].arch.vex.guest_RSP;
76 regs->misc.AMD64.r_rbp
77 = VG_(threads)[tid].arch.vex.guest_RBP;
78# elif defined(VGA_ppc32)
79 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000080 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000081 regs->misc.PPC32.r_lr
82 = VG_(threads)[tid].arch.vex.guest_LR;
83# elif defined(VGA_ppc64)
84 regs->r_pc = VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000085 regs->r_sp = VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000086 regs->misc.PPC64.r_lr
87 = VG_(threads)[tid].arch.vex.guest_LR;
88# elif defined(VGA_arm)
sewardj1dbd3372010-08-22 12:21:14 +000089 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_R15T;
sewardj59570ff2010-01-01 11:59:33 +000090 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_R13;
91 regs->misc.ARM.r14
92 = VG_(threads)[tid].arch.vex.guest_R14;
93 regs->misc.ARM.r12
94 = VG_(threads)[tid].arch.vex.guest_R12;
95 regs->misc.ARM.r11
96 = VG_(threads)[tid].arch.vex.guest_R11;
sewardjfa5ce562010-09-23 22:05:59 +000097 regs->misc.ARM.r7
98 = VG_(threads)[tid].arch.vex.guest_R7;
sewardjb5b87402011-03-07 16:05:35 +000099# elif defined(VGA_s390x)
100 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_IA;
101 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_SP;
102 regs->misc.S390X.r_fp
103 = VG_(threads)[tid].arch.vex.guest_r11;
104 regs->misc.S390X.r_lr
105 = VG_(threads)[tid].arch.vex.guest_r14;
sewardj5db15402012-06-07 09:13:21 +0000106# elif defined(VGA_mips32)
107 regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
108 regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
109 regs->misc.MIPS32.r30
110 = VG_(threads)[tid].arch.vex.guest_r30;
111 regs->misc.MIPS32.r31
112 = VG_(threads)[tid].arch.vex.guest_r31;
113 regs->misc.MIPS32.r28
114 = VG_(threads)[tid].arch.vex.guest_r28;
sewardj59570ff2010-01-01 11:59:33 +0000115# else
116# error "Unknown arch"
117# endif
118}
119
120
sewardj9c606bd2008-09-18 18:12:50 +0000121void VG_(set_syscall_return_shadows) ( ThreadId tid,
122 /* shadow vals for the result */
123 UWord s1res, UWord s2res,
124 /* shadow vals for the error val */
125 UWord s1err, UWord s2err )
126{
127# if defined(VGP_x86_linux)
128 VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res;
129 VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res;
130# elif defined(VGP_amd64_linux)
131 VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res;
132 VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res;
133# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
134 VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
135 VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
sewardj59570ff2010-01-01 11:59:33 +0000136# elif defined(VGP_arm_linux)
137 VG_(threads)[tid].arch.vex_shadow1.guest_R0 = s1res;
138 VG_(threads)[tid].arch.vex_shadow2.guest_R0 = s2res;
njnf76d27a2009-05-28 01:53:07 +0000139# elif defined(VGO_darwin)
140 // GrP fixme darwin syscalls may return more values (2 registers plus error)
sewardjb5b87402011-03-07 16:05:35 +0000141# elif defined(VGP_s390x_linux)
142 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
143 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj5db15402012-06-07 09:13:21 +0000144# elif defined(VGP_mips32_linux)
145 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
146 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj9c606bd2008-09-18 18:12:50 +0000147# else
148# error "Unknown plat"
149# endif
150}
njnf536bbb2005-06-13 04:21:38 +0000151
sewardj7cf4e6b2008-05-01 20:24:26 +0000152void
153VG_(get_shadow_regs_area) ( ThreadId tid,
154 /*DST*/UChar* dst,
njnc4431bf2009-01-15 21:29:24 +0000155 /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size )
njnf536bbb2005-06-13 04:21:38 +0000156{
sewardj7cf4e6b2008-05-01 20:24:26 +0000157 void* src;
njnf536bbb2005-06-13 04:21:38 +0000158 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000159 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000160 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000161 // Bounds check
162 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
163 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000164 // Copy
165 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000166 src = NULL;
167 switch (shadowNo) {
168 case 0: src = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
169 case 1: src = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
170 case 2: src = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
171 }
172 tl_assert(src != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000173 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000174}
175
sewardj7cf4e6b2008-05-01 20:24:26 +0000176void
177VG_(set_shadow_regs_area) ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +0000178 /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
sewardj7cf4e6b2008-05-01 20:24:26 +0000179 /*SRC*/const UChar* src )
njnf536bbb2005-06-13 04:21:38 +0000180{
sewardj7cf4e6b2008-05-01 20:24:26 +0000181 void* dst;
njnf536bbb2005-06-13 04:21:38 +0000182 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000183 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000184 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000185 // Bounds check
186 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
187 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000188 // Copy
189 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000190 dst = NULL;
191 switch (shadowNo) {
192 case 0: dst = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
193 case 1: dst = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
194 case 2: dst = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
195 }
196 tl_assert(dst != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000197 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000198}
199
200
philippea22f59d2012-01-26 23:13:52 +0000201static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId, HChar*, Addr))
njn6ace3ea2005-06-17 03:06:27 +0000202{
philippea22f59d2012-01-26 23:13:52 +0000203 VexGuestArchState* vex = &(VG_(get_ThreadState)(tid)->arch.vex);
njn6ace3ea2005-06-17 03:06:27 +0000204#if defined(VGA_x86)
philippea22f59d2012-01-26 23:13:52 +0000205 (*f)(tid, "EAX", vex->guest_EAX);
206 (*f)(tid, "ECX", vex->guest_ECX);
207 (*f)(tid, "EDX", vex->guest_EDX);
208 (*f)(tid, "EBX", vex->guest_EBX);
209 (*f)(tid, "ESI", vex->guest_ESI);
210 (*f)(tid, "EDI", vex->guest_EDI);
211 (*f)(tid, "ESP", vex->guest_ESP);
212 (*f)(tid, "EBP", vex->guest_EBP);
njn6ace3ea2005-06-17 03:06:27 +0000213#elif defined(VGA_amd64)
philippea22f59d2012-01-26 23:13:52 +0000214 (*f)(tid, "RAX", vex->guest_RAX);
215 (*f)(tid, "RCX", vex->guest_RCX);
216 (*f)(tid, "RDX", vex->guest_RDX);
217 (*f)(tid, "RBX", vex->guest_RBX);
218 (*f)(tid, "RSI", vex->guest_RSI);
219 (*f)(tid, "RDI", vex->guest_RDI);
220 (*f)(tid, "RSP", vex->guest_RSP);
221 (*f)(tid, "RBP", vex->guest_RBP);
222 (*f)(tid, "R8" , vex->guest_R8 );
223 (*f)(tid, "R9" , vex->guest_R9 );
224 (*f)(tid, "R10", vex->guest_R10);
225 (*f)(tid, "R11", vex->guest_R11);
226 (*f)(tid, "R12", vex->guest_R12);
227 (*f)(tid, "R13", vex->guest_R13);
228 (*f)(tid, "R14", vex->guest_R14);
229 (*f)(tid, "R15", vex->guest_R15);
sewardj2c48c7b2005-11-29 13:05:56 +0000230#elif defined(VGA_ppc32) || defined(VGA_ppc64)
philippea22f59d2012-01-26 23:13:52 +0000231 (*f)(tid, "GPR0" , vex->guest_GPR0 );
232 (*f)(tid, "GPR1" , vex->guest_GPR1 );
233 (*f)(tid, "GPR2" , vex->guest_GPR2 );
234 (*f)(tid, "GPR3" , vex->guest_GPR3 );
235 (*f)(tid, "GPR4" , vex->guest_GPR4 );
236 (*f)(tid, "GPR5" , vex->guest_GPR5 );
237 (*f)(tid, "GPR6" , vex->guest_GPR6 );
238 (*f)(tid, "GPR7" , vex->guest_GPR7 );
239 (*f)(tid, "GPR8" , vex->guest_GPR8 );
240 (*f)(tid, "GPR9" , vex->guest_GPR9 );
241 (*f)(tid, "GPR10", vex->guest_GPR10);
242 (*f)(tid, "GPR11", vex->guest_GPR11);
243 (*f)(tid, "GPR12", vex->guest_GPR12);
244 (*f)(tid, "GPR13", vex->guest_GPR13);
245 (*f)(tid, "GPR14", vex->guest_GPR14);
246 (*f)(tid, "GPR15", vex->guest_GPR15);
247 (*f)(tid, "GPR16", vex->guest_GPR16);
248 (*f)(tid, "GPR17", vex->guest_GPR17);
249 (*f)(tid, "GPR18", vex->guest_GPR18);
250 (*f)(tid, "GPR19", vex->guest_GPR19);
251 (*f)(tid, "GPR20", vex->guest_GPR20);
252 (*f)(tid, "GPR21", vex->guest_GPR21);
253 (*f)(tid, "GPR22", vex->guest_GPR22);
254 (*f)(tid, "GPR23", vex->guest_GPR23);
255 (*f)(tid, "GPR24", vex->guest_GPR24);
256 (*f)(tid, "GPR25", vex->guest_GPR25);
257 (*f)(tid, "GPR26", vex->guest_GPR26);
258 (*f)(tid, "GPR27", vex->guest_GPR27);
259 (*f)(tid, "GPR28", vex->guest_GPR28);
260 (*f)(tid, "GPR29", vex->guest_GPR29);
261 (*f)(tid, "GPR30", vex->guest_GPR30);
262 (*f)(tid, "GPR31", vex->guest_GPR31);
263 (*f)(tid, "CTR" , vex->guest_CTR );
264 (*f)(tid, "LR" , vex->guest_LR );
sewardj59570ff2010-01-01 11:59:33 +0000265#elif defined(VGA_arm)
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, "R8" , vex->guest_R8 );
274 (*f)(tid, "R9" , vex->guest_R9 );
275 (*f)(tid, "R10", vex->guest_R10);
276 (*f)(tid, "R11", vex->guest_R11);
277 (*f)(tid, "R12", vex->guest_R12);
278 (*f)(tid, "R13", vex->guest_R13);
279 (*f)(tid, "R14", vex->guest_R14);
sewardjb5b87402011-03-07 16:05:35 +0000280#elif defined(VGA_s390x)
philippea22f59d2012-01-26 23:13:52 +0000281 (*f)(tid, "r0" , vex->guest_r0 );
282 (*f)(tid, "r1" , vex->guest_r1 );
283 (*f)(tid, "r2" , vex->guest_r2 );
284 (*f)(tid, "r3" , vex->guest_r3 );
285 (*f)(tid, "r4" , vex->guest_r4 );
286 (*f)(tid, "r5" , vex->guest_r5 );
287 (*f)(tid, "r6" , vex->guest_r6 );
288 (*f)(tid, "r7" , vex->guest_r7 );
289 (*f)(tid, "r8" , vex->guest_r8 );
290 (*f)(tid, "r9" , vex->guest_r9 );
291 (*f)(tid, "r10", vex->guest_r10);
292 (*f)(tid, "r11", vex->guest_r11);
293 (*f)(tid, "r12", vex->guest_r12);
294 (*f)(tid, "r13", vex->guest_r13);
295 (*f)(tid, "r14", vex->guest_r14);
296 (*f)(tid, "r15", vex->guest_r15);
sewardj5db15402012-06-07 09:13:21 +0000297#elif defined(VGA_mips32)
298 (*f)(tid, "r0" , vex->guest_r0 );
299 (*f)(tid, "r1" , vex->guest_r1 );
300 (*f)(tid, "r2" , vex->guest_r2 );
301 (*f)(tid, "r3" , vex->guest_r3 );
302 (*f)(tid, "r4" , vex->guest_r4 );
303 (*f)(tid, "r5" , vex->guest_r5 );
304 (*f)(tid, "r6" , vex->guest_r6 );
305 (*f)(tid, "r7" , vex->guest_r7 );
306 (*f)(tid, "r8" , vex->guest_r8 );
307 (*f)(tid, "r9" , vex->guest_r9 );
308 (*f)(tid, "r10", vex->guest_r10);
309 (*f)(tid, "r11", vex->guest_r11);
310 (*f)(tid, "r12", vex->guest_r12);
311 (*f)(tid, "r13", vex->guest_r13);
312 (*f)(tid, "r14", vex->guest_r14);
313 (*f)(tid, "r15", vex->guest_r15);
314 (*f)(tid, "r16", vex->guest_r16);
315 (*f)(tid, "r17", vex->guest_r17);
316 (*f)(tid, "r18", vex->guest_r18);
317 (*f)(tid, "r19", vex->guest_r19);
318 (*f)(tid, "r20", vex->guest_r20);
319 (*f)(tid, "r21", vex->guest_r21);
320 (*f)(tid, "r22", vex->guest_r22);
321 (*f)(tid, "r23", vex->guest_r23);
322 (*f)(tid, "r24", vex->guest_r24);
323 (*f)(tid, "r25", vex->guest_r25);
324 (*f)(tid, "r26", vex->guest_r26);
325 (*f)(tid, "r27", vex->guest_r27);
326 (*f)(tid, "r28", vex->guest_r28);
327 (*f)(tid, "r29", vex->guest_r29);
328 (*f)(tid, "r30", vex->guest_r30);
329 (*f)(tid, "r31", vex->guest_r31);
njn6ace3ea2005-06-17 03:06:27 +0000330#else
331# error Unknown arch
332#endif
333}
334
335
philippea22f59d2012-01-26 23:13:52 +0000336void VG_(apply_to_GP_regs)(void (*f)(ThreadId, HChar*, UWord))
njn6ace3ea2005-06-17 03:06:27 +0000337{
338 ThreadId tid;
339
340 for (tid = 1; tid < VG_N_THREADS; tid++) {
341 if (VG_(is_valid_tid)(tid)) {
philippea22f59d2012-01-26 23:13:52 +0000342 apply_to_GPs_of_tid(tid, f);
njn6ace3ea2005-06-17 03:06:27 +0000343 }
344 }
345}
346
sewardjb8b79ad2008-03-03 01:35:41 +0000347void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
njnb506bd82005-06-21 04:01:51 +0000348{
sewardjb8b79ad2008-03-03 01:35:41 +0000349 *tid = (ThreadId)(-1);
njnb506bd82005-06-21 04:01:51 +0000350}
njn6ace3ea2005-06-17 03:06:27 +0000351
sewardjb8b79ad2008-03-03 01:35:41 +0000352Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
353 /*OUT*/Addr* stack_min,
354 /*OUT*/Addr* stack_max)
njn1d0cb0d2005-08-15 01:52:02 +0000355{
356 ThreadId i;
sewardjb8b79ad2008-03-03 01:35:41 +0000357 for (i = (*tid)+1; i < VG_N_THREADS; i++) {
358 if (i == VG_INVALID_THREADID)
359 continue;
njn1d0cb0d2005-08-15 01:52:02 +0000360 if (VG_(threads)[i].status != VgTs_Empty) {
361 *tid = i;
362 *stack_min = VG_(get_SP)(i);
363 *stack_max = VG_(threads)[i].client_stack_highest_word;
njn1d0cb0d2005-08-15 01:52:02 +0000364 return True;
365 }
366 }
367 return False;
368}
sewardj7821e2e2005-08-08 00:35:46 +0000369
sewardjbbec7722007-11-25 14:08:53 +0000370Addr VG_(thread_get_stack_max)(ThreadId tid)
371{
372 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
373 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
374 return VG_(threads)[tid].client_stack_highest_word;
375}
376
bart0fb03202008-03-29 09:25:53 +0000377SizeT VG_(thread_get_stack_size)(ThreadId tid)
378{
379 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
380 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
381 return VG_(threads)[tid].client_stack_szB;
382}
383
bart83c5a922010-09-02 14:38:38 +0000384Addr VG_(thread_get_altstack_min)(ThreadId tid)
385{
386 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
387 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
388 return (Addr)VG_(threads)[tid].altstack.ss_sp;
389}
390
391SizeT VG_(thread_get_altstack_size)(ThreadId tid)
392{
393 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
394 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
395 return VG_(threads)[tid].altstack.ss_size;
396}
397
sewardje2d1e672005-11-12 23:10:48 +0000398//-------------------------------------------------------------
399/* Details about the capabilities of the underlying (host) CPU. These
400 details are acquired by (1) enquiring with the CPU at startup, or
401 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
402 line size). It's a bit nasty in the sense that there's no obvious
403 way to stop uses of some of this info before it's ready to go.
florian0daa4e32012-04-22 02:48:20 +0000404 See pub_core_machine.h for more information about that.
sewardjb5b87402011-03-07 16:05:35 +0000405
sewardje2d1e672005-11-12 23:10:48 +0000406 VG_(machine_get_hwcaps) may use signals (although it attempts to
407 leave signal state unchanged) and therefore should only be
408 called before m_main sets up the client's signal state.
409*/
410
411/* --------- State --------- */
sewardj59570ff2010-01-01 11:59:33 +0000412static Bool hwcaps_done = False;
sewardje2d1e672005-11-12 23:10:48 +0000413
414/* --- all archs --- */
sewardj98763d52012-06-03 22:40:07 +0000415static VexArch va = VexArch_INVALID;
sewardje2d1e672005-11-12 23:10:48 +0000416static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000417
sewardj7821e2e2005-08-08 00:35:46 +0000418#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000419UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000420#endif
sewardje2d1e672005-11-12 23:10:48 +0000421#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000422UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000423UInt VG_(machine_ppc32_has_VMX) = 0;
424#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000425#if defined(VGA_ppc64)
426ULong VG_(machine_ppc64_has_VMX) = 0;
427#endif
sewardj1dbd3372010-08-22 12:21:14 +0000428#if defined(VGA_arm)
429Int VG_(machine_arm_archlevel) = 4;
430#endif
sewardje2d1e672005-11-12 23:10:48 +0000431
sewardjb5b87402011-03-07 16:05:35 +0000432/* fixs390: anything for s390x here ? */
sewardje2d1e672005-11-12 23:10:48 +0000433
sewardj2c3f2ea2011-04-13 15:40:10 +0000434/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
sewardj6c591e12011-04-11 16:17:51 +0000435 testing, so we need a VG_MINIMAL_JMP_BUF. */
436#if defined(VGA_ppc32) || defined(VGA_ppc64) \
petarj2fd883a2012-06-30 02:12:13 +0000437 || defined(VGA_arm) || defined(VGA_s390x)
sewardj6c591e12011-04-11 16:17:51 +0000438#include "pub_tool_libcsetjmp.h"
sewardj97d3ebb2011-04-11 18:36:34 +0000439static VG_MINIMAL_JMP_BUF(env_unsup_insn);
sewardj6c591e12011-04-11 16:17:51 +0000440static void handler_unsup_insn ( Int x ) {
441 VG_MINIMAL_LONGJMP(env_unsup_insn);
442}
sewardj5ae70ce2010-09-08 15:12:33 +0000443#endif
444
sewardjb9c815b2010-09-03 15:51:34 +0000445
446/* Helper function for VG_(machine_get_hwcaps), assumes the SIGILL/etc
447 * handlers are installed. Determines the the sizes affected by dcbz
448 * and dcbzl instructions and updates the given VexArchInfo structure
449 * accordingly.
450 *
451 * Not very defensive: assumes that as long as the dcbz/dcbzl
452 * instructions don't raise a SIGILL, that they will zero an aligned,
453 * contiguous block of memory of a sensible size. */
sewardj5ae70ce2010-09-08 15:12:33 +0000454#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjb9c815b2010-09-03 15:51:34 +0000455static void find_ppc_dcbz_sz(VexArchInfo *arch_info)
456{
sewardjdcb3a592010-09-04 00:43:14 +0000457 Int dcbz_szB = 0;
sewardjb9c815b2010-09-03 15:51:34 +0000458 Int dcbzl_szB;
sewardj5ae70ce2010-09-08 15:12:33 +0000459# define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
sewardjb9c815b2010-09-03 15:51:34 +0000460 char test_block[4*MAX_DCBZL_SZB];
461 char *aligned = test_block;
462 Int i;
463
464 /* round up to next max block size, assumes MAX_DCBZL_SZB is pof2 */
465 aligned = (char *)(((HWord)aligned + MAX_DCBZL_SZB) & ~(MAX_DCBZL_SZB - 1));
466 vg_assert((aligned + MAX_DCBZL_SZB) <= &test_block[sizeof(test_block)]);
467
468 /* dcbz often clears 32B, although sometimes whatever the native cache
469 * block size is */
470 VG_(memset)(test_block, 0xff, sizeof(test_block));
471 __asm__ __volatile__("dcbz 0,%0"
472 : /*out*/
473 : "r" (aligned) /*in*/
474 : "memory" /*clobber*/);
475 for (dcbz_szB = 0, i = 0; i < sizeof(test_block); ++i) {
476 if (!test_block[i])
477 ++dcbz_szB;
478 }
479 vg_assert(dcbz_szB == 32 || dcbz_szB == 64 || dcbz_szB == 128);
480
481 /* dcbzl clears 128B on G5/PPC970, and usually 32B on other platforms */
sewardj6c591e12011-04-11 16:17:51 +0000482 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb9c815b2010-09-03 15:51:34 +0000483 dcbzl_szB = 0; /* indicates unsupported */
484 }
485 else {
486 VG_(memset)(test_block, 0xff, sizeof(test_block));
487 /* some older assemblers won't understand the dcbzl instruction
488 * variant, so we directly emit the instruction ourselves */
489 __asm__ __volatile__("mr 9, %0 ; .long 0x7C204FEC" /*dcbzl 0,9*/
490 : /*out*/
491 : "r" (aligned) /*in*/
492 : "memory", "r9" /*clobber*/);
493 for (dcbzl_szB = 0, i = 0; i < sizeof(test_block); ++i) {
494 if (!test_block[i])
495 ++dcbzl_szB;
496 }
497 vg_assert(dcbzl_szB == 32 || dcbzl_szB == 64 || dcbzl_szB == 128);
498 }
499
500 arch_info->ppc_dcbz_szB = dcbz_szB;
501 arch_info->ppc_dcbzl_szB = dcbzl_szB;
502
503 VG_(debugLog)(1, "machine", "dcbz_szB=%d dcbzl_szB=%d\n",
504 dcbz_szB, dcbzl_szB);
sewardj5ae70ce2010-09-08 15:12:33 +0000505# undef MAX_DCBZL_SZB
sewardjb9c815b2010-09-03 15:51:34 +0000506}
sewardj5ae70ce2010-09-08 15:12:33 +0000507#endif /* defined(VGA_ppc32) || defined(VGA_ppc64) */
508
sewardj2c3f2ea2011-04-13 15:40:10 +0000509#ifdef VGA_s390x
sewardj5ae70ce2010-09-08 15:12:33 +0000510
sewardj2c3f2ea2011-04-13 15:40:10 +0000511/* Read /proc/cpuinfo. Look for lines like these
512
513 processor 0: version = FF, identification = 0117C9, machine = 2064
514
florian4e63b8e2012-04-22 03:50:20 +0000515 and return the machine model. If the machine model could not be determined
516 or it is an unknown model, return VEX_S390X_MODEL_UNKNOWN. */
sewardj2c3f2ea2011-04-13 15:40:10 +0000517
518static UInt VG_(get_machine_model)(void)
519{
520 static struct model_map {
521 HChar name[5];
522 UInt id;
523 } model_map[] = {
524 { "2064", VEX_S390X_MODEL_Z900 },
525 { "2066", VEX_S390X_MODEL_Z800 },
526 { "2084", VEX_S390X_MODEL_Z990 },
527 { "2086", VEX_S390X_MODEL_Z890 },
528 { "2094", VEX_S390X_MODEL_Z9_EC },
529 { "2096", VEX_S390X_MODEL_Z9_BC },
530 { "2097", VEX_S390X_MODEL_Z10_EC },
531 { "2098", VEX_S390X_MODEL_Z10_BC },
532 { "2817", VEX_S390X_MODEL_Z196 },
florian258ede72011-09-02 22:20:41 +0000533 { "2818", VEX_S390X_MODEL_Z114 },
florian87a25cf2012-08-28 13:33:10 +0000534 { "2827", VEX_S390X_MODEL_ZEC12 },
sewardj2c3f2ea2011-04-13 15:40:10 +0000535 };
536
537 Int model, n, fh;
538 SysRes fd;
539 SizeT num_bytes, file_buf_size;
540 HChar *p, *m, *model_name, *file_buf;
541
542 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
543 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
florian4e63b8e2012-04-22 03:50:20 +0000544 if ( sr_isError(fd) ) return VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000545
546 fh = sr_Res(fd);
547
548 /* Determine the size of /proc/cpuinfo.
549 Work around broken-ness in /proc file system implementation.
550 fstat returns a zero size for /proc/cpuinfo although it is
551 claimed to be a regular file. */
552 num_bytes = 0;
553 file_buf_size = 1000;
554 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
555 while (42) {
556 n = VG_(read)(fh, file_buf, file_buf_size);
557 if (n < 0) break;
558
559 num_bytes += n;
560 if (n < file_buf_size) break; /* reached EOF */
561 }
562
563 if (n < 0) num_bytes = 0; /* read error; ignore contents */
564
565 if (num_bytes > file_buf_size) {
566 VG_(free)( file_buf );
567 VG_(lseek)( fh, 0, VKI_SEEK_SET );
568 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
569 n = VG_(read)( fh, file_buf, num_bytes );
570 if (n < 0) num_bytes = 0;
571 }
572
573 file_buf[num_bytes] = '\0';
574 VG_(close)(fh);
575
576 /* Parse file */
florian4e63b8e2012-04-22 03:50:20 +0000577 model = VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000578 for (p = file_buf; *p; ++p) {
579 /* Beginning of line */
580 if (VG_(strncmp)( p, "processor", sizeof "processor" - 1 ) != 0) continue;
581
582 m = VG_(strstr)( p, "machine" );
583 if (m == NULL) continue;
584
585 p = m + sizeof "machine" - 1;
586 while ( VG_(isspace)( *p ) || *p == '=') {
587 if (*p == '\n') goto next_line;
588 ++p;
589 }
590
591 model_name = p;
592 for (n = 0; n < sizeof model_map / sizeof model_map[0]; ++n) {
593 struct model_map *mm = model_map + n;
594 SizeT len = VG_(strlen)( mm->name );
595 if ( VG_(strncmp)( mm->name, model_name, len ) == 0 &&
596 VG_(isspace)( model_name[len] )) {
597 if (mm->id < model) model = mm->id;
598 p = model_name + len;
599 break;
600 }
601 }
602 /* Skip until end-of-line */
603 while (*p != '\n')
604 ++p;
605 next_line: ;
606 }
607
608 VG_(free)( file_buf );
florian00164922011-10-25 21:37:15 +0000609 VG_(debugLog)(1, "machine", "model = %s\n",
florian4e63b8e2012-04-22 03:50:20 +0000610 model == VEX_S390X_MODEL_UNKNOWN ? "UNKNOWN"
florian00164922011-10-25 21:37:15 +0000611 : model_map[model].name);
sewardj2c3f2ea2011-04-13 15:40:10 +0000612 return model;
613}
614
615#endif /* VGA_s390x */
sewardj5ae70ce2010-09-08 15:12:33 +0000616
sewardj5db15402012-06-07 09:13:21 +0000617#ifdef VGA_mips32
618
619/* Read /proc/cpuinfo and return the machine model. */
620static UInt VG_(get_machine_model)(void)
621{
622 char *search_MIPS_str = "MIPS";
623 char *search_Broadcom_str = "Broadcom";
624 Int n, fh;
625 SysRes fd;
626 SizeT num_bytes, file_buf_size;
627 HChar *file_buf;
628
629 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
630 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
631 if ( sr_isError(fd) ) return -1;
632
633 fh = sr_Res(fd);
634
635 /* Determine the size of /proc/cpuinfo.
636 Work around broken-ness in /proc file system implementation.
637 fstat returns a zero size for /proc/cpuinfo although it is
638 claimed to be a regular file. */
639 num_bytes = 0;
640 file_buf_size = 1000;
641 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
642 while (42) {
643 n = VG_(read)(fh, file_buf, file_buf_size);
644 if (n < 0) break;
645
646 num_bytes += n;
647 if (n < file_buf_size) break; /* reached EOF */
648 }
649
650 if (n < 0) num_bytes = 0; /* read error; ignore contents */
651
652 if (num_bytes > file_buf_size) {
653 VG_(free)( file_buf );
654 VG_(lseek)( fh, 0, VKI_SEEK_SET );
655 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
656 n = VG_(read)( fh, file_buf, num_bytes );
657 if (n < 0) num_bytes = 0;
658 }
659
660 file_buf[num_bytes] = '\0';
661 VG_(close)(fh);
662
663 /* Parse file */
664 if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL)
665 return VEX_PRID_COMP_BROADCOM;
666 if (VG_(strstr) (file_buf, search_MIPS_str) != NULL)
667 return VEX_PRID_COMP_MIPS;
668
669 /* Did not find string in the proc file. */
670 return -1;
671}
672
673#endif
674
sewardj5ae70ce2010-09-08 15:12:33 +0000675/* Determine what insn set and insn set variant the host has, and
676 record it. To be called once at system startup. Returns False if
677 this a CPU incapable of running Valgrind. */
sewardje3826cf2005-11-13 00:30:22 +0000678
sewardje2d1e672005-11-12 23:10:48 +0000679Bool VG_(machine_get_hwcaps)( void )
680{
681 vg_assert(hwcaps_done == False);
682 hwcaps_done = True;
683
684 // Whack default settings into vai, so that we only need to fill in
685 // any interesting bits.
686 LibVEX_default_VexArchInfo(&vai);
687
688#if defined(VGA_x86)
sewardj40d91c72010-07-29 15:40:32 +0000689 { Bool have_sse1, have_sse2, have_cx8, have_lzcnt;
sewardjc7ffc942011-03-28 16:26:42 +0000690 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000691 UChar vstr[13];
692 vstr[0] = 0;
sewardje2d1e672005-11-12 23:10:48 +0000693
694 if (!VG_(has_cpuid)())
695 /* we can't do cpuid at all. Give up. */
696 return False;
697
tomad8a5912011-06-10 15:04:22 +0000698 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000699 if (eax < 1)
700 /* we can't ask for cpuid(x) for x > 0. Give up. */
701 return False;
702
sewardj40d91c72010-07-29 15:40:32 +0000703 /* Get processor ID string, and max basic/extended index
704 values. */
sewardj40d91c72010-07-29 15:40:32 +0000705 VG_(memcpy)(&vstr[0], &ebx, 4);
706 VG_(memcpy)(&vstr[4], &edx, 4);
707 VG_(memcpy)(&vstr[8], &ecx, 4);
708 vstr[12] = 0;
709
tomad8a5912011-06-10 15:04:22 +0000710 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000711 max_extended = eax;
712
sewardje2d1e672005-11-12 23:10:48 +0000713 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000714 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000715
716 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
717 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
718
sewardj1c0ce7a2009-07-01 08:10:49 +0000719 /* cmpxchg8b is a minimum requirement now; if we don't have it we
720 must simply give up. But all CPUs since Pentium-I have it, so
721 that doesn't seem like much of a restriction. */
722 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
723 if (!have_cx8)
724 return False;
725
sewardj40d91c72010-07-29 15:40:32 +0000726 /* Figure out if this is an AMD that can do LZCNT. */
727 have_lzcnt = False;
728 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
729 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000730 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000731 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
732 }
733
sewardje2d1e672005-11-12 23:10:48 +0000734 if (have_sse2 && have_sse1) {
735 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000736 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
737 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardj40d91c72010-07-29 15:40:32 +0000738 if (have_lzcnt)
739 vai.hwcaps |= VEX_HWCAPS_X86_LZCNT;
sewardje2d1e672005-11-12 23:10:48 +0000740 VG_(machine_x86_have_mxcsr) = 1;
741 return True;
742 }
743
744 if (have_sse1) {
745 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000746 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000747 VG_(machine_x86_have_mxcsr) = 1;
748 return True;
749 }
750
sewardje3121f32006-01-27 21:23:23 +0000751 va = VexArchX86;
752 vai.hwcaps = 0; /*baseline - no sse at all*/
sewardje2d1e672005-11-12 23:10:48 +0000753 VG_(machine_x86_have_mxcsr) = 0;
754 return True;
755 }
756
757#elif defined(VGA_amd64)
sewardjc7ffc942011-03-28 16:26:42 +0000758 { Bool have_sse3, have_cx8, have_cx16;
sewardjee1a8972012-04-26 14:17:50 +0000759 Bool have_lzcnt, have_avx /*, have_fma*/;
sewardjc7ffc942011-03-28 16:26:42 +0000760 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000761 UChar vstr[13];
762 vstr[0] = 0;
sewardj1c0ce7a2009-07-01 08:10:49 +0000763
764 if (!VG_(has_cpuid)())
765 /* we can't do cpuid at all. Give up. */
766 return False;
767
tomad8a5912011-06-10 15:04:22 +0000768 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000769 if (eax < 1)
770 /* we can't ask for cpuid(x) for x > 0. Give up. */
771 return False;
772
sewardj40d91c72010-07-29 15:40:32 +0000773 /* Get processor ID string, and max basic/extended index
774 values. */
sewardj40d91c72010-07-29 15:40:32 +0000775 VG_(memcpy)(&vstr[0], &ebx, 4);
776 VG_(memcpy)(&vstr[4], &edx, 4);
777 VG_(memcpy)(&vstr[8], &ecx, 4);
778 vstr[12] = 0;
779
tomad8a5912011-06-10 15:04:22 +0000780 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000781 max_extended = eax;
782
sewardj1c0ce7a2009-07-01 08:10:49 +0000783 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000784 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000785
sewardjc7ffc942011-03-28 16:26:42 +0000786 // we assume that SSE1 and SSE2 are available by default
sewardj598971e2009-07-12 13:19:04 +0000787 have_sse3 = (ecx & (1<<0)) != 0; /* True => have sse3 insns */
sewardjee1a8972012-04-26 14:17:50 +0000788 // ssse3 is ecx:9
789 // sse41 is ecx:19
790 // sse42 is ecx:20
791
792 // osxsave is ecx:27
793 // avx is ecx:28
794 // fma is ecx:12
795 have_avx = False;
796 /* have_fma = False; */
797 if ( (ecx & ((1<<27)|(1<<28))) == ((1<<27)|(1<<28)) ) {
798 /* processor supports AVX instructions and XGETBV is enabled
799 by OS */
800 ULong w;
801 __asm__ __volatile__("movq $0,%%rcx ; "
802 ".byte 0x0F,0x01,0xD0 ; " /* xgetbv */
803 "movq %%rax,%0"
804 :/*OUT*/"=r"(w) :/*IN*/
805 :/*TRASH*/"rdx","rcx");
806 if ((w & 6) == 6) {
807 /* OS has enabled both XMM and YMM state support */
808 have_avx = True;
809 /* have_fma = (ecx & (1<<12)) != 0; */
810 /* have_fma: Probably correct, but gcc complains due to
811 unusedness. &*/
812 }
813 }
814
sewardj1c0ce7a2009-07-01 08:10:49 +0000815
816 /* cmpxchg8b is a minimum requirement now; if we don't have it we
817 must simply give up. But all CPUs since Pentium-I have it, so
818 that doesn't seem like much of a restriction. */
819 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
820 if (!have_cx8)
821 return False;
822
823 /* on amd64 we tolerate older cpus, which don't have cmpxchg16b */
824 have_cx16 = (ecx & (1<<13)) != 0; /* True => have cmpxchg16b */
825
sewardj40d91c72010-07-29 15:40:32 +0000826 /* Figure out if this is an AMD that can do LZCNT. */
827 have_lzcnt = False;
828 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
829 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000830 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000831 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
832 }
833
sewardj1c0ce7a2009-07-01 08:10:49 +0000834 va = VexArchAMD64;
sewardjee1a8972012-04-26 14:17:50 +0000835 vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
836 | (have_cx16 ? VEX_HWCAPS_AMD64_CX16 : 0)
837 | (have_lzcnt ? VEX_HWCAPS_AMD64_LZCNT : 0)
838 | (have_avx ? VEX_HWCAPS_AMD64_AVX : 0);
sewardj1c0ce7a2009-07-01 08:10:49 +0000839 return True;
840 }
sewardje2d1e672005-11-12 23:10:48 +0000841
842#elif defined(VGA_ppc32)
bart1581e742009-01-13 07:49:14 +0000843 {
844 /* Find out which subset of the ppc32 instruction set is supported by
845 verifying whether various ppc32 instructions generate a SIGILL
846 or a SIGFPE. An alternative approach is to check the AT_HWCAP and
847 AT_PLATFORM entries in the ELF auxiliary table -- see also
848 the_iifii.client_auxv in m_main.c.
849 */
njncda2f0f2009-05-18 02:12:08 +0000850 vki_sigset_t saved_set, tmp_set;
851 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
852 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000853
sewardj5ba075a2012-04-02 21:25:14 +0000854 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
sewardj7637e9e2006-02-21 17:11:11 +0000855 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000856
njncda2f0f2009-05-18 02:12:08 +0000857 /* This is a kludge. Really we ought to back-convert saved_act
858 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
859 since that's a no-op on all ppc32 platforms so far supported,
860 it's not worth the typing effort. At least include most basic
861 sanity check: */
862 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
863
sewardje3826cf2005-11-13 00:30:22 +0000864 VG_(sigemptyset)(&tmp_set);
865 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000866 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardje3826cf2005-11-13 00:30:22 +0000867
sewardj7637e9e2006-02-21 17:11:11 +0000868 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
869 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000870
bart1581e742009-01-13 07:49:14 +0000871 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
sewardj7637e9e2006-02-21 17:11:11 +0000872 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000873 tmp_sigill_act = saved_sigill_act;
874
875 r = VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
876 vg_assert(r == 0);
877 tmp_sigfpe_act = saved_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000878
sewardj7637e9e2006-02-21 17:11:11 +0000879 /* NODEFER: signal handler does not return (from the kernel's point of
880 view), hence if it is to successfully catch a signal more than once,
881 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000882 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
883 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
884 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
885 tmp_sigill_act.ksa_handler = handler_unsup_insn;
886 r = VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
887 vg_assert(r == 0);
888
889 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
890 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
891 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
892 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
893 r = VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
894 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000895
sewardje3121f32006-01-27 21:23:23 +0000896 /* standard FP insns */
897 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000898 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000899 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000900 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000901 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000902 }
903
sewardje3121f32006-01-27 21:23:23 +0000904 /* Altivec insns */
905 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000906 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000907 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000908 } else {
sewardj71592122006-04-04 03:29:48 +0000909 /* Unfortunately some older assemblers don't speak Altivec (or
910 choose not to), so to be safe we directly emit the 32-bit
911 word corresponding to "vor 0,0,0". This fixes a build
912 problem that happens on Debian 3.1 (ppc32), and probably
913 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000914 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000915 }
916
sewardje3121f32006-01-27 21:23:23 +0000917 /* General-Purpose optional (fsqrt, fsqrts) */
918 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000919 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000920 have_FX = False;
921 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000922 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000923 }
924
925 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
926 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000927 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000928 have_GX = False;
929 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000930 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000931 }
932
sewardjf34eb492011-04-15 11:57:05 +0000933 /* VSX support implies Power ISA 2.06 */
934 have_VX = True;
935 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
936 have_VX = False;
937 } else {
938 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
939 }
940
sewardj5ba075a2012-04-02 21:25:14 +0000941 /* Check for Decimal Floating Point (DFP) support. */
942 have_DFP = True;
943 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
944 have_DFP = False;
945 } else {
946 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
947 }
sewardjf34eb492011-04-15 11:57:05 +0000948
sewardjb9c815b2010-09-03 15:51:34 +0000949 /* determine dcbz/dcbzl sizes while we still have the signal
950 * handlers registered */
951 find_ppc_dcbz_sz(&vai);
952
bart1581e742009-01-13 07:49:14 +0000953 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
954 vg_assert(r == 0);
955 r = VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj7637e9e2006-02-21 17:11:11 +0000956 vg_assert(r == 0);
957 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
958 vg_assert(r == 0);
sewardj5ba075a2012-04-02 21:25:14 +0000959 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +0000960 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +0000961 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +0000962 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
963 if (have_V && !have_F)
964 have_V = False;
965 if (have_FX && !have_F)
966 have_FX = False;
967 if (have_GX && !have_F)
968 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +0000969
sewardje3121f32006-01-27 21:23:23 +0000970 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
971 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000972
973 va = VexArchPPC32;
974
sewardje3121f32006-01-27 21:23:23 +0000975 vai.hwcaps = 0;
976 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
977 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
978 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
979 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardjf34eb492011-04-15 11:57:05 +0000980 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC32_VX;
sewardj5ba075a2012-04-02 21:25:14 +0000981 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC32_DFP;
982
sewardje3826cf2005-11-13 00:30:22 +0000983
984 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
985 called before we're ready to go. */
986 return True;
987 }
sewardje2d1e672005-11-12 23:10:48 +0000988
sewardj2c48c7b2005-11-29 13:05:56 +0000989#elif defined(VGA_ppc64)
bart1581e742009-01-13 07:49:14 +0000990 {
991 /* Same instruction set detection algorithm as for ppc32. */
njncda2f0f2009-05-18 02:12:08 +0000992 vki_sigset_t saved_set, tmp_set;
993 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
994 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardj2c48c7b2005-11-29 13:05:56 +0000995
sewardj5ba075a2012-04-02 21:25:14 +0000996 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
njncda2f0f2009-05-18 02:12:08 +0000997 Int r;
998
999 /* This is a kludge. Really we ought to back-convert saved_act
1000 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1001 since that's a no-op on all ppc64 platforms so far supported,
1002 it's not worth the typing effort. At least include most basic
1003 sanity check: */
1004 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
sewardj2c48c7b2005-11-29 13:05:56 +00001005
1006 VG_(sigemptyset)(&tmp_set);
1007 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +00001008 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardj2c48c7b2005-11-29 13:05:56 +00001009
njncda2f0f2009-05-18 02:12:08 +00001010 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1011 vg_assert(r == 0);
sewardj2c48c7b2005-11-29 13:05:56 +00001012
njncda2f0f2009-05-18 02:12:08 +00001013 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1014 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +00001015 tmp_sigill_act = saved_sigill_act;
1016
1017 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1018 tmp_sigfpe_act = saved_sigfpe_act;
1019
sewardj7637e9e2006-02-21 17:11:11 +00001020 /* NODEFER: signal handler does not return (from the kernel's point of
1021 view), hence if it is to successfully catch a signal more than once,
1022 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +00001023 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1024 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1025 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1026 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1027 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1028
1029 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1030 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1031 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1032 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1033 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001034
sewardje3121f32006-01-27 21:23:23 +00001035 /* standard FP insns */
1036 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +00001037 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001038 have_F = False;
1039 } else {
1040 __asm__ __volatile__("fmr 0,0");
1041 }
1042
1043 /* Altivec insns */
1044 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +00001045 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001046 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +00001047 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001048 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +00001049 }
1050
sewardje3121f32006-01-27 21:23:23 +00001051 /* General-Purpose optional (fsqrt, fsqrts) */
1052 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +00001053 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001054 have_FX = False;
1055 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001056 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001057 }
1058
1059 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
1060 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +00001061 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001062 have_GX = False;
1063 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001064 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001065 }
1066
sewardjf34eb492011-04-15 11:57:05 +00001067 /* VSX support implies Power ISA 2.06 */
1068 have_VX = True;
1069 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1070 have_VX = False;
1071 } else {
1072 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
1073 }
1074
sewardj5ba075a2012-04-02 21:25:14 +00001075 /* Check for Decimal Floating Point (DFP) support. */
1076 have_DFP = True;
1077 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1078 have_DFP = False;
1079 } else {
1080 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
1081 }
1082
sewardjb9c815b2010-09-03 15:51:34 +00001083 /* determine dcbz/dcbzl sizes while we still have the signal
1084 * handlers registered */
1085 find_ppc_dcbz_sz(&vai);
1086
bart1581e742009-01-13 07:49:14 +00001087 VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1088 VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001089 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
sewardj5ba075a2012-04-02 21:25:14 +00001090 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +00001091 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +00001092 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +00001093 /* on ppc64, if we don't even have FP, just give up. */
1094 if (!have_F)
1095 return False;
1096
1097 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +00001098
1099 va = VexArchPPC64;
sewardje3121f32006-01-27 21:23:23 +00001100
1101 vai.hwcaps = 0;
1102 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
1103 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
1104 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardjf34eb492011-04-15 11:57:05 +00001105 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC64_VX;
sewardj5ba075a2012-04-02 21:25:14 +00001106 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC64_DFP;
sewardj2c48c7b2005-11-29 13:05:56 +00001107
1108 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
1109 called before we're ready to go. */
1110 return True;
1111 }
1112
sewardjb5b87402011-03-07 16:05:35 +00001113#elif defined(VGA_s390x)
1114 {
1115 /* Instruction set detection code borrowed from ppc above. */
1116 vki_sigset_t saved_set, tmp_set;
1117 vki_sigaction_fromK_t saved_sigill_act;
1118 vki_sigaction_toK_t tmp_sigill_act;
1119
sewardj1c6f6ab2011-04-27 12:00:51 +00001120 volatile Bool have_LDISP, have_EIMM, have_GIE, have_DFP, have_FGX;
florian370bc772012-08-30 20:30:32 +00001121 volatile Bool have_STFLE, have_ETF2, have_ETF3, have_STCKF, have_FPEXT;
sewardj2c3f2ea2011-04-13 15:40:10 +00001122 Int r, model;
sewardjb5b87402011-03-07 16:05:35 +00001123
1124 /* Unblock SIGILL and stash away the old action for that signal */
1125 VG_(sigemptyset)(&tmp_set);
1126 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1127
1128 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1129 vg_assert(r == 0);
1130
1131 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1132 vg_assert(r == 0);
1133 tmp_sigill_act = saved_sigill_act;
1134
1135 /* NODEFER: signal handler does not return (from the kernel's point of
1136 view), hence if it is to successfully catch a signal more than once,
1137 we need the NODEFER flag. */
1138 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1139 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1140 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1141 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1142 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1143
1144 /* Determine hwcaps. Note, we cannot use the stfle insn because it
1145 is not supported on z900. */
1146
1147 have_LDISP = True;
sewardj6c591e12011-04-11 16:17:51 +00001148 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001149 have_LDISP = False;
1150 } else {
1151 /* BASR loads the address of the next insn into r1. Needed to avoid
1152 a segfault in XY. */
1153 __asm__ __volatile__("basr %%r1,%%r0\n\t"
1154 ".long 0xe3001000\n\t" /* XY 0,0(%r1) */
1155 ".short 0x0057" : : : "r0", "r1", "cc", "memory");
1156 }
1157
1158 have_EIMM = True;
sewardj6c591e12011-04-11 16:17:51 +00001159 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001160 have_EIMM = False;
1161 } else {
1162 __asm__ __volatile__(".long 0xc0090000\n\t" /* iilf r0,0 */
1163 ".short 0x0000" : : : "r0", "memory");
1164 }
1165
1166 have_GIE = True;
sewardj6c591e12011-04-11 16:17:51 +00001167 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001168 have_GIE = False;
1169 } else {
1170 __asm__ __volatile__(".long 0xc2010000\n\t" /* msfi r0,0 */
1171 ".short 0x0000" : : : "r0", "memory");
1172 }
1173
1174 have_DFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001175 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001176 have_DFP = False;
1177 } else {
1178 __asm__ __volatile__(".long 0xb3d20000"
1179 : : : "r0", "cc", "memory"); /* adtr r0,r0,r0 */
1180 }
1181
sewardj1c6f6ab2011-04-27 12:00:51 +00001182 have_FGX = True;
1183 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1184 have_FGX = False;
1185 } else {
1186 __asm__ __volatile__(".long 0xb3cd0000" : : : "r0"); /* lgdr r0,f0 */
1187 }
1188
florian833ffd02012-08-26 04:23:08 +00001189 /* Detect presence of certain facilities using the STFLE insn.
1190 Note, that these facilities were introduced at the same time or later
1191 as STFLE, so the absence of STLFE implies the absence of the facility
1192 we're trying to detect. */
floriand19733c2012-01-15 21:02:44 +00001193 have_STFLE = True;
1194 have_ETF2 = False;
floriane3d028c2012-05-03 01:31:24 +00001195 have_ETF3 = False;
florian833ffd02012-08-26 04:23:08 +00001196 have_STCKF = False;
floriane9685912012-09-01 23:48:09 +00001197 have_FPEXT = False;
floriand19733c2012-01-15 21:02:44 +00001198 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1199 have_STFLE = False;
1200 } else {
1201 ULong hoststfle[1];
1202 register ULong reg0 asm("0") = 0; /* one double word available */
1203
1204 __asm__ __volatile__(" .insn s,0xb2b00000,%0\n" /* stfle */
1205 : "=m" (hoststfle), "+d"(reg0)
1206 : : "cc", "memory");
1207 if (hoststfle[0] & (1ULL << (63 - 24)))
1208 have_ETF2 = True;
floriane3d028c2012-05-03 01:31:24 +00001209 if (hoststfle[0] & (1ULL << (63 - 30)))
1210 have_ETF3 = True;
florian833ffd02012-08-26 04:23:08 +00001211 if (hoststfle[0] & (1ULL << (63 - 25)))
1212 have_STCKF = True;
florian370bc772012-08-30 20:30:32 +00001213 if (hoststfle[0] & (1ULL << (63 - 37)))
1214 have_FPEXT = True;
floriand19733c2012-01-15 21:02:44 +00001215 }
1216
sewardjb5b87402011-03-07 16:05:35 +00001217 /* Restore signals */
1218 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1219 vg_assert(r == 0);
1220 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1221 vg_assert(r == 0);
sewardjb5b87402011-03-07 16:05:35 +00001222 va = VexArchS390X;
1223
sewardj2c3f2ea2011-04-13 15:40:10 +00001224 model = VG_(get_machine_model)();
1225
florian4e63b8e2012-04-22 03:50:20 +00001226 /* If the model is "unknown" don't treat this as an error. Assume
1227 this is a brand-new machine model for which we don't have the
1228 identification yet. Keeping fingers crossed. */
1229
sewardj1c6f6ab2011-04-27 12:00:51 +00001230 VG_(debugLog)(1, "machine", "machine %d LDISP %d EIMM %d GIE %d DFP %d "
florian833ffd02012-08-26 04:23:08 +00001231 "FGX %d STFLE %d ETF2 %d ETF3 %d STCKF %d\n",
1232 model, have_LDISP, have_EIMM, have_GIE, have_DFP, have_FGX,
1233 have_STFLE, have_ETF2, have_ETF3, have_STCKF);
sewardj2c3f2ea2011-04-13 15:40:10 +00001234
sewardj2c3f2ea2011-04-13 15:40:10 +00001235 vai.hwcaps = model;
1236 if (have_LDISP) {
1237 /* Use long displacement only on machines >= z990. For all other machines
1238 it is millicoded and therefore slow. */
1239 if (model >= VEX_S390X_MODEL_Z990)
1240 vai.hwcaps |= VEX_HWCAPS_S390X_LDISP;
1241 }
sewardjb5b87402011-03-07 16:05:35 +00001242 if (have_EIMM) vai.hwcaps |= VEX_HWCAPS_S390X_EIMM;
1243 if (have_GIE) vai.hwcaps |= VEX_HWCAPS_S390X_GIE;
1244 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_S390X_DFP;
sewardj1c6f6ab2011-04-27 12:00:51 +00001245 if (have_FGX) vai.hwcaps |= VEX_HWCAPS_S390X_FGX;
floriand19733c2012-01-15 21:02:44 +00001246 if (have_ETF2) vai.hwcaps |= VEX_HWCAPS_S390X_ETF2;
floriane3d028c2012-05-03 01:31:24 +00001247 if (have_ETF3) vai.hwcaps |= VEX_HWCAPS_S390X_ETF3;
florian68aba522012-04-21 15:43:25 +00001248 if (have_STFLE) vai.hwcaps |= VEX_HWCAPS_S390X_STFLE;
florian833ffd02012-08-26 04:23:08 +00001249 if (have_STCKF) vai.hwcaps |= VEX_HWCAPS_S390X_STCKF;
florian370bc772012-08-30 20:30:32 +00001250 if (have_FPEXT) vai.hwcaps |= VEX_HWCAPS_S390X_FPEXT;
sewardjb5b87402011-03-07 16:05:35 +00001251
sewardj2c3f2ea2011-04-13 15:40:10 +00001252 VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
1253
sewardjb5b87402011-03-07 16:05:35 +00001254 return True;
1255 }
1256
sewardj59570ff2010-01-01 11:59:33 +00001257#elif defined(VGA_arm)
1258 {
sewardj1dbd3372010-08-22 12:21:14 +00001259 /* Same instruction set detection algorithm as for ppc32. */
1260 vki_sigset_t saved_set, tmp_set;
1261 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
1262 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
1263
1264 volatile Bool have_VFP, have_VFP2, have_VFP3, have_NEON;
1265 volatile Int archlevel;
1266 Int r;
1267
1268 /* This is a kludge. Really we ought to back-convert saved_act
1269 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1270 since that's a no-op on all ppc64 platforms so far supported,
1271 it's not worth the typing effort. At least include most basic
1272 sanity check: */
1273 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
1274
1275 VG_(sigemptyset)(&tmp_set);
1276 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1277 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
1278
1279 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1280 vg_assert(r == 0);
1281
1282 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1283 vg_assert(r == 0);
1284 tmp_sigill_act = saved_sigill_act;
1285
1286 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1287 tmp_sigfpe_act = saved_sigfpe_act;
1288
1289 /* NODEFER: signal handler does not return (from the kernel's point of
1290 view), hence if it is to successfully catch a signal more than once,
1291 we need the NODEFER flag. */
1292 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1293 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1294 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1295 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1296 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1297
1298 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1299 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1300 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1301 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1302 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1303
1304 /* VFP insns */
1305 have_VFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001306 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001307 have_VFP = False;
1308 } else {
1309 __asm__ __volatile__(".word 0xEEB02B42"); /* VMOV.F64 d2, d2 */
1310 }
1311 /* There are several generation of VFP extension but they differs very
1312 little so for now we will not distinguish them. */
1313 have_VFP2 = have_VFP;
1314 have_VFP3 = have_VFP;
1315
1316 /* NEON insns */
1317 have_NEON = True;
sewardj6c591e12011-04-11 16:17:51 +00001318 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001319 have_NEON = False;
1320 } else {
1321 __asm__ __volatile__(".word 0xF2244154"); /* VMOV q2, q2 */
1322 }
1323
1324 /* ARM architecture level */
1325 archlevel = 5; /* v5 will be base level */
1326 if (archlevel < 7) {
1327 archlevel = 7;
sewardj6c591e12011-04-11 16:17:51 +00001328 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001329 archlevel = 5;
1330 } else {
1331 __asm__ __volatile__(".word 0xF45FF000"); /* PLI [PC,#-0] */
1332 }
1333 }
1334 if (archlevel < 6) {
1335 archlevel = 6;
sewardj6c591e12011-04-11 16:17:51 +00001336 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001337 archlevel = 5;
1338 } else {
1339 __asm__ __volatile__(".word 0xE6822012"); /* PKHBT r2, r2, r2 */
1340 }
1341 }
1342
1343 VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
1344 VG_(convert_sigaction_fromK_to_toK)(&saved_sigfpe_act, &tmp_sigfpe_act);
1345 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1346 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1347 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1348
1349 VG_(debugLog)(1, "machine", "ARMv%d VFP %d VFP2 %d VFP3 %d NEON %d\n",
1350 archlevel, (Int)have_VFP, (Int)have_VFP2, (Int)have_VFP3,
1351 (Int)have_NEON);
1352
1353 VG_(machine_arm_archlevel) = archlevel;
1354
sewardj59570ff2010-01-01 11:59:33 +00001355 va = VexArchARM;
sewardj1dbd3372010-08-22 12:21:14 +00001356
1357 vai.hwcaps = VEX_ARM_ARCHLEVEL(archlevel);
1358 if (have_VFP3) vai.hwcaps |= VEX_HWCAPS_ARM_VFP3;
1359 if (have_VFP2) vai.hwcaps |= VEX_HWCAPS_ARM_VFP2;
1360 if (have_VFP) vai.hwcaps |= VEX_HWCAPS_ARM_VFP;
1361 if (have_NEON) vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1362
sewardj59570ff2010-01-01 11:59:33 +00001363 return True;
1364 }
1365
sewardj5db15402012-06-07 09:13:21 +00001366#elif defined(VGA_mips32)
1367 {
1368 va = VexArchMIPS32;
1369 UInt model = VG_(get_machine_model)();
1370 if (model== -1)
1371 return False;
1372
1373 vai.hwcaps = model;
1374 return True;
1375 }
1376
sewardje2d1e672005-11-12 23:10:48 +00001377#else
1378# error "Unknown arch"
1379#endif
1380}
1381
sewardj2c48c7b2005-11-29 13:05:56 +00001382/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +00001383#if defined(VGA_ppc32)
1384void VG_(machine_ppc32_set_clszB)( Int szB )
1385{
1386 vg_assert(hwcaps_done);
1387
1388 /* Either the value must not have been set yet (zero) or we can
1389 tolerate it being set to the same value multiple times, as the
1390 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001391 vg_assert(vai.ppc_cache_line_szB == 0
1392 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +00001393
sewardj89230ca2008-05-29 16:39:57 +00001394 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001395 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +00001396}
1397#endif
1398
sewardje2d1e672005-11-12 23:10:48 +00001399
sewardj2c48c7b2005-11-29 13:05:56 +00001400/* Notify host cpu cache line size. */
1401#if defined(VGA_ppc64)
1402void VG_(machine_ppc64_set_clszB)( Int szB )
1403{
1404 vg_assert(hwcaps_done);
1405
1406 /* Either the value must not have been set yet (zero) or we can
1407 tolerate it being set to the same value multiple times, as the
1408 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001409 vg_assert(vai.ppc_cache_line_szB == 0
1410 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +00001411
sewardj89230ca2008-05-29 16:39:57 +00001412 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001413 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +00001414}
1415#endif
1416
1417
sewardja3551be2010-09-09 07:25:58 +00001418/* Notify host's ability to handle NEON instructions. */
1419#if defined(VGA_arm)
1420void VG_(machine_arm_set_has_NEON)( Bool has_neon )
1421{
1422 vg_assert(hwcaps_done);
1423 /* There's nothing else we can sanity check. */
1424
1425 if (has_neon) {
1426 vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1427 } else {
1428 vai.hwcaps &= ~VEX_HWCAPS_ARM_NEON;
1429 }
1430}
1431#endif
1432
1433
sewardje2d1e672005-11-12 23:10:48 +00001434/* Fetch host cpu info, once established. */
1435void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
1436 /*OUT*/VexArchInfo* pVai )
1437{
1438 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +00001439 if (pVa) *pVa = va;
1440 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +00001441}
sewardj7821e2e2005-08-08 00:35:46 +00001442
1443
sewardj98763d52012-06-03 22:40:07 +00001444/* Returns the size of the largest guest register that we will
1445 simulate in this run. This depends on both the guest architecture
1446 and on the specific capabilities we are simulating for that guest
1447 (eg, AVX or non-AVX ?, for amd64). Should return either 4, 8, 16
1448 or 32. General rule: if in doubt, return a value larger than
1449 reality.
1450
1451 This information is needed by Cachegrind and Callgrind to decide
1452 what the minimum cache line size they are prepared to simulate is.
1453 Basically require that the minimum cache line size is at least as
1454 large as the largest register that might get transferred to/from
1455 memory, so as to guarantee that any such transaction can straddle
1456 at most 2 cache lines.
1457*/
1458Int VG_(machine_get_size_of_largest_guest_register) ( void )
1459{
1460 vg_assert(hwcaps_done);
1461 /* Once hwcaps_done is True, we can fish around inside va/vai to
1462 find the information we need. */
1463
1464# if defined(VGA_x86)
1465 vg_assert(va == VexArchX86);
1466 /* We don't support AVX, so 32 is out. At the other end, even if
1467 we don't support any SSE, the X87 can generate 10 byte
1468 transfers, so let's say 16 to be on the safe side. Hence the
1469 answer is always 16. */
1470 return 16;
1471
1472# elif defined(VGA_amd64)
1473 /* if AVX then 32 else 16 */
1474 return (vai.hwcaps & VEX_HWCAPS_AMD64_AVX) ? 32 : 16;
1475
1476# elif defined(VGA_ppc32)
1477 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1478 if (vai.hwcaps & VEX_HWCAPS_PPC32_V) return 16;
1479 if (vai.hwcaps & VEX_HWCAPS_PPC32_VX) return 16;
1480 if (vai.hwcaps & VEX_HWCAPS_PPC32_DFP) return 16;
1481 return 8;
1482
1483# elif defined(VGA_ppc64)
1484 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1485 if (vai.hwcaps & VEX_HWCAPS_PPC64_V) return 16;
1486 if (vai.hwcaps & VEX_HWCAPS_PPC64_VX) return 16;
1487 if (vai.hwcaps & VEX_HWCAPS_PPC64_DFP) return 16;
1488 return 8;
1489
1490# elif defined(VGA_s390x)
1491 return 8;
1492
1493# elif defined(VGA_arm)
1494 /* Really it depends whether or not we have NEON, but let's just
1495 assume we always do. */
1496 return 16;
1497
sewardj5db15402012-06-07 09:13:21 +00001498# elif defined(VGA_mips32)
1499 /* The guest state implies 4, but that can't really be true, can
1500 it? */
1501 return 8;
1502
sewardj98763d52012-06-03 22:40:07 +00001503# else
1504# error "Unknown arch"
1505# endif
1506}
1507
1508
sewardj53ee1fc2005-12-23 02:29:58 +00001509// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +00001510// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +00001511void* VG_(fnptr_to_fnentry)( void* f )
1512{
sewardj6e9de462011-06-28 07:25:29 +00001513# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
1514 || defined(VGP_arm_linux) \
1515 || defined(VGP_ppc32_linux) || defined(VGO_darwin) \
sewardj5db15402012-06-07 09:13:21 +00001516 || defined(VGP_s390x_linux) || defined(VGP_mips32_linux)
sewardj53ee1fc2005-12-23 02:29:58 +00001517 return f;
sewardj6e9de462011-06-28 07:25:29 +00001518# elif defined(VGP_ppc64_linux)
1519 /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
1520 3-word function descriptor, of which the first word is the entry
1521 address. */
sewardjf1c91e02006-10-17 01:35:58 +00001522 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +00001523 return (void*)(descr[0]);
sewardj6e9de462011-06-28 07:25:29 +00001524# else
1525# error "Unknown platform"
1526# endif
sewardj53ee1fc2005-12-23 02:29:58 +00001527}
1528
njnf536bbb2005-06-13 04:21:38 +00001529/*--------------------------------------------------------------------*/
1530/*--- end ---*/
1531/*--------------------------------------------------------------------*/