blob: 8c3816808ec3fb579b04e09f7e7596bdc24b7947 [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
sewardj9eecbbb2010-05-03 21:37:12 +00009 Copyright (C) 2000-2010 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;
sewardj59570ff2010-01-01 11:59:33 +0000106# else
107# error "Unknown arch"
108# endif
109}
110
111
sewardj9c606bd2008-09-18 18:12:50 +0000112void VG_(set_syscall_return_shadows) ( ThreadId tid,
113 /* shadow vals for the result */
114 UWord s1res, UWord s2res,
115 /* shadow vals for the error val */
116 UWord s1err, UWord s2err )
117{
118# if defined(VGP_x86_linux)
119 VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res;
120 VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res;
121# elif defined(VGP_amd64_linux)
122 VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res;
123 VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res;
124# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
125 VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
126 VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
sewardj59570ff2010-01-01 11:59:33 +0000127# elif defined(VGP_arm_linux)
128 VG_(threads)[tid].arch.vex_shadow1.guest_R0 = s1res;
129 VG_(threads)[tid].arch.vex_shadow2.guest_R0 = s2res;
sewardj9c606bd2008-09-18 18:12:50 +0000130# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
131 VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
132 VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
133 VG_(threads)[tid].arch.vex_shadow1.guest_GPR4 = s1err;
134 VG_(threads)[tid].arch.vex_shadow2.guest_GPR4 = s2err;
njnf76d27a2009-05-28 01:53:07 +0000135# elif defined(VGO_darwin)
136 // GrP fixme darwin syscalls may return more values (2 registers plus error)
sewardjb5b87402011-03-07 16:05:35 +0000137# elif defined(VGP_s390x_linux)
138 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
139 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj9c606bd2008-09-18 18:12:50 +0000140# else
141# error "Unknown plat"
142# endif
143}
njnf536bbb2005-06-13 04:21:38 +0000144
sewardj7cf4e6b2008-05-01 20:24:26 +0000145void
146VG_(get_shadow_regs_area) ( ThreadId tid,
147 /*DST*/UChar* dst,
njnc4431bf2009-01-15 21:29:24 +0000148 /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size )
njnf536bbb2005-06-13 04:21:38 +0000149{
sewardj7cf4e6b2008-05-01 20:24:26 +0000150 void* src;
njnf536bbb2005-06-13 04:21:38 +0000151 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000152 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000153 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000154 // Bounds check
155 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
156 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000157 // Copy
158 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000159 src = NULL;
160 switch (shadowNo) {
161 case 0: src = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
162 case 1: src = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
163 case 2: src = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
164 }
165 tl_assert(src != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000166 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000167}
168
sewardj7cf4e6b2008-05-01 20:24:26 +0000169void
170VG_(set_shadow_regs_area) ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +0000171 /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
sewardj7cf4e6b2008-05-01 20:24:26 +0000172 /*SRC*/const UChar* src )
njnf536bbb2005-06-13 04:21:38 +0000173{
sewardj7cf4e6b2008-05-01 20:24:26 +0000174 void* dst;
njnf536bbb2005-06-13 04:21:38 +0000175 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000176 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000177 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000178 // Bounds check
179 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
180 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000181 // Copy
182 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000183 dst = NULL;
184 switch (shadowNo) {
185 case 0: dst = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
186 case 1: dst = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
187 case 2: dst = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
188 }
189 tl_assert(dst != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000190 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000191}
192
193
njn6ace3ea2005-06-17 03:06:27 +0000194static void apply_to_GPs_of_tid(VexGuestArchState* vex, void (*f)(Addr))
195{
196#if defined(VGA_x86)
197 (*f)(vex->guest_EAX);
198 (*f)(vex->guest_ECX);
199 (*f)(vex->guest_EDX);
200 (*f)(vex->guest_EBX);
201 (*f)(vex->guest_ESI);
202 (*f)(vex->guest_EDI);
203 (*f)(vex->guest_ESP);
204 (*f)(vex->guest_EBP);
205#elif defined(VGA_amd64)
206 (*f)(vex->guest_RAX);
207 (*f)(vex->guest_RCX);
208 (*f)(vex->guest_RDX);
209 (*f)(vex->guest_RBX);
210 (*f)(vex->guest_RSI);
211 (*f)(vex->guest_RDI);
212 (*f)(vex->guest_RSP);
213 (*f)(vex->guest_RBP);
214 (*f)(vex->guest_R8);
215 (*f)(vex->guest_R9);
216 (*f)(vex->guest_R10);
217 (*f)(vex->guest_R11);
218 (*f)(vex->guest_R12);
219 (*f)(vex->guest_R13);
220 (*f)(vex->guest_R14);
221 (*f)(vex->guest_R15);
sewardj2c48c7b2005-11-29 13:05:56 +0000222#elif defined(VGA_ppc32) || defined(VGA_ppc64)
cerion85665ca2005-06-20 15:51:07 +0000223 (*f)(vex->guest_GPR0);
224 (*f)(vex->guest_GPR1);
225 (*f)(vex->guest_GPR2);
226 (*f)(vex->guest_GPR3);
227 (*f)(vex->guest_GPR4);
228 (*f)(vex->guest_GPR5);
229 (*f)(vex->guest_GPR6);
230 (*f)(vex->guest_GPR7);
231 (*f)(vex->guest_GPR8);
232 (*f)(vex->guest_GPR9);
233 (*f)(vex->guest_GPR10);
234 (*f)(vex->guest_GPR11);
235 (*f)(vex->guest_GPR12);
236 (*f)(vex->guest_GPR13);
237 (*f)(vex->guest_GPR14);
238 (*f)(vex->guest_GPR15);
239 (*f)(vex->guest_GPR16);
240 (*f)(vex->guest_GPR17);
241 (*f)(vex->guest_GPR18);
242 (*f)(vex->guest_GPR19);
243 (*f)(vex->guest_GPR20);
244 (*f)(vex->guest_GPR21);
245 (*f)(vex->guest_GPR22);
246 (*f)(vex->guest_GPR23);
247 (*f)(vex->guest_GPR24);
248 (*f)(vex->guest_GPR25);
249 (*f)(vex->guest_GPR26);
250 (*f)(vex->guest_GPR27);
251 (*f)(vex->guest_GPR28);
252 (*f)(vex->guest_GPR29);
253 (*f)(vex->guest_GPR30);
254 (*f)(vex->guest_GPR31);
255 (*f)(vex->guest_CTR);
256 (*f)(vex->guest_LR);
sewardj59570ff2010-01-01 11:59:33 +0000257#elif defined(VGA_arm)
258 (*f)(vex->guest_R0);
259 (*f)(vex->guest_R1);
260 (*f)(vex->guest_R2);
261 (*f)(vex->guest_R3);
262 (*f)(vex->guest_R4);
263 (*f)(vex->guest_R5);
264 (*f)(vex->guest_R6);
265 (*f)(vex->guest_R8);
266 (*f)(vex->guest_R9);
267 (*f)(vex->guest_R10);
268 (*f)(vex->guest_R11);
269 (*f)(vex->guest_R12);
270 (*f)(vex->guest_R13);
271 (*f)(vex->guest_R14);
sewardjb5b87402011-03-07 16:05:35 +0000272#elif defined(VGA_s390x)
273 (*f)(vex->guest_r0);
274 (*f)(vex->guest_r1);
275 (*f)(vex->guest_r2);
276 (*f)(vex->guest_r3);
277 (*f)(vex->guest_r4);
278 (*f)(vex->guest_r5);
279 (*f)(vex->guest_r6);
280 (*f)(vex->guest_r7);
281 (*f)(vex->guest_r8);
282 (*f)(vex->guest_r9);
283 (*f)(vex->guest_r10);
284 (*f)(vex->guest_r11);
285 (*f)(vex->guest_r12);
286 (*f)(vex->guest_r13);
287 (*f)(vex->guest_r14);
288 (*f)(vex->guest_r15);
njn6ace3ea2005-06-17 03:06:27 +0000289#else
290# error Unknown arch
291#endif
292}
293
294
295void VG_(apply_to_GP_regs)(void (*f)(UWord))
296{
297 ThreadId tid;
298
299 for (tid = 1; tid < VG_N_THREADS; tid++) {
300 if (VG_(is_valid_tid)(tid)) {
301 ThreadState* tst = VG_(get_ThreadState)(tid);
302 apply_to_GPs_of_tid(&(tst->arch.vex), f);
303 }
304 }
305}
306
sewardjb8b79ad2008-03-03 01:35:41 +0000307void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
njnb506bd82005-06-21 04:01:51 +0000308{
sewardjb8b79ad2008-03-03 01:35:41 +0000309 *tid = (ThreadId)(-1);
njnb506bd82005-06-21 04:01:51 +0000310}
njn6ace3ea2005-06-17 03:06:27 +0000311
sewardjb8b79ad2008-03-03 01:35:41 +0000312Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
313 /*OUT*/Addr* stack_min,
314 /*OUT*/Addr* stack_max)
njn1d0cb0d2005-08-15 01:52:02 +0000315{
316 ThreadId i;
sewardjb8b79ad2008-03-03 01:35:41 +0000317 for (i = (*tid)+1; i < VG_N_THREADS; i++) {
318 if (i == VG_INVALID_THREADID)
319 continue;
njn1d0cb0d2005-08-15 01:52:02 +0000320 if (VG_(threads)[i].status != VgTs_Empty) {
321 *tid = i;
322 *stack_min = VG_(get_SP)(i);
323 *stack_max = VG_(threads)[i].client_stack_highest_word;
njn1d0cb0d2005-08-15 01:52:02 +0000324 return True;
325 }
326 }
327 return False;
328}
sewardj7821e2e2005-08-08 00:35:46 +0000329
sewardjbbec7722007-11-25 14:08:53 +0000330Addr VG_(thread_get_stack_max)(ThreadId tid)
331{
332 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
333 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
334 return VG_(threads)[tid].client_stack_highest_word;
335}
336
bart0fb03202008-03-29 09:25:53 +0000337SizeT VG_(thread_get_stack_size)(ThreadId tid)
338{
339 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
340 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
341 return VG_(threads)[tid].client_stack_szB;
342}
343
bart83c5a922010-09-02 14:38:38 +0000344Addr VG_(thread_get_altstack_min)(ThreadId tid)
345{
346 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
347 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
348 return (Addr)VG_(threads)[tid].altstack.ss_sp;
349}
350
351SizeT VG_(thread_get_altstack_size)(ThreadId tid)
352{
353 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
354 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
355 return VG_(threads)[tid].altstack.ss_size;
356}
357
sewardje2d1e672005-11-12 23:10:48 +0000358//-------------------------------------------------------------
359/* Details about the capabilities of the underlying (host) CPU. These
360 details are acquired by (1) enquiring with the CPU at startup, or
361 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
362 line size). It's a bit nasty in the sense that there's no obvious
363 way to stop uses of some of this info before it's ready to go.
sewardj10f08cf2005-06-29 10:16:14 +0000364
sewardje2d1e672005-11-12 23:10:48 +0000365 Current dependencies are:
sewardja48a4932005-09-29 11:09:56 +0000366
sewardje2d1e672005-11-12 23:10:48 +0000367 x86: initially: call VG_(machine_get_hwcaps)
sewardj10f08cf2005-06-29 10:16:14 +0000368
sewardje2d1e672005-11-12 23:10:48 +0000369 then safe to use VG_(machine_get_VexArchInfo)
370 and VG_(machine_x86_have_mxcsr)
371 -------------
372 amd64: initially: call VG_(machine_get_hwcaps)
373
374 then safe to use VG_(machine_get_VexArchInfo)
375 -------------
376 ppc32: initially: call VG_(machine_get_hwcaps)
377 call VG_(machine_ppc32_set_clszB)
378
379 then safe to use VG_(machine_get_VexArchInfo)
sewardj2c36d422005-11-13 01:59:22 +0000380 and VG_(machine_ppc32_has_FP)
sewardje2d1e672005-11-12 23:10:48 +0000381 and VG_(machine_ppc32_has_VMX)
cerion1f0d8142005-12-23 00:57:03 +0000382 -------------
383 ppc64: initially: call VG_(machine_get_hwcaps)
384 call VG_(machine_ppc64_set_clszB)
385
386 then safe to use VG_(machine_get_VexArchInfo)
387 and VG_(machine_ppc64_has_VMX)
sewardje2d1e672005-11-12 23:10:48 +0000388
sewardjb5b87402011-03-07 16:05:35 +0000389 -------------
390 s390x: initially: call VG_(machine_get_hwcaps)
391
392 then safe to use VG_(machine_get_VexArchInfo)
393
sewardje2d1e672005-11-12 23:10:48 +0000394 VG_(machine_get_hwcaps) may use signals (although it attempts to
395 leave signal state unchanged) and therefore should only be
396 called before m_main sets up the client's signal state.
397*/
398
399/* --------- State --------- */
sewardj59570ff2010-01-01 11:59:33 +0000400static Bool hwcaps_done = False;
sewardje2d1e672005-11-12 23:10:48 +0000401
402/* --- all archs --- */
403static VexArch va;
404static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000405
sewardj7821e2e2005-08-08 00:35:46 +0000406#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000407UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000408#endif
sewardje2d1e672005-11-12 23:10:48 +0000409#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000410UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000411UInt VG_(machine_ppc32_has_VMX) = 0;
412#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000413#if defined(VGA_ppc64)
414ULong VG_(machine_ppc64_has_VMX) = 0;
415#endif
sewardj1dbd3372010-08-22 12:21:14 +0000416#if defined(VGA_arm)
417Int VG_(machine_arm_archlevel) = 4;
418#endif
sewardje2d1e672005-11-12 23:10:48 +0000419
sewardjb5b87402011-03-07 16:05:35 +0000420/* fixs390: anything for s390x here ? */
sewardje2d1e672005-11-12 23:10:48 +0000421
sewardj2c3f2ea2011-04-13 15:40:10 +0000422/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
sewardj6c591e12011-04-11 16:17:51 +0000423 testing, so we need a VG_MINIMAL_JMP_BUF. */
424#if defined(VGA_ppc32) || defined(VGA_ppc64) \
425 || defined(VGA_arm) || defined(VGA_s390x)
426#include "pub_tool_libcsetjmp.h"
sewardj97d3ebb2011-04-11 18:36:34 +0000427static VG_MINIMAL_JMP_BUF(env_unsup_insn);
sewardj6c591e12011-04-11 16:17:51 +0000428static void handler_unsup_insn ( Int x ) {
429 VG_MINIMAL_LONGJMP(env_unsup_insn);
430}
sewardj5ae70ce2010-09-08 15:12:33 +0000431#endif
432
sewardjb9c815b2010-09-03 15:51:34 +0000433
434/* Helper function for VG_(machine_get_hwcaps), assumes the SIGILL/etc
435 * handlers are installed. Determines the the sizes affected by dcbz
436 * and dcbzl instructions and updates the given VexArchInfo structure
437 * accordingly.
438 *
439 * Not very defensive: assumes that as long as the dcbz/dcbzl
440 * instructions don't raise a SIGILL, that they will zero an aligned,
441 * contiguous block of memory of a sensible size. */
sewardj5ae70ce2010-09-08 15:12:33 +0000442#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjb9c815b2010-09-03 15:51:34 +0000443static void find_ppc_dcbz_sz(VexArchInfo *arch_info)
444{
sewardjdcb3a592010-09-04 00:43:14 +0000445 Int dcbz_szB = 0;
sewardjb9c815b2010-09-03 15:51:34 +0000446 Int dcbzl_szB;
sewardj5ae70ce2010-09-08 15:12:33 +0000447# define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
sewardjb9c815b2010-09-03 15:51:34 +0000448 char test_block[4*MAX_DCBZL_SZB];
449 char *aligned = test_block;
450 Int i;
451
452 /* round up to next max block size, assumes MAX_DCBZL_SZB is pof2 */
453 aligned = (char *)(((HWord)aligned + MAX_DCBZL_SZB) & ~(MAX_DCBZL_SZB - 1));
454 vg_assert((aligned + MAX_DCBZL_SZB) <= &test_block[sizeof(test_block)]);
455
456 /* dcbz often clears 32B, although sometimes whatever the native cache
457 * block size is */
458 VG_(memset)(test_block, 0xff, sizeof(test_block));
459 __asm__ __volatile__("dcbz 0,%0"
460 : /*out*/
461 : "r" (aligned) /*in*/
462 : "memory" /*clobber*/);
463 for (dcbz_szB = 0, i = 0; i < sizeof(test_block); ++i) {
464 if (!test_block[i])
465 ++dcbz_szB;
466 }
467 vg_assert(dcbz_szB == 32 || dcbz_szB == 64 || dcbz_szB == 128);
468
469 /* dcbzl clears 128B on G5/PPC970, and usually 32B on other platforms */
sewardj6c591e12011-04-11 16:17:51 +0000470 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb9c815b2010-09-03 15:51:34 +0000471 dcbzl_szB = 0; /* indicates unsupported */
472 }
473 else {
474 VG_(memset)(test_block, 0xff, sizeof(test_block));
475 /* some older assemblers won't understand the dcbzl instruction
476 * variant, so we directly emit the instruction ourselves */
477 __asm__ __volatile__("mr 9, %0 ; .long 0x7C204FEC" /*dcbzl 0,9*/
478 : /*out*/
479 : "r" (aligned) /*in*/
480 : "memory", "r9" /*clobber*/);
481 for (dcbzl_szB = 0, i = 0; i < sizeof(test_block); ++i) {
482 if (!test_block[i])
483 ++dcbzl_szB;
484 }
485 vg_assert(dcbzl_szB == 32 || dcbzl_szB == 64 || dcbzl_szB == 128);
486 }
487
488 arch_info->ppc_dcbz_szB = dcbz_szB;
489 arch_info->ppc_dcbzl_szB = dcbzl_szB;
490
491 VG_(debugLog)(1, "machine", "dcbz_szB=%d dcbzl_szB=%d\n",
492 dcbz_szB, dcbzl_szB);
sewardj5ae70ce2010-09-08 15:12:33 +0000493# undef MAX_DCBZL_SZB
sewardjb9c815b2010-09-03 15:51:34 +0000494}
sewardj5ae70ce2010-09-08 15:12:33 +0000495#endif /* defined(VGA_ppc32) || defined(VGA_ppc64) */
496
sewardj2c3f2ea2011-04-13 15:40:10 +0000497#ifdef VGA_s390x
sewardj5ae70ce2010-09-08 15:12:33 +0000498
sewardj2c3f2ea2011-04-13 15:40:10 +0000499/* Read /proc/cpuinfo. Look for lines like these
500
501 processor 0: version = FF, identification = 0117C9, machine = 2064
502
503 and return the machine model or VEX_S390X_MODEL_INVALID on error. */
504
505static UInt VG_(get_machine_model)(void)
506{
507 static struct model_map {
508 HChar name[5];
509 UInt id;
510 } model_map[] = {
511 { "2064", VEX_S390X_MODEL_Z900 },
512 { "2066", VEX_S390X_MODEL_Z800 },
513 { "2084", VEX_S390X_MODEL_Z990 },
514 { "2086", VEX_S390X_MODEL_Z890 },
515 { "2094", VEX_S390X_MODEL_Z9_EC },
516 { "2096", VEX_S390X_MODEL_Z9_BC },
517 { "2097", VEX_S390X_MODEL_Z10_EC },
518 { "2098", VEX_S390X_MODEL_Z10_BC },
519 { "2817", VEX_S390X_MODEL_Z196 },
520 };
521
522 Int model, n, fh;
523 SysRes fd;
524 SizeT num_bytes, file_buf_size;
525 HChar *p, *m, *model_name, *file_buf;
526
527 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
528 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
529 if ( sr_isError(fd) ) return VEX_S390X_MODEL_INVALID;
530
531 fh = sr_Res(fd);
532
533 /* Determine the size of /proc/cpuinfo.
534 Work around broken-ness in /proc file system implementation.
535 fstat returns a zero size for /proc/cpuinfo although it is
536 claimed to be a regular file. */
537 num_bytes = 0;
538 file_buf_size = 1000;
539 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
540 while (42) {
541 n = VG_(read)(fh, file_buf, file_buf_size);
542 if (n < 0) break;
543
544 num_bytes += n;
545 if (n < file_buf_size) break; /* reached EOF */
546 }
547
548 if (n < 0) num_bytes = 0; /* read error; ignore contents */
549
550 if (num_bytes > file_buf_size) {
551 VG_(free)( file_buf );
552 VG_(lseek)( fh, 0, VKI_SEEK_SET );
553 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
554 n = VG_(read)( fh, file_buf, num_bytes );
555 if (n < 0) num_bytes = 0;
556 }
557
558 file_buf[num_bytes] = '\0';
559 VG_(close)(fh);
560
561 /* Parse file */
562 model = VEX_S390X_MODEL_INVALID;
563 for (p = file_buf; *p; ++p) {
564 /* Beginning of line */
565 if (VG_(strncmp)( p, "processor", sizeof "processor" - 1 ) != 0) continue;
566
567 m = VG_(strstr)( p, "machine" );
568 if (m == NULL) continue;
569
570 p = m + sizeof "machine" - 1;
571 while ( VG_(isspace)( *p ) || *p == '=') {
572 if (*p == '\n') goto next_line;
573 ++p;
574 }
575
576 model_name = p;
577 for (n = 0; n < sizeof model_map / sizeof model_map[0]; ++n) {
578 struct model_map *mm = model_map + n;
579 SizeT len = VG_(strlen)( mm->name );
580 if ( VG_(strncmp)( mm->name, model_name, len ) == 0 &&
581 VG_(isspace)( model_name[len] )) {
582 if (mm->id < model) model = mm->id;
583 p = model_name + len;
584 break;
585 }
586 }
587 /* Skip until end-of-line */
588 while (*p != '\n')
589 ++p;
590 next_line: ;
591 }
592
593 VG_(free)( file_buf );
594 VG_(debugLog)(1, "machine", "model = %s\n", model_map[model].name);
595
596 return model;
597}
598
599#endif /* VGA_s390x */
sewardj5ae70ce2010-09-08 15:12:33 +0000600
601/* Determine what insn set and insn set variant the host has, and
602 record it. To be called once at system startup. Returns False if
603 this a CPU incapable of running Valgrind. */
sewardje3826cf2005-11-13 00:30:22 +0000604
sewardje2d1e672005-11-12 23:10:48 +0000605Bool VG_(machine_get_hwcaps)( void )
606{
607 vg_assert(hwcaps_done == False);
608 hwcaps_done = True;
609
610 // Whack default settings into vai, so that we only need to fill in
611 // any interesting bits.
612 LibVEX_default_VexArchInfo(&vai);
613
614#if defined(VGA_x86)
sewardj40d91c72010-07-29 15:40:32 +0000615 { Bool have_sse1, have_sse2, have_cx8, have_lzcnt;
sewardjc7ffc942011-03-28 16:26:42 +0000616 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000617 UChar vstr[13];
618 vstr[0] = 0;
sewardje2d1e672005-11-12 23:10:48 +0000619
620 if (!VG_(has_cpuid)())
621 /* we can't do cpuid at all. Give up. */
622 return False;
623
tomad8a5912011-06-10 15:04:22 +0000624 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000625 if (eax < 1)
626 /* we can't ask for cpuid(x) for x > 0. Give up. */
627 return False;
628
sewardj40d91c72010-07-29 15:40:32 +0000629 /* Get processor ID string, and max basic/extended index
630 values. */
sewardj40d91c72010-07-29 15:40:32 +0000631 VG_(memcpy)(&vstr[0], &ebx, 4);
632 VG_(memcpy)(&vstr[4], &edx, 4);
633 VG_(memcpy)(&vstr[8], &ecx, 4);
634 vstr[12] = 0;
635
tomad8a5912011-06-10 15:04:22 +0000636 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000637 max_extended = eax;
638
sewardje2d1e672005-11-12 23:10:48 +0000639 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000640 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000641
642 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
643 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
644
sewardj1c0ce7a2009-07-01 08:10:49 +0000645 /* cmpxchg8b is a minimum requirement now; if we don't have it we
646 must simply give up. But all CPUs since Pentium-I have it, so
647 that doesn't seem like much of a restriction. */
648 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
649 if (!have_cx8)
650 return False;
651
sewardj40d91c72010-07-29 15:40:32 +0000652 /* Figure out if this is an AMD that can do LZCNT. */
653 have_lzcnt = False;
654 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
655 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000656 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000657 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
658 }
659
sewardje2d1e672005-11-12 23:10:48 +0000660 if (have_sse2 && have_sse1) {
661 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000662 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
663 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardj40d91c72010-07-29 15:40:32 +0000664 if (have_lzcnt)
665 vai.hwcaps |= VEX_HWCAPS_X86_LZCNT;
sewardje2d1e672005-11-12 23:10:48 +0000666 VG_(machine_x86_have_mxcsr) = 1;
667 return True;
668 }
669
670 if (have_sse1) {
671 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000672 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000673 VG_(machine_x86_have_mxcsr) = 1;
674 return True;
675 }
676
sewardje3121f32006-01-27 21:23:23 +0000677 va = VexArchX86;
678 vai.hwcaps = 0; /*baseline - no sse at all*/
sewardje2d1e672005-11-12 23:10:48 +0000679 VG_(machine_x86_have_mxcsr) = 0;
680 return True;
681 }
682
683#elif defined(VGA_amd64)
sewardjc7ffc942011-03-28 16:26:42 +0000684 { Bool have_sse3, have_cx8, have_cx16;
sewardj40d91c72010-07-29 15:40:32 +0000685 Bool have_lzcnt;
sewardjc7ffc942011-03-28 16:26:42 +0000686 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000687 UChar vstr[13];
688 vstr[0] = 0;
sewardj1c0ce7a2009-07-01 08:10:49 +0000689
690 if (!VG_(has_cpuid)())
691 /* we can't do cpuid at all. Give up. */
692 return False;
693
tomad8a5912011-06-10 15:04:22 +0000694 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000695 if (eax < 1)
696 /* we can't ask for cpuid(x) for x > 0. Give up. */
697 return False;
698
sewardj40d91c72010-07-29 15:40:32 +0000699 /* Get processor ID string, and max basic/extended index
700 values. */
sewardj40d91c72010-07-29 15:40:32 +0000701 VG_(memcpy)(&vstr[0], &ebx, 4);
702 VG_(memcpy)(&vstr[4], &edx, 4);
703 VG_(memcpy)(&vstr[8], &ecx, 4);
704 vstr[12] = 0;
705
tomad8a5912011-06-10 15:04:22 +0000706 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000707 max_extended = eax;
708
sewardj1c0ce7a2009-07-01 08:10:49 +0000709 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000710 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000711
sewardjc7ffc942011-03-28 16:26:42 +0000712 // we assume that SSE1 and SSE2 are available by default
sewardj598971e2009-07-12 13:19:04 +0000713 have_sse3 = (ecx & (1<<0)) != 0; /* True => have sse3 insns */
sewardj40d91c72010-07-29 15:40:32 +0000714 // ssse3 is ecx:9
715 // sse41 is ecx:19
716 // sse42 is ecx:20
sewardj1c0ce7a2009-07-01 08:10:49 +0000717
718 /* cmpxchg8b is a minimum requirement now; if we don't have it we
719 must simply give up. But all CPUs since Pentium-I have it, so
720 that doesn't seem like much of a restriction. */
721 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
722 if (!have_cx8)
723 return False;
724
725 /* on amd64 we tolerate older cpus, which don't have cmpxchg16b */
726 have_cx16 = (ecx & (1<<13)) != 0; /* True => have cmpxchg16b */
727
sewardj40d91c72010-07-29 15:40:32 +0000728 /* Figure out if this is an AMD that can do LZCNT. */
729 have_lzcnt = False;
730 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
731 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000732 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000733 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
734 }
735
sewardj1c0ce7a2009-07-01 08:10:49 +0000736 va = VexArchAMD64;
737 vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
sewardj40d91c72010-07-29 15:40:32 +0000738 | (have_cx16 ? VEX_HWCAPS_AMD64_CX16 : 0)
739 | (have_lzcnt ? VEX_HWCAPS_AMD64_LZCNT : 0);
sewardj1c0ce7a2009-07-01 08:10:49 +0000740 return True;
741 }
sewardje2d1e672005-11-12 23:10:48 +0000742
743#elif defined(VGA_ppc32)
bart1581e742009-01-13 07:49:14 +0000744 {
745 /* Find out which subset of the ppc32 instruction set is supported by
746 verifying whether various ppc32 instructions generate a SIGILL
747 or a SIGFPE. An alternative approach is to check the AT_HWCAP and
748 AT_PLATFORM entries in the ELF auxiliary table -- see also
749 the_iifii.client_auxv in m_main.c.
750 */
njncda2f0f2009-05-18 02:12:08 +0000751 vki_sigset_t saved_set, tmp_set;
752 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
753 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000754
sewardjf34eb492011-04-15 11:57:05 +0000755 volatile Bool have_F, have_V, have_FX, have_GX, have_VX;
sewardj7637e9e2006-02-21 17:11:11 +0000756 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000757
njncda2f0f2009-05-18 02:12:08 +0000758 /* This is a kludge. Really we ought to back-convert saved_act
759 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
760 since that's a no-op on all ppc32 platforms so far supported,
761 it's not worth the typing effort. At least include most basic
762 sanity check: */
763 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
764
sewardje3826cf2005-11-13 00:30:22 +0000765 VG_(sigemptyset)(&tmp_set);
766 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000767 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardje3826cf2005-11-13 00:30:22 +0000768
sewardj7637e9e2006-02-21 17:11:11 +0000769 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
770 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000771
bart1581e742009-01-13 07:49:14 +0000772 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
sewardj7637e9e2006-02-21 17:11:11 +0000773 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000774 tmp_sigill_act = saved_sigill_act;
775
776 r = VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
777 vg_assert(r == 0);
778 tmp_sigfpe_act = saved_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000779
sewardj7637e9e2006-02-21 17:11:11 +0000780 /* NODEFER: signal handler does not return (from the kernel's point of
781 view), hence if it is to successfully catch a signal more than once,
782 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000783 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
784 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
785 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
786 tmp_sigill_act.ksa_handler = handler_unsup_insn;
787 r = VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
788 vg_assert(r == 0);
789
790 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
791 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
792 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
793 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
794 r = VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
795 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000796
sewardje3121f32006-01-27 21:23:23 +0000797 /* standard FP insns */
798 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000799 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000800 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000801 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000802 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000803 }
804
sewardje3121f32006-01-27 21:23:23 +0000805 /* Altivec insns */
806 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000807 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000808 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000809 } else {
sewardj71592122006-04-04 03:29:48 +0000810 /* Unfortunately some older assemblers don't speak Altivec (or
811 choose not to), so to be safe we directly emit the 32-bit
812 word corresponding to "vor 0,0,0". This fixes a build
813 problem that happens on Debian 3.1 (ppc32), and probably
814 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000815 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000816 }
817
sewardje3121f32006-01-27 21:23:23 +0000818 /* General-Purpose optional (fsqrt, fsqrts) */
819 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000820 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000821 have_FX = False;
822 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000823 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000824 }
825
826 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
827 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000828 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000829 have_GX = False;
830 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000831 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000832 }
833
sewardjf34eb492011-04-15 11:57:05 +0000834 /* VSX support implies Power ISA 2.06 */
835 have_VX = True;
836 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
837 have_VX = False;
838 } else {
839 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
840 }
841
842
sewardjb9c815b2010-09-03 15:51:34 +0000843 /* determine dcbz/dcbzl sizes while we still have the signal
844 * handlers registered */
845 find_ppc_dcbz_sz(&vai);
846
bart1581e742009-01-13 07:49:14 +0000847 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
848 vg_assert(r == 0);
849 r = VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj7637e9e2006-02-21 17:11:11 +0000850 vg_assert(r == 0);
851 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
852 vg_assert(r == 0);
sewardjf34eb492011-04-15 11:57:05 +0000853 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d\n",
854 (Int)have_F, (Int)have_V, (Int)have_FX,
855 (Int)have_GX, (Int)have_VX);
sewardje3121f32006-01-27 21:23:23 +0000856 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
857 if (have_V && !have_F)
858 have_V = False;
859 if (have_FX && !have_F)
860 have_FX = False;
861 if (have_GX && !have_F)
862 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +0000863
sewardje3121f32006-01-27 21:23:23 +0000864 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
865 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000866
867 va = VexArchPPC32;
868
sewardje3121f32006-01-27 21:23:23 +0000869 vai.hwcaps = 0;
870 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
871 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
872 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
873 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardjf34eb492011-04-15 11:57:05 +0000874 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC32_VX;
sewardje3826cf2005-11-13 00:30:22 +0000875
876 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
877 called before we're ready to go. */
878 return True;
879 }
sewardje2d1e672005-11-12 23:10:48 +0000880
sewardj2c48c7b2005-11-29 13:05:56 +0000881#elif defined(VGA_ppc64)
bart1581e742009-01-13 07:49:14 +0000882 {
883 /* Same instruction set detection algorithm as for ppc32. */
njncda2f0f2009-05-18 02:12:08 +0000884 vki_sigset_t saved_set, tmp_set;
885 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
886 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardj2c48c7b2005-11-29 13:05:56 +0000887
sewardjf34eb492011-04-15 11:57:05 +0000888 volatile Bool have_F, have_V, have_FX, have_GX, have_VX;
njncda2f0f2009-05-18 02:12:08 +0000889 Int r;
890
891 /* This is a kludge. Really we ought to back-convert saved_act
892 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
893 since that's a no-op on all ppc64 platforms so far supported,
894 it's not worth the typing effort. At least include most basic
895 sanity check: */
896 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
sewardj2c48c7b2005-11-29 13:05:56 +0000897
898 VG_(sigemptyset)(&tmp_set);
899 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000900 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardj2c48c7b2005-11-29 13:05:56 +0000901
njncda2f0f2009-05-18 02:12:08 +0000902 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
903 vg_assert(r == 0);
sewardj2c48c7b2005-11-29 13:05:56 +0000904
njncda2f0f2009-05-18 02:12:08 +0000905 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
906 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000907 tmp_sigill_act = saved_sigill_act;
908
909 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
910 tmp_sigfpe_act = saved_sigfpe_act;
911
sewardj7637e9e2006-02-21 17:11:11 +0000912 /* NODEFER: signal handler does not return (from the kernel's point of
913 view), hence if it is to successfully catch a signal more than once,
914 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000915 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
916 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
917 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
918 tmp_sigill_act.ksa_handler = handler_unsup_insn;
919 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
920
921 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
922 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
923 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
924 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
925 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +0000926
sewardje3121f32006-01-27 21:23:23 +0000927 /* standard FP insns */
928 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000929 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000930 have_F = False;
931 } else {
932 __asm__ __volatile__("fmr 0,0");
933 }
934
935 /* Altivec insns */
936 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000937 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000938 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +0000939 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000940 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +0000941 }
942
sewardje3121f32006-01-27 21:23:23 +0000943 /* General-Purpose optional (fsqrt, fsqrts) */
944 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000945 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000946 have_FX = False;
947 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000948 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000949 }
950
951 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
952 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000953 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000954 have_GX = False;
955 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000956 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000957 }
958
sewardjf34eb492011-04-15 11:57:05 +0000959 /* VSX support implies Power ISA 2.06 */
960 have_VX = True;
961 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
962 have_VX = False;
963 } else {
964 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
965 }
966
sewardjb9c815b2010-09-03 15:51:34 +0000967 /* determine dcbz/dcbzl sizes while we still have the signal
968 * handlers registered */
969 find_ppc_dcbz_sz(&vai);
970
bart1581e742009-01-13 07:49:14 +0000971 VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
972 VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +0000973 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
sewardjf34eb492011-04-15 11:57:05 +0000974 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d\n",
975 (Int)have_F, (Int)have_V, (Int)have_FX,
976 (Int)have_GX, (Int)have_VX);
sewardje3121f32006-01-27 21:23:23 +0000977 /* on ppc64, if we don't even have FP, just give up. */
978 if (!have_F)
979 return False;
980
981 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +0000982
983 va = VexArchPPC64;
sewardje3121f32006-01-27 21:23:23 +0000984
985 vai.hwcaps = 0;
986 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
987 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
988 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardjf34eb492011-04-15 11:57:05 +0000989 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC64_VX;
sewardj2c48c7b2005-11-29 13:05:56 +0000990
991 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
992 called before we're ready to go. */
993 return True;
994 }
995
sewardjb5b87402011-03-07 16:05:35 +0000996#elif defined(VGA_s390x)
997 {
998 /* Instruction set detection code borrowed from ppc above. */
999 vki_sigset_t saved_set, tmp_set;
1000 vki_sigaction_fromK_t saved_sigill_act;
1001 vki_sigaction_toK_t tmp_sigill_act;
1002
sewardj1c6f6ab2011-04-27 12:00:51 +00001003 volatile Bool have_LDISP, have_EIMM, have_GIE, have_DFP, have_FGX;
sewardj2c3f2ea2011-04-13 15:40:10 +00001004 Int r, model;
sewardjb5b87402011-03-07 16:05:35 +00001005
1006 /* Unblock SIGILL and stash away the old action for that signal */
1007 VG_(sigemptyset)(&tmp_set);
1008 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1009
1010 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1011 vg_assert(r == 0);
1012
1013 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1014 vg_assert(r == 0);
1015 tmp_sigill_act = saved_sigill_act;
1016
1017 /* NODEFER: signal handler does not return (from the kernel's point of
1018 view), hence if it is to successfully catch a signal more than once,
1019 we need the NODEFER flag. */
1020 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1021 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1022 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1023 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1024 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1025
1026 /* Determine hwcaps. Note, we cannot use the stfle insn because it
1027 is not supported on z900. */
1028
1029 have_LDISP = True;
sewardj6c591e12011-04-11 16:17:51 +00001030 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001031 have_LDISP = False;
1032 } else {
1033 /* BASR loads the address of the next insn into r1. Needed to avoid
1034 a segfault in XY. */
1035 __asm__ __volatile__("basr %%r1,%%r0\n\t"
1036 ".long 0xe3001000\n\t" /* XY 0,0(%r1) */
1037 ".short 0x0057" : : : "r0", "r1", "cc", "memory");
1038 }
1039
1040 have_EIMM = True;
sewardj6c591e12011-04-11 16:17:51 +00001041 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001042 have_EIMM = False;
1043 } else {
1044 __asm__ __volatile__(".long 0xc0090000\n\t" /* iilf r0,0 */
1045 ".short 0x0000" : : : "r0", "memory");
1046 }
1047
1048 have_GIE = True;
sewardj6c591e12011-04-11 16:17:51 +00001049 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001050 have_GIE = False;
1051 } else {
1052 __asm__ __volatile__(".long 0xc2010000\n\t" /* msfi r0,0 */
1053 ".short 0x0000" : : : "r0", "memory");
1054 }
1055
1056 have_DFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001057 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001058 have_DFP = False;
1059 } else {
1060 __asm__ __volatile__(".long 0xb3d20000"
1061 : : : "r0", "cc", "memory"); /* adtr r0,r0,r0 */
1062 }
1063
sewardj1c6f6ab2011-04-27 12:00:51 +00001064 have_FGX = True;
1065 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1066 have_FGX = False;
1067 } else {
1068 __asm__ __volatile__(".long 0xb3cd0000" : : : "r0"); /* lgdr r0,f0 */
1069 }
1070
sewardjb5b87402011-03-07 16:05:35 +00001071 /* Restore signals */
1072 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1073 vg_assert(r == 0);
1074 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1075 vg_assert(r == 0);
sewardjb5b87402011-03-07 16:05:35 +00001076 va = VexArchS390X;
1077
sewardj2c3f2ea2011-04-13 15:40:10 +00001078 model = VG_(get_machine_model)();
1079
sewardj1c6f6ab2011-04-27 12:00:51 +00001080 VG_(debugLog)(1, "machine", "machine %d LDISP %d EIMM %d GIE %d DFP %d "
1081 "FGX %d\n", model, have_LDISP, have_EIMM, have_GIE,
1082 have_DFP, have_FGX);
sewardj2c3f2ea2011-04-13 15:40:10 +00001083
1084 if (model == VEX_S390X_MODEL_INVALID) return False;
1085
1086 vai.hwcaps = model;
1087 if (have_LDISP) {
1088 /* Use long displacement only on machines >= z990. For all other machines
1089 it is millicoded and therefore slow. */
1090 if (model >= VEX_S390X_MODEL_Z990)
1091 vai.hwcaps |= VEX_HWCAPS_S390X_LDISP;
1092 }
sewardjb5b87402011-03-07 16:05:35 +00001093 if (have_EIMM) vai.hwcaps |= VEX_HWCAPS_S390X_EIMM;
1094 if (have_GIE) vai.hwcaps |= VEX_HWCAPS_S390X_GIE;
1095 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_S390X_DFP;
sewardj1c6f6ab2011-04-27 12:00:51 +00001096 if (have_FGX) vai.hwcaps |= VEX_HWCAPS_S390X_FGX;
sewardjb5b87402011-03-07 16:05:35 +00001097
sewardj2c3f2ea2011-04-13 15:40:10 +00001098 VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
1099
sewardjb5b87402011-03-07 16:05:35 +00001100 return True;
1101 }
1102
sewardj59570ff2010-01-01 11:59:33 +00001103#elif defined(VGA_arm)
1104 {
sewardj1dbd3372010-08-22 12:21:14 +00001105 /* Same instruction set detection algorithm as for ppc32. */
1106 vki_sigset_t saved_set, tmp_set;
1107 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
1108 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
1109
1110 volatile Bool have_VFP, have_VFP2, have_VFP3, have_NEON;
1111 volatile Int archlevel;
1112 Int r;
1113
1114 /* This is a kludge. Really we ought to back-convert saved_act
1115 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1116 since that's a no-op on all ppc64 platforms so far supported,
1117 it's not worth the typing effort. At least include most basic
1118 sanity check: */
1119 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
1120
1121 VG_(sigemptyset)(&tmp_set);
1122 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1123 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
1124
1125 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1126 vg_assert(r == 0);
1127
1128 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1129 vg_assert(r == 0);
1130 tmp_sigill_act = saved_sigill_act;
1131
1132 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1133 tmp_sigfpe_act = saved_sigfpe_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 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1145 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1146 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1147 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1148 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1149
1150 /* VFP insns */
1151 have_VFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001152 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001153 have_VFP = False;
1154 } else {
1155 __asm__ __volatile__(".word 0xEEB02B42"); /* VMOV.F64 d2, d2 */
1156 }
1157 /* There are several generation of VFP extension but they differs very
1158 little so for now we will not distinguish them. */
1159 have_VFP2 = have_VFP;
1160 have_VFP3 = have_VFP;
1161
1162 /* NEON insns */
1163 have_NEON = True;
sewardj6c591e12011-04-11 16:17:51 +00001164 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001165 have_NEON = False;
1166 } else {
1167 __asm__ __volatile__(".word 0xF2244154"); /* VMOV q2, q2 */
1168 }
1169
1170 /* ARM architecture level */
1171 archlevel = 5; /* v5 will be base level */
1172 if (archlevel < 7) {
1173 archlevel = 7;
sewardj6c591e12011-04-11 16:17:51 +00001174 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001175 archlevel = 5;
1176 } else {
1177 __asm__ __volatile__(".word 0xF45FF000"); /* PLI [PC,#-0] */
1178 }
1179 }
1180 if (archlevel < 6) {
1181 archlevel = 6;
sewardj6c591e12011-04-11 16:17:51 +00001182 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001183 archlevel = 5;
1184 } else {
1185 __asm__ __volatile__(".word 0xE6822012"); /* PKHBT r2, r2, r2 */
1186 }
1187 }
1188
1189 VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
1190 VG_(convert_sigaction_fromK_to_toK)(&saved_sigfpe_act, &tmp_sigfpe_act);
1191 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1192 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1193 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1194
1195 VG_(debugLog)(1, "machine", "ARMv%d VFP %d VFP2 %d VFP3 %d NEON %d\n",
1196 archlevel, (Int)have_VFP, (Int)have_VFP2, (Int)have_VFP3,
1197 (Int)have_NEON);
1198
1199 VG_(machine_arm_archlevel) = archlevel;
1200
sewardj59570ff2010-01-01 11:59:33 +00001201 va = VexArchARM;
sewardj1dbd3372010-08-22 12:21:14 +00001202
1203 vai.hwcaps = VEX_ARM_ARCHLEVEL(archlevel);
1204 if (have_VFP3) vai.hwcaps |= VEX_HWCAPS_ARM_VFP3;
1205 if (have_VFP2) vai.hwcaps |= VEX_HWCAPS_ARM_VFP2;
1206 if (have_VFP) vai.hwcaps |= VEX_HWCAPS_ARM_VFP;
1207 if (have_NEON) vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1208
sewardj59570ff2010-01-01 11:59:33 +00001209 return True;
1210 }
1211
sewardje2d1e672005-11-12 23:10:48 +00001212#else
1213# error "Unknown arch"
1214#endif
1215}
1216
sewardj2c48c7b2005-11-29 13:05:56 +00001217/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +00001218#if defined(VGA_ppc32)
1219void VG_(machine_ppc32_set_clszB)( Int szB )
1220{
1221 vg_assert(hwcaps_done);
1222
1223 /* Either the value must not have been set yet (zero) or we can
1224 tolerate it being set to the same value multiple times, as the
1225 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001226 vg_assert(vai.ppc_cache_line_szB == 0
1227 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +00001228
sewardj89230ca2008-05-29 16:39:57 +00001229 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001230 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +00001231}
1232#endif
1233
sewardje2d1e672005-11-12 23:10:48 +00001234
sewardj2c48c7b2005-11-29 13:05:56 +00001235/* Notify host cpu cache line size. */
1236#if defined(VGA_ppc64)
1237void VG_(machine_ppc64_set_clszB)( Int szB )
1238{
1239 vg_assert(hwcaps_done);
1240
1241 /* Either the value must not have been set yet (zero) or we can
1242 tolerate it being set to the same value multiple times, as the
1243 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001244 vg_assert(vai.ppc_cache_line_szB == 0
1245 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +00001246
sewardj89230ca2008-05-29 16:39:57 +00001247 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001248 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +00001249}
1250#endif
1251
1252
sewardja3551be2010-09-09 07:25:58 +00001253/* Notify host's ability to handle NEON instructions. */
1254#if defined(VGA_arm)
1255void VG_(machine_arm_set_has_NEON)( Bool has_neon )
1256{
1257 vg_assert(hwcaps_done);
1258 /* There's nothing else we can sanity check. */
1259
1260 if (has_neon) {
1261 vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1262 } else {
1263 vai.hwcaps &= ~VEX_HWCAPS_ARM_NEON;
1264 }
1265}
1266#endif
1267
1268
sewardje2d1e672005-11-12 23:10:48 +00001269/* Fetch host cpu info, once established. */
1270void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
1271 /*OUT*/VexArchInfo* pVai )
1272{
1273 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +00001274 if (pVa) *pVa = va;
1275 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +00001276}
sewardj7821e2e2005-08-08 00:35:46 +00001277
1278
sewardj53ee1fc2005-12-23 02:29:58 +00001279// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +00001280// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +00001281void* VG_(fnptr_to_fnentry)( void* f )
1282{
sewardj59570ff2010-01-01 11:59:33 +00001283#if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
1284 || defined(VGP_arm_linux) \
sewardjb5b87402011-03-07 16:05:35 +00001285 || defined(VGP_ppc32_linux) || defined(VGO_darwin) \
1286 || defined(VGP_s390x_linux)
sewardj53ee1fc2005-12-23 02:29:58 +00001287 return f;
sewardjf1c91e02006-10-17 01:35:58 +00001288#elif defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
1289 || defined(VGP_ppc64_aix5)
1290 /* All other ppc variants use the AIX scheme, in which f is a
1291 pointer to a 3-word function descriptor, of which the first word
1292 is the entry address. */
1293 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +00001294 return (void*)(descr[0]);
1295#else
1296# error "Unknown platform"
1297#endif
1298}
1299
njnf536bbb2005-06-13 04:21:38 +00001300/*--------------------------------------------------------------------*/
1301/*--- end ---*/
1302/*--------------------------------------------------------------------*/