blob: 358cc652dcba5092499c5c5c71303bf4f5b47705 [file] [log] [blame]
njnf536bbb2005-06-13 04:21:38 +00001
2/*--------------------------------------------------------------------*/
3/*--- Machine-related stuff. m_machine.c ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj9ebd6e02007-01-08 06:01:59 +000010 Copyright (C) 2000-2007 Julian Seward
njnf536bbb2005-06-13 04:21:38 +000011 jseward@acm.org
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
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"
36#include "pub_core_machine.h"
sewardje2d1e672005-11-12 23:10:48 +000037#include "pub_core_cpuid.h"
sewardje3826cf2005-11-13 00:30:22 +000038#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL
39
njnf536bbb2005-06-13 04:21:38 +000040
njnaf839f52005-06-23 03:27:57 +000041#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
42#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
43#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
njnf536bbb2005-06-13 04:21:38 +000044
45Addr VG_(get_SP) ( ThreadId tid )
46{
47 return STACK_PTR( VG_(threads)[tid].arch );
48}
49
50Addr VG_(get_IP) ( ThreadId tid )
51{
52 return INSTR_PTR( VG_(threads)[tid].arch );
53}
54
55Addr VG_(get_FP) ( ThreadId tid )
56{
57 return FRAME_PTR( VG_(threads)[tid].arch );
58}
59
sewardjacaec5f2005-08-19 16:02:59 +000060Addr VG_(get_LR) ( ThreadId tid )
61{
sewardj2c48c7b2005-11-29 13:05:56 +000062# if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjacaec5f2005-08-19 16:02:59 +000063 return VG_(threads)[tid].arch.vex.guest_LR;
64# elif defined(VGA_x86) || defined(VGA_amd64)
65 return 0;
66# else
67# error "Unknown arch"
68# endif
69}
70
njnf536bbb2005-06-13 04:21:38 +000071void VG_(set_SP) ( ThreadId tid, Addr sp )
72{
73 STACK_PTR( VG_(threads)[tid].arch ) = sp;
74}
75
76void VG_(set_IP) ( ThreadId tid, Addr ip )
77{
78 INSTR_PTR( VG_(threads)[tid].arch ) = ip;
79}
80
81
82void VG_(get_shadow_regs_area) ( ThreadId tid, OffT offset, SizeT size,
83 UChar* area )
84{
85 ThreadState* tst;
86
87 vg_assert(VG_(is_valid_tid)(tid));
88 tst = & VG_(threads)[tid];
89
90 // Bounds check
91 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
92 vg_assert(offset + size <= sizeof(VexGuestArchState));
93
94 VG_(memcpy)( area, (void*)(((Addr)&(tst->arch.vex_shadow)) + offset), size);
95}
96
97void VG_(set_shadow_regs_area) ( ThreadId tid, OffT offset, SizeT size,
98 const UChar* area )
99{
100 ThreadState* tst;
101
102 vg_assert(VG_(is_valid_tid)(tid));
103 tst = & VG_(threads)[tid];
104
105 // Bounds check
106 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
107 vg_assert(offset + size <= sizeof(VexGuestArchState));
108
109 VG_(memcpy)( (void*)(((Addr)(&tst->arch.vex_shadow)) + offset), area, size);
110}
111
112
njn6ace3ea2005-06-17 03:06:27 +0000113static void apply_to_GPs_of_tid(VexGuestArchState* vex, void (*f)(Addr))
114{
115#if defined(VGA_x86)
116 (*f)(vex->guest_EAX);
117 (*f)(vex->guest_ECX);
118 (*f)(vex->guest_EDX);
119 (*f)(vex->guest_EBX);
120 (*f)(vex->guest_ESI);
121 (*f)(vex->guest_EDI);
122 (*f)(vex->guest_ESP);
123 (*f)(vex->guest_EBP);
124#elif defined(VGA_amd64)
125 (*f)(vex->guest_RAX);
126 (*f)(vex->guest_RCX);
127 (*f)(vex->guest_RDX);
128 (*f)(vex->guest_RBX);
129 (*f)(vex->guest_RSI);
130 (*f)(vex->guest_RDI);
131 (*f)(vex->guest_RSP);
132 (*f)(vex->guest_RBP);
133 (*f)(vex->guest_R8);
134 (*f)(vex->guest_R9);
135 (*f)(vex->guest_R10);
136 (*f)(vex->guest_R11);
137 (*f)(vex->guest_R12);
138 (*f)(vex->guest_R13);
139 (*f)(vex->guest_R14);
140 (*f)(vex->guest_R15);
sewardj2c48c7b2005-11-29 13:05:56 +0000141#elif defined(VGA_ppc32) || defined(VGA_ppc64)
cerion85665ca2005-06-20 15:51:07 +0000142 /* XXX ask tool about validity? */
143 (*f)(vex->guest_GPR0);
144 (*f)(vex->guest_GPR1);
145 (*f)(vex->guest_GPR2);
146 (*f)(vex->guest_GPR3);
147 (*f)(vex->guest_GPR4);
148 (*f)(vex->guest_GPR5);
149 (*f)(vex->guest_GPR6);
150 (*f)(vex->guest_GPR7);
151 (*f)(vex->guest_GPR8);
152 (*f)(vex->guest_GPR9);
153 (*f)(vex->guest_GPR10);
154 (*f)(vex->guest_GPR11);
155 (*f)(vex->guest_GPR12);
156 (*f)(vex->guest_GPR13);
157 (*f)(vex->guest_GPR14);
158 (*f)(vex->guest_GPR15);
159 (*f)(vex->guest_GPR16);
160 (*f)(vex->guest_GPR17);
161 (*f)(vex->guest_GPR18);
162 (*f)(vex->guest_GPR19);
163 (*f)(vex->guest_GPR20);
164 (*f)(vex->guest_GPR21);
165 (*f)(vex->guest_GPR22);
166 (*f)(vex->guest_GPR23);
167 (*f)(vex->guest_GPR24);
168 (*f)(vex->guest_GPR25);
169 (*f)(vex->guest_GPR26);
170 (*f)(vex->guest_GPR27);
171 (*f)(vex->guest_GPR28);
172 (*f)(vex->guest_GPR29);
173 (*f)(vex->guest_GPR30);
174 (*f)(vex->guest_GPR31);
175 (*f)(vex->guest_CTR);
176 (*f)(vex->guest_LR);
177
njn6ace3ea2005-06-17 03:06:27 +0000178#else
179# error Unknown arch
180#endif
181}
182
183
184void VG_(apply_to_GP_regs)(void (*f)(UWord))
185{
186 ThreadId tid;
187
188 for (tid = 1; tid < VG_N_THREADS; tid++) {
189 if (VG_(is_valid_tid)(tid)) {
190 ThreadState* tst = VG_(get_ThreadState)(tid);
191 apply_to_GPs_of_tid(&(tst->arch.vex), f);
192 }
193 }
194}
195
njn1d0cb0d2005-08-15 01:52:02 +0000196static ThreadId thread_stack_iter = VG_INVALID_THREADID;
197
198void VG_(thread_stack_reset_iter)(void)
njnb506bd82005-06-21 04:01:51 +0000199{
njn1d0cb0d2005-08-15 01:52:02 +0000200 thread_stack_iter = 1;
njnb506bd82005-06-21 04:01:51 +0000201}
njn6ace3ea2005-06-17 03:06:27 +0000202
njn1d0cb0d2005-08-15 01:52:02 +0000203Bool VG_(thread_stack_next)(ThreadId* tid, Addr* stack_min, Addr* stack_max)
204{
205 ThreadId i;
206 for (i = thread_stack_iter; i < VG_N_THREADS; i++) {
207 if (VG_(threads)[i].status != VgTs_Empty) {
208 *tid = i;
209 *stack_min = VG_(get_SP)(i);
210 *stack_max = VG_(threads)[i].client_stack_highest_word;
211 thread_stack_iter = i + 1;
212 return True;
213 }
214 }
215 return False;
216}
sewardj7821e2e2005-08-08 00:35:46 +0000217
sewardje2d1e672005-11-12 23:10:48 +0000218//-------------------------------------------------------------
219/* Details about the capabilities of the underlying (host) CPU. These
220 details are acquired by (1) enquiring with the CPU at startup, or
221 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
222 line size). It's a bit nasty in the sense that there's no obvious
223 way to stop uses of some of this info before it's ready to go.
sewardj10f08cf2005-06-29 10:16:14 +0000224
sewardje2d1e672005-11-12 23:10:48 +0000225 Current dependencies are:
sewardja48a4932005-09-29 11:09:56 +0000226
sewardje2d1e672005-11-12 23:10:48 +0000227 x86: initially: call VG_(machine_get_hwcaps)
sewardj10f08cf2005-06-29 10:16:14 +0000228
sewardje2d1e672005-11-12 23:10:48 +0000229 then safe to use VG_(machine_get_VexArchInfo)
230 and VG_(machine_x86_have_mxcsr)
231 -------------
232 amd64: initially: call VG_(machine_get_hwcaps)
233
234 then safe to use VG_(machine_get_VexArchInfo)
235 -------------
236 ppc32: initially: call VG_(machine_get_hwcaps)
237 call VG_(machine_ppc32_set_clszB)
238
239 then safe to use VG_(machine_get_VexArchInfo)
sewardj2c36d422005-11-13 01:59:22 +0000240 and VG_(machine_ppc32_has_FP)
sewardje2d1e672005-11-12 23:10:48 +0000241 and VG_(machine_ppc32_has_VMX)
cerion1f0d8142005-12-23 00:57:03 +0000242 -------------
243 ppc64: initially: call VG_(machine_get_hwcaps)
244 call VG_(machine_ppc64_set_clszB)
245
246 then safe to use VG_(machine_get_VexArchInfo)
247 and VG_(machine_ppc64_has_VMX)
sewardje2d1e672005-11-12 23:10:48 +0000248
249 VG_(machine_get_hwcaps) may use signals (although it attempts to
250 leave signal state unchanged) and therefore should only be
251 called before m_main sets up the client's signal state.
252*/
253
254/* --------- State --------- */
255static Bool hwcaps_done = False;
256
257/* --- all archs --- */
258static VexArch va;
259static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000260
sewardj7821e2e2005-08-08 00:35:46 +0000261#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000262UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000263#endif
sewardje2d1e672005-11-12 23:10:48 +0000264#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000265UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000266UInt VG_(machine_ppc32_has_VMX) = 0;
267#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000268#if defined(VGA_ppc64)
269ULong VG_(machine_ppc64_has_VMX) = 0;
270#endif
sewardje2d1e672005-11-12 23:10:48 +0000271
272
273/* Determine what insn set and insn set variant the host has, and
274 record it. To be called once at system startup. Returns False if
275 this a CPU incapable of running Valgrind. */
276
sewardj2c48c7b2005-11-29 13:05:56 +0000277#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardje3826cf2005-11-13 00:30:22 +0000278#include <setjmp.h> // For jmp_buf
279static jmp_buf env_sigill;
280static void handler_sigill ( Int x ) { __builtin_longjmp(env_sigill,1); }
281#endif
282
sewardje2d1e672005-11-12 23:10:48 +0000283Bool VG_(machine_get_hwcaps)( void )
284{
285 vg_assert(hwcaps_done == False);
286 hwcaps_done = True;
287
288 // Whack default settings into vai, so that we only need to fill in
289 // any interesting bits.
290 LibVEX_default_VexArchInfo(&vai);
291
292#if defined(VGA_x86)
293 { Bool have_sse1, have_sse2;
294 UInt eax, ebx, ecx, edx;
295
296 if (!VG_(has_cpuid)())
297 /* we can't do cpuid at all. Give up. */
298 return False;
299
300 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
301 if (eax < 1)
302 /* we can't ask for cpuid(x) for x > 0. Give up. */
303 return False;
304
305 /* get capabilities bits into edx */
306 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
307
308 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
309 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
310
311 if (have_sse2 && have_sse1) {
312 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000313 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
314 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardje2d1e672005-11-12 23:10:48 +0000315 VG_(machine_x86_have_mxcsr) = 1;
316 return True;
317 }
318
319 if (have_sse1) {
320 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000321 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000322 VG_(machine_x86_have_mxcsr) = 1;
323 return True;
324 }
325
sewardje3121f32006-01-27 21:23:23 +0000326 va = VexArchX86;
327 vai.hwcaps = 0; /*baseline - no sse at all*/
sewardje2d1e672005-11-12 23:10:48 +0000328 VG_(machine_x86_have_mxcsr) = 0;
329 return True;
330 }
331
332#elif defined(VGA_amd64)
333 vg_assert(VG_(has_cpuid)());
sewardje3121f32006-01-27 21:23:23 +0000334 va = VexArchAMD64;
335 vai.hwcaps = 0; /*baseline - SSE2 */
sewardje2d1e672005-11-12 23:10:48 +0000336 return True;
337
338#elif defined(VGA_ppc32)
sewardje3826cf2005-11-13 00:30:22 +0000339 { /* ppc32 doesn't seem to have a sane way to find out what insn
340 sets the CPU supports. So we have to arse around with
341 SIGILLs. Yuck. */
342 vki_sigset_t saved_set, tmp_set;
343 struct vki_sigaction saved_act, tmp_act;
344
sewardjb32bc732006-01-27 21:52:39 +0000345 volatile Bool have_F, have_V, have_FX, have_GX;
sewardj7637e9e2006-02-21 17:11:11 +0000346 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000347
348 VG_(sigemptyset)(&tmp_set);
349 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
350
sewardj7637e9e2006-02-21 17:11:11 +0000351 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
352 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000353
sewardj7637e9e2006-02-21 17:11:11 +0000354 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_act);
355 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000356 tmp_act = saved_act;
357
sewardj7637e9e2006-02-21 17:11:11 +0000358 /* NODEFER: signal handler does not return (from the kernel's point of
359 view), hence if it is to successfully catch a signal more than once,
360 we need the NODEFER flag. */
sewardje3826cf2005-11-13 00:30:22 +0000361 tmp_act.sa_flags &= ~VKI_SA_RESETHAND;
362 tmp_act.sa_flags &= ~VKI_SA_SIGINFO;
sewardj7637e9e2006-02-21 17:11:11 +0000363 tmp_act.sa_flags |= VKI_SA_NODEFER;
sewardje3826cf2005-11-13 00:30:22 +0000364
sewardje3121f32006-01-27 21:23:23 +0000365 /* standard FP insns */
366 have_F = True;
sewardje3826cf2005-11-13 00:30:22 +0000367 tmp_act.ksa_handler = handler_sigill;
sewardj7637e9e2006-02-21 17:11:11 +0000368 r = VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
369 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000370 if (__builtin_setjmp(env_sigill)) {
sewardje3121f32006-01-27 21:23:23 +0000371 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000372 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000373 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000374 }
375
sewardje3121f32006-01-27 21:23:23 +0000376 /* Altivec insns */
377 have_V = True;
sewardje3826cf2005-11-13 00:30:22 +0000378 tmp_act.ksa_handler = handler_sigill;
sewardj7637e9e2006-02-21 17:11:11 +0000379 r = VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
380 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000381 if (__builtin_setjmp(env_sigill)) {
sewardje3121f32006-01-27 21:23:23 +0000382 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000383 } else {
sewardj71592122006-04-04 03:29:48 +0000384 /* Unfortunately some older assemblers don't speak Altivec (or
385 choose not to), so to be safe we directly emit the 32-bit
386 word corresponding to "vor 0,0,0". This fixes a build
387 problem that happens on Debian 3.1 (ppc32), and probably
388 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000389 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000390 }
391
sewardje3121f32006-01-27 21:23:23 +0000392 /* General-Purpose optional (fsqrt, fsqrts) */
393 have_FX = True;
394 tmp_act.ksa_handler = handler_sigill;
sewardj7637e9e2006-02-21 17:11:11 +0000395 r = VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
396 vg_assert(r == 0);
sewardje3121f32006-01-27 21:23:23 +0000397 if (__builtin_setjmp(env_sigill)) {
398 have_FX = False;
399 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000400 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000401 }
402
403 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
404 have_GX = True;
405 tmp_act.ksa_handler = handler_sigill;
sewardj7637e9e2006-02-21 17:11:11 +0000406 r = VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
407 vg_assert(r == 0);
sewardje3121f32006-01-27 21:23:23 +0000408 if (__builtin_setjmp(env_sigill)) {
409 have_GX = False;
410 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000411 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000412 }
413
sewardj7637e9e2006-02-21 17:11:11 +0000414 r = VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
415 vg_assert(r == 0);
416 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
417 vg_assert(r == 0);
sewardjb32bc732006-01-27 21:52:39 +0000418 /*
sewardje3121f32006-01-27 21:23:23 +0000419 VG_(printf)("F %d V %d FX %d GX %d\n",
420 (Int)have_F, (Int)have_V, (Int)have_FX, (Int)have_GX);
sewardjb32bc732006-01-27 21:52:39 +0000421 */
sewardje3121f32006-01-27 21:23:23 +0000422 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
423 if (have_V && !have_F)
424 have_V = False;
425 if (have_FX && !have_F)
426 have_FX = False;
427 if (have_GX && !have_F)
428 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +0000429
sewardje3121f32006-01-27 21:23:23 +0000430 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
431 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000432
433 va = VexArchPPC32;
434
sewardje3121f32006-01-27 21:23:23 +0000435 vai.hwcaps = 0;
436 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
437 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
438 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
439 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardje3826cf2005-11-13 00:30:22 +0000440
441 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
442 called before we're ready to go. */
443 return True;
444 }
sewardje2d1e672005-11-12 23:10:48 +0000445
sewardj2c48c7b2005-11-29 13:05:56 +0000446#elif defined(VGA_ppc64)
sewardje3121f32006-01-27 21:23:23 +0000447 { /* Same idiocy as for ppc32 - arse around with SIGILLs. */
448 vki_sigset_t saved_set, tmp_set;
sewardj2c48c7b2005-11-29 13:05:56 +0000449 struct vki_sigaction saved_act, tmp_act;
450
sewardjb32bc732006-01-27 21:52:39 +0000451 volatile Bool have_F, have_V, have_FX, have_GX;
sewardj2c48c7b2005-11-29 13:05:56 +0000452
453 VG_(sigemptyset)(&tmp_set);
454 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
455
456 VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
457
458 VG_(sigaction)(VKI_SIGILL, NULL, &saved_act);
459 tmp_act = saved_act;
460
sewardj7637e9e2006-02-21 17:11:11 +0000461 /* NODEFER: signal handler does not return (from the kernel's point of
462 view), hence if it is to successfully catch a signal more than once,
463 we need the NODEFER flag. */
sewardj2c48c7b2005-11-29 13:05:56 +0000464 tmp_act.sa_flags &= ~VKI_SA_RESETHAND;
465 tmp_act.sa_flags &= ~VKI_SA_SIGINFO;
sewardj7637e9e2006-02-21 17:11:11 +0000466 tmp_act.sa_flags |= VKI_SA_NODEFER;
sewardj2c48c7b2005-11-29 13:05:56 +0000467
sewardje3121f32006-01-27 21:23:23 +0000468 /* standard FP insns */
469 have_F = True;
sewardj2c48c7b2005-11-29 13:05:56 +0000470 tmp_act.ksa_handler = handler_sigill;
471 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +0000472 if (__builtin_setjmp(env_sigill)) {
sewardje3121f32006-01-27 21:23:23 +0000473 have_F = False;
474 } else {
475 __asm__ __volatile__("fmr 0,0");
476 }
477
478 /* Altivec insns */
479 have_V = True;
480 tmp_act.ksa_handler = handler_sigill;
481 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
482 if (__builtin_setjmp(env_sigill)) {
483 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +0000484 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000485 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +0000486 }
487
sewardje3121f32006-01-27 21:23:23 +0000488 /* General-Purpose optional (fsqrt, fsqrts) */
489 have_FX = True;
490 tmp_act.ksa_handler = handler_sigill;
491 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
492 if (__builtin_setjmp(env_sigill)) {
493 have_FX = False;
494 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000495 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000496 }
497
498 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
499 have_GX = True;
500 tmp_act.ksa_handler = handler_sigill;
501 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
502 if (__builtin_setjmp(env_sigill)) {
503 have_GX = False;
504 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000505 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000506 }
507
sewardj2c48c7b2005-11-29 13:05:56 +0000508 VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
509 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
sewardjb32bc732006-01-27 21:52:39 +0000510 /*
sewardje3121f32006-01-27 21:23:23 +0000511 if (0)
512 VG_(printf)("F %d V %d FX %d GX %d\n",
513 (Int)have_F, (Int)have_V, (Int)have_FX, (Int)have_GX);
sewardjb32bc732006-01-27 21:52:39 +0000514 */
sewardje3121f32006-01-27 21:23:23 +0000515 /* on ppc64, if we don't even have FP, just give up. */
516 if (!have_F)
517 return False;
518
519 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +0000520
521 va = VexArchPPC64;
sewardje3121f32006-01-27 21:23:23 +0000522
523 vai.hwcaps = 0;
524 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
525 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
526 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardj2c48c7b2005-11-29 13:05:56 +0000527
528 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
529 called before we're ready to go. */
530 return True;
531 }
532
sewardje2d1e672005-11-12 23:10:48 +0000533#else
534# error "Unknown arch"
535#endif
536}
537
sewardj2c48c7b2005-11-29 13:05:56 +0000538/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +0000539#if defined(VGA_ppc32)
540void VG_(machine_ppc32_set_clszB)( Int szB )
541{
542 vg_assert(hwcaps_done);
543
544 /* Either the value must not have been set yet (zero) or we can
545 tolerate it being set to the same value multiple times, as the
546 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +0000547 vg_assert(vai.ppc_cache_line_szB == 0
548 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +0000549
550 vg_assert(szB == 32 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +0000551 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +0000552}
553#endif
554
sewardje2d1e672005-11-12 23:10:48 +0000555
sewardj2c48c7b2005-11-29 13:05:56 +0000556/* Notify host cpu cache line size. */
557#if defined(VGA_ppc64)
558void VG_(machine_ppc64_set_clszB)( Int szB )
559{
560 vg_assert(hwcaps_done);
561
562 /* Either the value must not have been set yet (zero) or we can
563 tolerate it being set to the same value multiple times, as the
564 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +0000565 vg_assert(vai.ppc_cache_line_szB == 0
566 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +0000567
568 vg_assert(szB == 32 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +0000569 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +0000570}
571#endif
572
573
sewardje2d1e672005-11-12 23:10:48 +0000574/* Fetch host cpu info, once established. */
575void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
576 /*OUT*/VexArchInfo* pVai )
577{
578 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +0000579 if (pVa) *pVa = va;
580 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +0000581}
sewardj7821e2e2005-08-08 00:35:46 +0000582
583
sewardj53ee1fc2005-12-23 02:29:58 +0000584// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +0000585// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +0000586void* VG_(fnptr_to_fnentry)( void* f )
587{
sewardjf1c91e02006-10-17 01:35:58 +0000588#if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
589 || defined(VGP_ppc32_linux)
sewardj53ee1fc2005-12-23 02:29:58 +0000590 return f;
sewardjf1c91e02006-10-17 01:35:58 +0000591#elif defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
592 || defined(VGP_ppc64_aix5)
593 /* All other ppc variants use the AIX scheme, in which f is a
594 pointer to a 3-word function descriptor, of which the first word
595 is the entry address. */
596 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +0000597 return (void*)(descr[0]);
598#else
599# error "Unknown platform"
600#endif
601}
602
njnf536bbb2005-06-13 04:21:38 +0000603/*--------------------------------------------------------------------*/
604/*--- end ---*/
605/*--------------------------------------------------------------------*/