blob: 3fe6f071fbab8223aecc509ff2149f75716bf78b [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
sewardjec062e82011-10-23 07:32:08 +00009 Copyright (C) 2000-2011 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;
njnf76d27a2009-05-28 01:53:07 +0000130# elif defined(VGO_darwin)
131 // GrP fixme darwin syscalls may return more values (2 registers plus error)
sewardjb5b87402011-03-07 16:05:35 +0000132# elif defined(VGP_s390x_linux)
133 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
134 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj9c606bd2008-09-18 18:12:50 +0000135# else
136# error "Unknown plat"
137# endif
138}
njnf536bbb2005-06-13 04:21:38 +0000139
sewardj7cf4e6b2008-05-01 20:24:26 +0000140void
141VG_(get_shadow_regs_area) ( ThreadId tid,
142 /*DST*/UChar* dst,
njnc4431bf2009-01-15 21:29:24 +0000143 /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size )
njnf536bbb2005-06-13 04:21:38 +0000144{
sewardj7cf4e6b2008-05-01 20:24:26 +0000145 void* src;
njnf536bbb2005-06-13 04:21:38 +0000146 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000147 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000148 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000149 // Bounds check
150 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
151 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000152 // Copy
153 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000154 src = NULL;
155 switch (shadowNo) {
156 case 0: src = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
157 case 1: src = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
158 case 2: src = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
159 }
160 tl_assert(src != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000161 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000162}
163
sewardj7cf4e6b2008-05-01 20:24:26 +0000164void
165VG_(set_shadow_regs_area) ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +0000166 /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
sewardj7cf4e6b2008-05-01 20:24:26 +0000167 /*SRC*/const UChar* src )
njnf536bbb2005-06-13 04:21:38 +0000168{
sewardj7cf4e6b2008-05-01 20:24:26 +0000169 void* dst;
njnf536bbb2005-06-13 04:21:38 +0000170 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000171 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000172 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000173 // Bounds check
174 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
175 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000176 // Copy
177 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000178 dst = NULL;
179 switch (shadowNo) {
180 case 0: dst = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
181 case 1: dst = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
182 case 2: dst = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
183 }
184 tl_assert(dst != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000185 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000186}
187
188
philippea22f59d2012-01-26 23:13:52 +0000189static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId, HChar*, Addr))
njn6ace3ea2005-06-17 03:06:27 +0000190{
philippea22f59d2012-01-26 23:13:52 +0000191 VexGuestArchState* vex = &(VG_(get_ThreadState)(tid)->arch.vex);
njn6ace3ea2005-06-17 03:06:27 +0000192#if defined(VGA_x86)
philippea22f59d2012-01-26 23:13:52 +0000193 (*f)(tid, "EAX", vex->guest_EAX);
194 (*f)(tid, "ECX", vex->guest_ECX);
195 (*f)(tid, "EDX", vex->guest_EDX);
196 (*f)(tid, "EBX", vex->guest_EBX);
197 (*f)(tid, "ESI", vex->guest_ESI);
198 (*f)(tid, "EDI", vex->guest_EDI);
199 (*f)(tid, "ESP", vex->guest_ESP);
200 (*f)(tid, "EBP", vex->guest_EBP);
njn6ace3ea2005-06-17 03:06:27 +0000201#elif defined(VGA_amd64)
philippea22f59d2012-01-26 23:13:52 +0000202 (*f)(tid, "RAX", vex->guest_RAX);
203 (*f)(tid, "RCX", vex->guest_RCX);
204 (*f)(tid, "RDX", vex->guest_RDX);
205 (*f)(tid, "RBX", vex->guest_RBX);
206 (*f)(tid, "RSI", vex->guest_RSI);
207 (*f)(tid, "RDI", vex->guest_RDI);
208 (*f)(tid, "RSP", vex->guest_RSP);
209 (*f)(tid, "RBP", vex->guest_RBP);
210 (*f)(tid, "R8" , vex->guest_R8 );
211 (*f)(tid, "R9" , vex->guest_R9 );
212 (*f)(tid, "R10", vex->guest_R10);
213 (*f)(tid, "R11", vex->guest_R11);
214 (*f)(tid, "R12", vex->guest_R12);
215 (*f)(tid, "R13", vex->guest_R13);
216 (*f)(tid, "R14", vex->guest_R14);
217 (*f)(tid, "R15", vex->guest_R15);
sewardj2c48c7b2005-11-29 13:05:56 +0000218#elif defined(VGA_ppc32) || defined(VGA_ppc64)
philippea22f59d2012-01-26 23:13:52 +0000219 (*f)(tid, "GPR0" , vex->guest_GPR0 );
220 (*f)(tid, "GPR1" , vex->guest_GPR1 );
221 (*f)(tid, "GPR2" , vex->guest_GPR2 );
222 (*f)(tid, "GPR3" , vex->guest_GPR3 );
223 (*f)(tid, "GPR4" , vex->guest_GPR4 );
224 (*f)(tid, "GPR5" , vex->guest_GPR5 );
225 (*f)(tid, "GPR6" , vex->guest_GPR6 );
226 (*f)(tid, "GPR7" , vex->guest_GPR7 );
227 (*f)(tid, "GPR8" , vex->guest_GPR8 );
228 (*f)(tid, "GPR9" , vex->guest_GPR9 );
229 (*f)(tid, "GPR10", vex->guest_GPR10);
230 (*f)(tid, "GPR11", vex->guest_GPR11);
231 (*f)(tid, "GPR12", vex->guest_GPR12);
232 (*f)(tid, "GPR13", vex->guest_GPR13);
233 (*f)(tid, "GPR14", vex->guest_GPR14);
234 (*f)(tid, "GPR15", vex->guest_GPR15);
235 (*f)(tid, "GPR16", vex->guest_GPR16);
236 (*f)(tid, "GPR17", vex->guest_GPR17);
237 (*f)(tid, "GPR18", vex->guest_GPR18);
238 (*f)(tid, "GPR19", vex->guest_GPR19);
239 (*f)(tid, "GPR20", vex->guest_GPR20);
240 (*f)(tid, "GPR21", vex->guest_GPR21);
241 (*f)(tid, "GPR22", vex->guest_GPR22);
242 (*f)(tid, "GPR23", vex->guest_GPR23);
243 (*f)(tid, "GPR24", vex->guest_GPR24);
244 (*f)(tid, "GPR25", vex->guest_GPR25);
245 (*f)(tid, "GPR26", vex->guest_GPR26);
246 (*f)(tid, "GPR27", vex->guest_GPR27);
247 (*f)(tid, "GPR28", vex->guest_GPR28);
248 (*f)(tid, "GPR29", vex->guest_GPR29);
249 (*f)(tid, "GPR30", vex->guest_GPR30);
250 (*f)(tid, "GPR31", vex->guest_GPR31);
251 (*f)(tid, "CTR" , vex->guest_CTR );
252 (*f)(tid, "LR" , vex->guest_LR );
sewardj59570ff2010-01-01 11:59:33 +0000253#elif defined(VGA_arm)
philippea22f59d2012-01-26 23:13:52 +0000254 (*f)(tid, "R0" , vex->guest_R0 );
255 (*f)(tid, "R1" , vex->guest_R1 );
256 (*f)(tid, "R2" , vex->guest_R2 );
257 (*f)(tid, "R3" , vex->guest_R3 );
258 (*f)(tid, "R4" , vex->guest_R4 );
259 (*f)(tid, "R5" , vex->guest_R5 );
260 (*f)(tid, "R6" , vex->guest_R6 );
261 (*f)(tid, "R8" , vex->guest_R8 );
262 (*f)(tid, "R9" , vex->guest_R9 );
263 (*f)(tid, "R10", vex->guest_R10);
264 (*f)(tid, "R11", vex->guest_R11);
265 (*f)(tid, "R12", vex->guest_R12);
266 (*f)(tid, "R13", vex->guest_R13);
267 (*f)(tid, "R14", vex->guest_R14);
sewardjb5b87402011-03-07 16:05:35 +0000268#elif defined(VGA_s390x)
philippea22f59d2012-01-26 23:13:52 +0000269 (*f)(tid, "r0" , vex->guest_r0 );
270 (*f)(tid, "r1" , vex->guest_r1 );
271 (*f)(tid, "r2" , vex->guest_r2 );
272 (*f)(tid, "r3" , vex->guest_r3 );
273 (*f)(tid, "r4" , vex->guest_r4 );
274 (*f)(tid, "r5" , vex->guest_r5 );
275 (*f)(tid, "r6" , vex->guest_r6 );
276 (*f)(tid, "r7" , vex->guest_r7 );
277 (*f)(tid, "r8" , vex->guest_r8 );
278 (*f)(tid, "r9" , vex->guest_r9 );
279 (*f)(tid, "r10", vex->guest_r10);
280 (*f)(tid, "r11", vex->guest_r11);
281 (*f)(tid, "r12", vex->guest_r12);
282 (*f)(tid, "r13", vex->guest_r13);
283 (*f)(tid, "r14", vex->guest_r14);
284 (*f)(tid, "r15", vex->guest_r15);
njn6ace3ea2005-06-17 03:06:27 +0000285#else
286# error Unknown arch
287#endif
288}
289
290
philippea22f59d2012-01-26 23:13:52 +0000291void VG_(apply_to_GP_regs)(void (*f)(ThreadId, HChar*, UWord))
njn6ace3ea2005-06-17 03:06:27 +0000292{
293 ThreadId tid;
294
295 for (tid = 1; tid < VG_N_THREADS; tid++) {
296 if (VG_(is_valid_tid)(tid)) {
philippea22f59d2012-01-26 23:13:52 +0000297 apply_to_GPs_of_tid(tid, f);
njn6ace3ea2005-06-17 03:06:27 +0000298 }
299 }
300}
301
sewardjb8b79ad2008-03-03 01:35:41 +0000302void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
njnb506bd82005-06-21 04:01:51 +0000303{
sewardjb8b79ad2008-03-03 01:35:41 +0000304 *tid = (ThreadId)(-1);
njnb506bd82005-06-21 04:01:51 +0000305}
njn6ace3ea2005-06-17 03:06:27 +0000306
sewardjb8b79ad2008-03-03 01:35:41 +0000307Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
308 /*OUT*/Addr* stack_min,
309 /*OUT*/Addr* stack_max)
njn1d0cb0d2005-08-15 01:52:02 +0000310{
311 ThreadId i;
sewardjb8b79ad2008-03-03 01:35:41 +0000312 for (i = (*tid)+1; i < VG_N_THREADS; i++) {
313 if (i == VG_INVALID_THREADID)
314 continue;
njn1d0cb0d2005-08-15 01:52:02 +0000315 if (VG_(threads)[i].status != VgTs_Empty) {
316 *tid = i;
317 *stack_min = VG_(get_SP)(i);
318 *stack_max = VG_(threads)[i].client_stack_highest_word;
njn1d0cb0d2005-08-15 01:52:02 +0000319 return True;
320 }
321 }
322 return False;
323}
sewardj7821e2e2005-08-08 00:35:46 +0000324
sewardjbbec7722007-11-25 14:08:53 +0000325Addr VG_(thread_get_stack_max)(ThreadId tid)
326{
327 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
328 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
329 return VG_(threads)[tid].client_stack_highest_word;
330}
331
bart0fb03202008-03-29 09:25:53 +0000332SizeT VG_(thread_get_stack_size)(ThreadId tid)
333{
334 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
335 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
336 return VG_(threads)[tid].client_stack_szB;
337}
338
bart83c5a922010-09-02 14:38:38 +0000339Addr VG_(thread_get_altstack_min)(ThreadId tid)
340{
341 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
342 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
343 return (Addr)VG_(threads)[tid].altstack.ss_sp;
344}
345
346SizeT VG_(thread_get_altstack_size)(ThreadId tid)
347{
348 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
349 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
350 return VG_(threads)[tid].altstack.ss_size;
351}
352
sewardje2d1e672005-11-12 23:10:48 +0000353//-------------------------------------------------------------
354/* Details about the capabilities of the underlying (host) CPU. These
355 details are acquired by (1) enquiring with the CPU at startup, or
356 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
357 line size). It's a bit nasty in the sense that there's no obvious
358 way to stop uses of some of this info before it's ready to go.
florian0daa4e32012-04-22 02:48:20 +0000359 See pub_core_machine.h for more information about that.
sewardjb5b87402011-03-07 16:05:35 +0000360
sewardje2d1e672005-11-12 23:10:48 +0000361 VG_(machine_get_hwcaps) may use signals (although it attempts to
362 leave signal state unchanged) and therefore should only be
363 called before m_main sets up the client's signal state.
364*/
365
366/* --------- State --------- */
sewardj59570ff2010-01-01 11:59:33 +0000367static Bool hwcaps_done = False;
sewardje2d1e672005-11-12 23:10:48 +0000368
369/* --- all archs --- */
370static VexArch va;
371static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000372
sewardj7821e2e2005-08-08 00:35:46 +0000373#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000374UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000375#endif
sewardje2d1e672005-11-12 23:10:48 +0000376#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000377UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000378UInt VG_(machine_ppc32_has_VMX) = 0;
379#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000380#if defined(VGA_ppc64)
381ULong VG_(machine_ppc64_has_VMX) = 0;
382#endif
sewardj1dbd3372010-08-22 12:21:14 +0000383#if defined(VGA_arm)
384Int VG_(machine_arm_archlevel) = 4;
385#endif
sewardje2d1e672005-11-12 23:10:48 +0000386
sewardjb5b87402011-03-07 16:05:35 +0000387/* fixs390: anything for s390x here ? */
sewardje2d1e672005-11-12 23:10:48 +0000388
sewardj2c3f2ea2011-04-13 15:40:10 +0000389/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
sewardj6c591e12011-04-11 16:17:51 +0000390 testing, so we need a VG_MINIMAL_JMP_BUF. */
391#if defined(VGA_ppc32) || defined(VGA_ppc64) \
392 || defined(VGA_arm) || defined(VGA_s390x)
393#include "pub_tool_libcsetjmp.h"
sewardj97d3ebb2011-04-11 18:36:34 +0000394static VG_MINIMAL_JMP_BUF(env_unsup_insn);
sewardj6c591e12011-04-11 16:17:51 +0000395static void handler_unsup_insn ( Int x ) {
396 VG_MINIMAL_LONGJMP(env_unsup_insn);
397}
sewardj5ae70ce2010-09-08 15:12:33 +0000398#endif
399
sewardjb9c815b2010-09-03 15:51:34 +0000400
401/* Helper function for VG_(machine_get_hwcaps), assumes the SIGILL/etc
402 * handlers are installed. Determines the the sizes affected by dcbz
403 * and dcbzl instructions and updates the given VexArchInfo structure
404 * accordingly.
405 *
406 * Not very defensive: assumes that as long as the dcbz/dcbzl
407 * instructions don't raise a SIGILL, that they will zero an aligned,
408 * contiguous block of memory of a sensible size. */
sewardj5ae70ce2010-09-08 15:12:33 +0000409#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjb9c815b2010-09-03 15:51:34 +0000410static void find_ppc_dcbz_sz(VexArchInfo *arch_info)
411{
sewardjdcb3a592010-09-04 00:43:14 +0000412 Int dcbz_szB = 0;
sewardjb9c815b2010-09-03 15:51:34 +0000413 Int dcbzl_szB;
sewardj5ae70ce2010-09-08 15:12:33 +0000414# define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
sewardjb9c815b2010-09-03 15:51:34 +0000415 char test_block[4*MAX_DCBZL_SZB];
416 char *aligned = test_block;
417 Int i;
418
419 /* round up to next max block size, assumes MAX_DCBZL_SZB is pof2 */
420 aligned = (char *)(((HWord)aligned + MAX_DCBZL_SZB) & ~(MAX_DCBZL_SZB - 1));
421 vg_assert((aligned + MAX_DCBZL_SZB) <= &test_block[sizeof(test_block)]);
422
423 /* dcbz often clears 32B, although sometimes whatever the native cache
424 * block size is */
425 VG_(memset)(test_block, 0xff, sizeof(test_block));
426 __asm__ __volatile__("dcbz 0,%0"
427 : /*out*/
428 : "r" (aligned) /*in*/
429 : "memory" /*clobber*/);
430 for (dcbz_szB = 0, i = 0; i < sizeof(test_block); ++i) {
431 if (!test_block[i])
432 ++dcbz_szB;
433 }
434 vg_assert(dcbz_szB == 32 || dcbz_szB == 64 || dcbz_szB == 128);
435
436 /* dcbzl clears 128B on G5/PPC970, and usually 32B on other platforms */
sewardj6c591e12011-04-11 16:17:51 +0000437 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb9c815b2010-09-03 15:51:34 +0000438 dcbzl_szB = 0; /* indicates unsupported */
439 }
440 else {
441 VG_(memset)(test_block, 0xff, sizeof(test_block));
442 /* some older assemblers won't understand the dcbzl instruction
443 * variant, so we directly emit the instruction ourselves */
444 __asm__ __volatile__("mr 9, %0 ; .long 0x7C204FEC" /*dcbzl 0,9*/
445 : /*out*/
446 : "r" (aligned) /*in*/
447 : "memory", "r9" /*clobber*/);
448 for (dcbzl_szB = 0, i = 0; i < sizeof(test_block); ++i) {
449 if (!test_block[i])
450 ++dcbzl_szB;
451 }
452 vg_assert(dcbzl_szB == 32 || dcbzl_szB == 64 || dcbzl_szB == 128);
453 }
454
455 arch_info->ppc_dcbz_szB = dcbz_szB;
456 arch_info->ppc_dcbzl_szB = dcbzl_szB;
457
458 VG_(debugLog)(1, "machine", "dcbz_szB=%d dcbzl_szB=%d\n",
459 dcbz_szB, dcbzl_szB);
sewardj5ae70ce2010-09-08 15:12:33 +0000460# undef MAX_DCBZL_SZB
sewardjb9c815b2010-09-03 15:51:34 +0000461}
sewardj5ae70ce2010-09-08 15:12:33 +0000462#endif /* defined(VGA_ppc32) || defined(VGA_ppc64) */
463
sewardj2c3f2ea2011-04-13 15:40:10 +0000464#ifdef VGA_s390x
sewardj5ae70ce2010-09-08 15:12:33 +0000465
sewardj2c3f2ea2011-04-13 15:40:10 +0000466/* Read /proc/cpuinfo. Look for lines like these
467
468 processor 0: version = FF, identification = 0117C9, machine = 2064
469
florian4e63b8e2012-04-22 03:50:20 +0000470 and return the machine model. If the machine model could not be determined
471 or it is an unknown model, return VEX_S390X_MODEL_UNKNOWN. */
sewardj2c3f2ea2011-04-13 15:40:10 +0000472
473static UInt VG_(get_machine_model)(void)
474{
475 static struct model_map {
476 HChar name[5];
477 UInt id;
478 } model_map[] = {
479 { "2064", VEX_S390X_MODEL_Z900 },
480 { "2066", VEX_S390X_MODEL_Z800 },
481 { "2084", VEX_S390X_MODEL_Z990 },
482 { "2086", VEX_S390X_MODEL_Z890 },
483 { "2094", VEX_S390X_MODEL_Z9_EC },
484 { "2096", VEX_S390X_MODEL_Z9_BC },
485 { "2097", VEX_S390X_MODEL_Z10_EC },
486 { "2098", VEX_S390X_MODEL_Z10_BC },
487 { "2817", VEX_S390X_MODEL_Z196 },
florian258ede72011-09-02 22:20:41 +0000488 { "2818", VEX_S390X_MODEL_Z114 },
sewardj2c3f2ea2011-04-13 15:40:10 +0000489 };
490
491 Int model, n, fh;
492 SysRes fd;
493 SizeT num_bytes, file_buf_size;
494 HChar *p, *m, *model_name, *file_buf;
495
496 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
497 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
florian4e63b8e2012-04-22 03:50:20 +0000498 if ( sr_isError(fd) ) return VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000499
500 fh = sr_Res(fd);
501
502 /* Determine the size of /proc/cpuinfo.
503 Work around broken-ness in /proc file system implementation.
504 fstat returns a zero size for /proc/cpuinfo although it is
505 claimed to be a regular file. */
506 num_bytes = 0;
507 file_buf_size = 1000;
508 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
509 while (42) {
510 n = VG_(read)(fh, file_buf, file_buf_size);
511 if (n < 0) break;
512
513 num_bytes += n;
514 if (n < file_buf_size) break; /* reached EOF */
515 }
516
517 if (n < 0) num_bytes = 0; /* read error; ignore contents */
518
519 if (num_bytes > file_buf_size) {
520 VG_(free)( file_buf );
521 VG_(lseek)( fh, 0, VKI_SEEK_SET );
522 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
523 n = VG_(read)( fh, file_buf, num_bytes );
524 if (n < 0) num_bytes = 0;
525 }
526
527 file_buf[num_bytes] = '\0';
528 VG_(close)(fh);
529
530 /* Parse file */
florian4e63b8e2012-04-22 03:50:20 +0000531 model = VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000532 for (p = file_buf; *p; ++p) {
533 /* Beginning of line */
534 if (VG_(strncmp)( p, "processor", sizeof "processor" - 1 ) != 0) continue;
535
536 m = VG_(strstr)( p, "machine" );
537 if (m == NULL) continue;
538
539 p = m + sizeof "machine" - 1;
540 while ( VG_(isspace)( *p ) || *p == '=') {
541 if (*p == '\n') goto next_line;
542 ++p;
543 }
544
545 model_name = p;
546 for (n = 0; n < sizeof model_map / sizeof model_map[0]; ++n) {
547 struct model_map *mm = model_map + n;
548 SizeT len = VG_(strlen)( mm->name );
549 if ( VG_(strncmp)( mm->name, model_name, len ) == 0 &&
550 VG_(isspace)( model_name[len] )) {
551 if (mm->id < model) model = mm->id;
552 p = model_name + len;
553 break;
554 }
555 }
556 /* Skip until end-of-line */
557 while (*p != '\n')
558 ++p;
559 next_line: ;
560 }
561
562 VG_(free)( file_buf );
florian00164922011-10-25 21:37:15 +0000563 VG_(debugLog)(1, "machine", "model = %s\n",
florian4e63b8e2012-04-22 03:50:20 +0000564 model == VEX_S390X_MODEL_UNKNOWN ? "UNKNOWN"
florian00164922011-10-25 21:37:15 +0000565 : model_map[model].name);
sewardj2c3f2ea2011-04-13 15:40:10 +0000566 return model;
567}
568
569#endif /* VGA_s390x */
sewardj5ae70ce2010-09-08 15:12:33 +0000570
571/* Determine what insn set and insn set variant the host has, and
572 record it. To be called once at system startup. Returns False if
573 this a CPU incapable of running Valgrind. */
sewardje3826cf2005-11-13 00:30:22 +0000574
sewardje2d1e672005-11-12 23:10:48 +0000575Bool VG_(machine_get_hwcaps)( void )
576{
577 vg_assert(hwcaps_done == False);
578 hwcaps_done = True;
579
580 // Whack default settings into vai, so that we only need to fill in
581 // any interesting bits.
582 LibVEX_default_VexArchInfo(&vai);
583
584#if defined(VGA_x86)
sewardj40d91c72010-07-29 15:40:32 +0000585 { Bool have_sse1, have_sse2, have_cx8, have_lzcnt;
sewardjc7ffc942011-03-28 16:26:42 +0000586 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000587 UChar vstr[13];
588 vstr[0] = 0;
sewardje2d1e672005-11-12 23:10:48 +0000589
590 if (!VG_(has_cpuid)())
591 /* we can't do cpuid at all. Give up. */
592 return False;
593
tomad8a5912011-06-10 15:04:22 +0000594 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000595 if (eax < 1)
596 /* we can't ask for cpuid(x) for x > 0. Give up. */
597 return False;
598
sewardj40d91c72010-07-29 15:40:32 +0000599 /* Get processor ID string, and max basic/extended index
600 values. */
sewardj40d91c72010-07-29 15:40:32 +0000601 VG_(memcpy)(&vstr[0], &ebx, 4);
602 VG_(memcpy)(&vstr[4], &edx, 4);
603 VG_(memcpy)(&vstr[8], &ecx, 4);
604 vstr[12] = 0;
605
tomad8a5912011-06-10 15:04:22 +0000606 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000607 max_extended = eax;
608
sewardje2d1e672005-11-12 23:10:48 +0000609 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000610 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000611
612 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
613 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
614
sewardj1c0ce7a2009-07-01 08:10:49 +0000615 /* cmpxchg8b is a minimum requirement now; if we don't have it we
616 must simply give up. But all CPUs since Pentium-I have it, so
617 that doesn't seem like much of a restriction. */
618 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
619 if (!have_cx8)
620 return False;
621
sewardj40d91c72010-07-29 15:40:32 +0000622 /* Figure out if this is an AMD that can do LZCNT. */
623 have_lzcnt = False;
624 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
625 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000626 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000627 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
628 }
629
sewardje2d1e672005-11-12 23:10:48 +0000630 if (have_sse2 && have_sse1) {
631 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000632 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
633 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardj40d91c72010-07-29 15:40:32 +0000634 if (have_lzcnt)
635 vai.hwcaps |= VEX_HWCAPS_X86_LZCNT;
sewardje2d1e672005-11-12 23:10:48 +0000636 VG_(machine_x86_have_mxcsr) = 1;
637 return True;
638 }
639
640 if (have_sse1) {
641 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000642 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000643 VG_(machine_x86_have_mxcsr) = 1;
644 return True;
645 }
646
sewardje3121f32006-01-27 21:23:23 +0000647 va = VexArchX86;
648 vai.hwcaps = 0; /*baseline - no sse at all*/
sewardje2d1e672005-11-12 23:10:48 +0000649 VG_(machine_x86_have_mxcsr) = 0;
650 return True;
651 }
652
653#elif defined(VGA_amd64)
sewardjc7ffc942011-03-28 16:26:42 +0000654 { Bool have_sse3, have_cx8, have_cx16;
sewardj40d91c72010-07-29 15:40:32 +0000655 Bool have_lzcnt;
sewardjc7ffc942011-03-28 16:26:42 +0000656 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000657 UChar vstr[13];
658 vstr[0] = 0;
sewardj1c0ce7a2009-07-01 08:10:49 +0000659
660 if (!VG_(has_cpuid)())
661 /* we can't do cpuid at all. Give up. */
662 return False;
663
tomad8a5912011-06-10 15:04:22 +0000664 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000665 if (eax < 1)
666 /* we can't ask for cpuid(x) for x > 0. Give up. */
667 return False;
668
sewardj40d91c72010-07-29 15:40:32 +0000669 /* Get processor ID string, and max basic/extended index
670 values. */
sewardj40d91c72010-07-29 15:40:32 +0000671 VG_(memcpy)(&vstr[0], &ebx, 4);
672 VG_(memcpy)(&vstr[4], &edx, 4);
673 VG_(memcpy)(&vstr[8], &ecx, 4);
674 vstr[12] = 0;
675
tomad8a5912011-06-10 15:04:22 +0000676 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000677 max_extended = eax;
678
sewardj1c0ce7a2009-07-01 08:10:49 +0000679 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000680 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000681
sewardjc7ffc942011-03-28 16:26:42 +0000682 // we assume that SSE1 and SSE2 are available by default
sewardj598971e2009-07-12 13:19:04 +0000683 have_sse3 = (ecx & (1<<0)) != 0; /* True => have sse3 insns */
sewardj40d91c72010-07-29 15:40:32 +0000684 // ssse3 is ecx:9
685 // sse41 is ecx:19
686 // sse42 is ecx:20
sewardj1c0ce7a2009-07-01 08:10:49 +0000687
688 /* cmpxchg8b is a minimum requirement now; if we don't have it we
689 must simply give up. But all CPUs since Pentium-I have it, so
690 that doesn't seem like much of a restriction. */
691 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
692 if (!have_cx8)
693 return False;
694
695 /* on amd64 we tolerate older cpus, which don't have cmpxchg16b */
696 have_cx16 = (ecx & (1<<13)) != 0; /* True => have cmpxchg16b */
697
sewardj40d91c72010-07-29 15:40:32 +0000698 /* Figure out if this is an AMD that can do LZCNT. */
699 have_lzcnt = False;
700 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
701 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000702 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000703 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
704 }
705
sewardj1c0ce7a2009-07-01 08:10:49 +0000706 va = VexArchAMD64;
707 vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
sewardj40d91c72010-07-29 15:40:32 +0000708 | (have_cx16 ? VEX_HWCAPS_AMD64_CX16 : 0)
709 | (have_lzcnt ? VEX_HWCAPS_AMD64_LZCNT : 0);
sewardj1c0ce7a2009-07-01 08:10:49 +0000710 return True;
711 }
sewardje2d1e672005-11-12 23:10:48 +0000712
713#elif defined(VGA_ppc32)
bart1581e742009-01-13 07:49:14 +0000714 {
715 /* Find out which subset of the ppc32 instruction set is supported by
716 verifying whether various ppc32 instructions generate a SIGILL
717 or a SIGFPE. An alternative approach is to check the AT_HWCAP and
718 AT_PLATFORM entries in the ELF auxiliary table -- see also
719 the_iifii.client_auxv in m_main.c.
720 */
njncda2f0f2009-05-18 02:12:08 +0000721 vki_sigset_t saved_set, tmp_set;
722 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
723 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000724
sewardj5ba075a2012-04-02 21:25:14 +0000725 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
sewardj7637e9e2006-02-21 17:11:11 +0000726 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000727
njncda2f0f2009-05-18 02:12:08 +0000728 /* This is a kludge. Really we ought to back-convert saved_act
729 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
730 since that's a no-op on all ppc32 platforms so far supported,
731 it's not worth the typing effort. At least include most basic
732 sanity check: */
733 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
734
sewardje3826cf2005-11-13 00:30:22 +0000735 VG_(sigemptyset)(&tmp_set);
736 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000737 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardje3826cf2005-11-13 00:30:22 +0000738
sewardj7637e9e2006-02-21 17:11:11 +0000739 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
740 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000741
bart1581e742009-01-13 07:49:14 +0000742 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
sewardj7637e9e2006-02-21 17:11:11 +0000743 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000744 tmp_sigill_act = saved_sigill_act;
745
746 r = VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
747 vg_assert(r == 0);
748 tmp_sigfpe_act = saved_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000749
sewardj7637e9e2006-02-21 17:11:11 +0000750 /* NODEFER: signal handler does not return (from the kernel's point of
751 view), hence if it is to successfully catch a signal more than once,
752 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000753 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
754 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
755 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
756 tmp_sigill_act.ksa_handler = handler_unsup_insn;
757 r = VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
758 vg_assert(r == 0);
759
760 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
761 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
762 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
763 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
764 r = VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
765 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000766
sewardje3121f32006-01-27 21:23:23 +0000767 /* standard FP insns */
768 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000769 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000770 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000771 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000772 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000773 }
774
sewardje3121f32006-01-27 21:23:23 +0000775 /* Altivec insns */
776 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000777 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000778 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000779 } else {
sewardj71592122006-04-04 03:29:48 +0000780 /* Unfortunately some older assemblers don't speak Altivec (or
781 choose not to), so to be safe we directly emit the 32-bit
782 word corresponding to "vor 0,0,0". This fixes a build
783 problem that happens on Debian 3.1 (ppc32), and probably
784 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000785 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000786 }
787
sewardje3121f32006-01-27 21:23:23 +0000788 /* General-Purpose optional (fsqrt, fsqrts) */
789 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000790 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000791 have_FX = False;
792 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000793 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000794 }
795
796 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
797 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000798 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000799 have_GX = False;
800 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000801 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000802 }
803
sewardjf34eb492011-04-15 11:57:05 +0000804 /* VSX support implies Power ISA 2.06 */
805 have_VX = True;
806 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
807 have_VX = False;
808 } else {
809 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
810 }
811
sewardj5ba075a2012-04-02 21:25:14 +0000812 /* Check for Decimal Floating Point (DFP) support. */
813 have_DFP = True;
814 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
815 have_DFP = False;
816 } else {
817 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
818 }
sewardjf34eb492011-04-15 11:57:05 +0000819
sewardjb9c815b2010-09-03 15:51:34 +0000820 /* determine dcbz/dcbzl sizes while we still have the signal
821 * handlers registered */
822 find_ppc_dcbz_sz(&vai);
823
bart1581e742009-01-13 07:49:14 +0000824 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
825 vg_assert(r == 0);
826 r = VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj7637e9e2006-02-21 17:11:11 +0000827 vg_assert(r == 0);
828 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
829 vg_assert(r == 0);
sewardj5ba075a2012-04-02 21:25:14 +0000830 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +0000831 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +0000832 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +0000833 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
834 if (have_V && !have_F)
835 have_V = False;
836 if (have_FX && !have_F)
837 have_FX = False;
838 if (have_GX && !have_F)
839 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +0000840
sewardje3121f32006-01-27 21:23:23 +0000841 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
842 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000843
844 va = VexArchPPC32;
845
sewardje3121f32006-01-27 21:23:23 +0000846 vai.hwcaps = 0;
847 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
848 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
849 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
850 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardjf34eb492011-04-15 11:57:05 +0000851 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC32_VX;
sewardj5ba075a2012-04-02 21:25:14 +0000852 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC32_DFP;
853
sewardje3826cf2005-11-13 00:30:22 +0000854
855 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
856 called before we're ready to go. */
857 return True;
858 }
sewardje2d1e672005-11-12 23:10:48 +0000859
sewardj2c48c7b2005-11-29 13:05:56 +0000860#elif defined(VGA_ppc64)
bart1581e742009-01-13 07:49:14 +0000861 {
862 /* Same instruction set detection algorithm as for ppc32. */
njncda2f0f2009-05-18 02:12:08 +0000863 vki_sigset_t saved_set, tmp_set;
864 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
865 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardj2c48c7b2005-11-29 13:05:56 +0000866
sewardj5ba075a2012-04-02 21:25:14 +0000867 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
njncda2f0f2009-05-18 02:12:08 +0000868 Int r;
869
870 /* This is a kludge. Really we ought to back-convert saved_act
871 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
872 since that's a no-op on all ppc64 platforms so far supported,
873 it's not worth the typing effort. At least include most basic
874 sanity check: */
875 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
sewardj2c48c7b2005-11-29 13:05:56 +0000876
877 VG_(sigemptyset)(&tmp_set);
878 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000879 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardj2c48c7b2005-11-29 13:05:56 +0000880
njncda2f0f2009-05-18 02:12:08 +0000881 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
882 vg_assert(r == 0);
sewardj2c48c7b2005-11-29 13:05:56 +0000883
njncda2f0f2009-05-18 02:12:08 +0000884 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
885 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000886 tmp_sigill_act = saved_sigill_act;
887
888 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
889 tmp_sigfpe_act = saved_sigfpe_act;
890
sewardj7637e9e2006-02-21 17:11:11 +0000891 /* NODEFER: signal handler does not return (from the kernel's point of
892 view), hence if it is to successfully catch a signal more than once,
893 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000894 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
895 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
896 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
897 tmp_sigill_act.ksa_handler = handler_unsup_insn;
898 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
899
900 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
901 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
902 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
903 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
904 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +0000905
sewardje3121f32006-01-27 21:23:23 +0000906 /* standard FP insns */
907 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000908 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000909 have_F = False;
910 } else {
911 __asm__ __volatile__("fmr 0,0");
912 }
913
914 /* Altivec insns */
915 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000916 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000917 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +0000918 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000919 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +0000920 }
921
sewardje3121f32006-01-27 21:23:23 +0000922 /* General-Purpose optional (fsqrt, fsqrts) */
923 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000924 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000925 have_FX = False;
926 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000927 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000928 }
929
930 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
931 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000932 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000933 have_GX = False;
934 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000935 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000936 }
937
sewardjf34eb492011-04-15 11:57:05 +0000938 /* VSX support implies Power ISA 2.06 */
939 have_VX = True;
940 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
941 have_VX = False;
942 } else {
943 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
944 }
945
sewardj5ba075a2012-04-02 21:25:14 +0000946 /* Check for Decimal Floating Point (DFP) support. */
947 have_DFP = True;
948 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
949 have_DFP = False;
950 } else {
951 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
952 }
953
sewardjb9c815b2010-09-03 15:51:34 +0000954 /* determine dcbz/dcbzl sizes while we still have the signal
955 * handlers registered */
956 find_ppc_dcbz_sz(&vai);
957
bart1581e742009-01-13 07:49:14 +0000958 VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
959 VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +0000960 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
sewardj5ba075a2012-04-02 21:25:14 +0000961 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +0000962 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +0000963 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +0000964 /* on ppc64, if we don't even have FP, just give up. */
965 if (!have_F)
966 return False;
967
968 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +0000969
970 va = VexArchPPC64;
sewardje3121f32006-01-27 21:23:23 +0000971
972 vai.hwcaps = 0;
973 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
974 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
975 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardjf34eb492011-04-15 11:57:05 +0000976 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC64_VX;
sewardj5ba075a2012-04-02 21:25:14 +0000977 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC64_DFP;
sewardj2c48c7b2005-11-29 13:05:56 +0000978
979 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
980 called before we're ready to go. */
981 return True;
982 }
983
sewardjb5b87402011-03-07 16:05:35 +0000984#elif defined(VGA_s390x)
985 {
986 /* Instruction set detection code borrowed from ppc above. */
987 vki_sigset_t saved_set, tmp_set;
988 vki_sigaction_fromK_t saved_sigill_act;
989 vki_sigaction_toK_t tmp_sigill_act;
990
sewardj1c6f6ab2011-04-27 12:00:51 +0000991 volatile Bool have_LDISP, have_EIMM, have_GIE, have_DFP, have_FGX;
floriand19733c2012-01-15 21:02:44 +0000992 volatile Bool have_STFLE, have_ETF2;
sewardj2c3f2ea2011-04-13 15:40:10 +0000993 Int r, model;
sewardjb5b87402011-03-07 16:05:35 +0000994
995 /* Unblock SIGILL and stash away the old action for that signal */
996 VG_(sigemptyset)(&tmp_set);
997 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
998
999 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1000 vg_assert(r == 0);
1001
1002 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1003 vg_assert(r == 0);
1004 tmp_sigill_act = saved_sigill_act;
1005
1006 /* NODEFER: signal handler does not return (from the kernel's point of
1007 view), hence if it is to successfully catch a signal more than once,
1008 we need the NODEFER flag. */
1009 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1010 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1011 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1012 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1013 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1014
1015 /* Determine hwcaps. Note, we cannot use the stfle insn because it
1016 is not supported on z900. */
1017
1018 have_LDISP = True;
sewardj6c591e12011-04-11 16:17:51 +00001019 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001020 have_LDISP = False;
1021 } else {
1022 /* BASR loads the address of the next insn into r1. Needed to avoid
1023 a segfault in XY. */
1024 __asm__ __volatile__("basr %%r1,%%r0\n\t"
1025 ".long 0xe3001000\n\t" /* XY 0,0(%r1) */
1026 ".short 0x0057" : : : "r0", "r1", "cc", "memory");
1027 }
1028
1029 have_EIMM = True;
sewardj6c591e12011-04-11 16:17:51 +00001030 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001031 have_EIMM = False;
1032 } else {
1033 __asm__ __volatile__(".long 0xc0090000\n\t" /* iilf r0,0 */
1034 ".short 0x0000" : : : "r0", "memory");
1035 }
1036
1037 have_GIE = True;
sewardj6c591e12011-04-11 16:17:51 +00001038 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001039 have_GIE = False;
1040 } else {
1041 __asm__ __volatile__(".long 0xc2010000\n\t" /* msfi r0,0 */
1042 ".short 0x0000" : : : "r0", "memory");
1043 }
1044
1045 have_DFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001046 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001047 have_DFP = False;
1048 } else {
1049 __asm__ __volatile__(".long 0xb3d20000"
1050 : : : "r0", "cc", "memory"); /* adtr r0,r0,r0 */
1051 }
1052
sewardj1c6f6ab2011-04-27 12:00:51 +00001053 have_FGX = True;
1054 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1055 have_FGX = False;
1056 } else {
1057 __asm__ __volatile__(".long 0xb3cd0000" : : : "r0"); /* lgdr r0,f0 */
1058 }
1059
floriand19733c2012-01-15 21:02:44 +00001060 /* Detect presence of the ETF2-enhancement facility using the
1061 STFLE insn. Note, that STFLE and ETF2 were introduced at the same
1062 time, so the absence of STLFE implies the absence of ETF2. */
1063 have_STFLE = True;
1064 have_ETF2 = False;
1065 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1066 have_STFLE = False;
1067 } else {
1068 ULong hoststfle[1];
1069 register ULong reg0 asm("0") = 0; /* one double word available */
1070
1071 __asm__ __volatile__(" .insn s,0xb2b00000,%0\n" /* stfle */
1072 : "=m" (hoststfle), "+d"(reg0)
1073 : : "cc", "memory");
1074 if (hoststfle[0] & (1ULL << (63 - 24)))
1075 have_ETF2 = True;
1076 }
1077
sewardjb5b87402011-03-07 16:05:35 +00001078 /* Restore signals */
1079 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1080 vg_assert(r == 0);
1081 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1082 vg_assert(r == 0);
sewardjb5b87402011-03-07 16:05:35 +00001083 va = VexArchS390X;
1084
sewardj2c3f2ea2011-04-13 15:40:10 +00001085 model = VG_(get_machine_model)();
1086
florian4e63b8e2012-04-22 03:50:20 +00001087 /* If the model is "unknown" don't treat this as an error. Assume
1088 this is a brand-new machine model for which we don't have the
1089 identification yet. Keeping fingers crossed. */
1090
sewardj1c6f6ab2011-04-27 12:00:51 +00001091 VG_(debugLog)(1, "machine", "machine %d LDISP %d EIMM %d GIE %d DFP %d "
floriand19733c2012-01-15 21:02:44 +00001092 "FGX %d STFLE %d ETF2 %d\n", model, have_LDISP, have_EIMM,
1093 have_GIE, have_DFP, have_FGX, have_STFLE, have_ETF2);
sewardj2c3f2ea2011-04-13 15:40:10 +00001094
sewardj2c3f2ea2011-04-13 15:40:10 +00001095 vai.hwcaps = model;
1096 if (have_LDISP) {
1097 /* Use long displacement only on machines >= z990. For all other machines
1098 it is millicoded and therefore slow. */
1099 if (model >= VEX_S390X_MODEL_Z990)
1100 vai.hwcaps |= VEX_HWCAPS_S390X_LDISP;
1101 }
sewardjb5b87402011-03-07 16:05:35 +00001102 if (have_EIMM) vai.hwcaps |= VEX_HWCAPS_S390X_EIMM;
1103 if (have_GIE) vai.hwcaps |= VEX_HWCAPS_S390X_GIE;
1104 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_S390X_DFP;
sewardj1c6f6ab2011-04-27 12:00:51 +00001105 if (have_FGX) vai.hwcaps |= VEX_HWCAPS_S390X_FGX;
floriand19733c2012-01-15 21:02:44 +00001106 if (have_ETF2) vai.hwcaps |= VEX_HWCAPS_S390X_ETF2;
florian68aba522012-04-21 15:43:25 +00001107 if (have_STFLE) vai.hwcaps |= VEX_HWCAPS_S390X_STFLE;
sewardjb5b87402011-03-07 16:05:35 +00001108
sewardj2c3f2ea2011-04-13 15:40:10 +00001109 VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
1110
sewardjb5b87402011-03-07 16:05:35 +00001111 return True;
1112 }
1113
sewardj59570ff2010-01-01 11:59:33 +00001114#elif defined(VGA_arm)
1115 {
sewardj1dbd3372010-08-22 12:21:14 +00001116 /* Same instruction set detection algorithm as for ppc32. */
1117 vki_sigset_t saved_set, tmp_set;
1118 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
1119 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
1120
1121 volatile Bool have_VFP, have_VFP2, have_VFP3, have_NEON;
1122 volatile Int archlevel;
1123 Int r;
1124
1125 /* This is a kludge. Really we ought to back-convert saved_act
1126 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1127 since that's a no-op on all ppc64 platforms so far supported,
1128 it's not worth the typing effort. At least include most basic
1129 sanity check: */
1130 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
1131
1132 VG_(sigemptyset)(&tmp_set);
1133 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1134 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
1135
1136 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1137 vg_assert(r == 0);
1138
1139 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1140 vg_assert(r == 0);
1141 tmp_sigill_act = saved_sigill_act;
1142
1143 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1144 tmp_sigfpe_act = saved_sigfpe_act;
1145
1146 /* NODEFER: signal handler does not return (from the kernel's point of
1147 view), hence if it is to successfully catch a signal more than once,
1148 we need the NODEFER flag. */
1149 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1150 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1151 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1152 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1153 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1154
1155 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1156 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1157 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1158 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1159 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1160
1161 /* VFP insns */
1162 have_VFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001163 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001164 have_VFP = False;
1165 } else {
1166 __asm__ __volatile__(".word 0xEEB02B42"); /* VMOV.F64 d2, d2 */
1167 }
1168 /* There are several generation of VFP extension but they differs very
1169 little so for now we will not distinguish them. */
1170 have_VFP2 = have_VFP;
1171 have_VFP3 = have_VFP;
1172
1173 /* NEON insns */
1174 have_NEON = True;
sewardj6c591e12011-04-11 16:17:51 +00001175 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001176 have_NEON = False;
1177 } else {
1178 __asm__ __volatile__(".word 0xF2244154"); /* VMOV q2, q2 */
1179 }
1180
1181 /* ARM architecture level */
1182 archlevel = 5; /* v5 will be base level */
1183 if (archlevel < 7) {
1184 archlevel = 7;
sewardj6c591e12011-04-11 16:17:51 +00001185 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001186 archlevel = 5;
1187 } else {
1188 __asm__ __volatile__(".word 0xF45FF000"); /* PLI [PC,#-0] */
1189 }
1190 }
1191 if (archlevel < 6) {
1192 archlevel = 6;
sewardj6c591e12011-04-11 16:17:51 +00001193 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001194 archlevel = 5;
1195 } else {
1196 __asm__ __volatile__(".word 0xE6822012"); /* PKHBT r2, r2, r2 */
1197 }
1198 }
1199
1200 VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
1201 VG_(convert_sigaction_fromK_to_toK)(&saved_sigfpe_act, &tmp_sigfpe_act);
1202 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1203 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1204 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1205
1206 VG_(debugLog)(1, "machine", "ARMv%d VFP %d VFP2 %d VFP3 %d NEON %d\n",
1207 archlevel, (Int)have_VFP, (Int)have_VFP2, (Int)have_VFP3,
1208 (Int)have_NEON);
1209
1210 VG_(machine_arm_archlevel) = archlevel;
1211
sewardj59570ff2010-01-01 11:59:33 +00001212 va = VexArchARM;
sewardj1dbd3372010-08-22 12:21:14 +00001213
1214 vai.hwcaps = VEX_ARM_ARCHLEVEL(archlevel);
1215 if (have_VFP3) vai.hwcaps |= VEX_HWCAPS_ARM_VFP3;
1216 if (have_VFP2) vai.hwcaps |= VEX_HWCAPS_ARM_VFP2;
1217 if (have_VFP) vai.hwcaps |= VEX_HWCAPS_ARM_VFP;
1218 if (have_NEON) vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1219
sewardj59570ff2010-01-01 11:59:33 +00001220 return True;
1221 }
1222
sewardje2d1e672005-11-12 23:10:48 +00001223#else
1224# error "Unknown arch"
1225#endif
1226}
1227
sewardj2c48c7b2005-11-29 13:05:56 +00001228/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +00001229#if defined(VGA_ppc32)
1230void VG_(machine_ppc32_set_clszB)( Int szB )
1231{
1232 vg_assert(hwcaps_done);
1233
1234 /* Either the value must not have been set yet (zero) or we can
1235 tolerate it being set to the same value multiple times, as the
1236 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001237 vg_assert(vai.ppc_cache_line_szB == 0
1238 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +00001239
sewardj89230ca2008-05-29 16:39:57 +00001240 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001241 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +00001242}
1243#endif
1244
sewardje2d1e672005-11-12 23:10:48 +00001245
sewardj2c48c7b2005-11-29 13:05:56 +00001246/* Notify host cpu cache line size. */
1247#if defined(VGA_ppc64)
1248void VG_(machine_ppc64_set_clszB)( Int szB )
1249{
1250 vg_assert(hwcaps_done);
1251
1252 /* Either the value must not have been set yet (zero) or we can
1253 tolerate it being set to the same value multiple times, as the
1254 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001255 vg_assert(vai.ppc_cache_line_szB == 0
1256 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +00001257
sewardj89230ca2008-05-29 16:39:57 +00001258 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001259 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +00001260}
1261#endif
1262
1263
sewardja3551be2010-09-09 07:25:58 +00001264/* Notify host's ability to handle NEON instructions. */
1265#if defined(VGA_arm)
1266void VG_(machine_arm_set_has_NEON)( Bool has_neon )
1267{
1268 vg_assert(hwcaps_done);
1269 /* There's nothing else we can sanity check. */
1270
1271 if (has_neon) {
1272 vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1273 } else {
1274 vai.hwcaps &= ~VEX_HWCAPS_ARM_NEON;
1275 }
1276}
1277#endif
1278
1279
sewardje2d1e672005-11-12 23:10:48 +00001280/* Fetch host cpu info, once established. */
1281void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
1282 /*OUT*/VexArchInfo* pVai )
1283{
1284 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +00001285 if (pVa) *pVa = va;
1286 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +00001287}
sewardj7821e2e2005-08-08 00:35:46 +00001288
1289
sewardj53ee1fc2005-12-23 02:29:58 +00001290// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +00001291// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +00001292void* VG_(fnptr_to_fnentry)( void* f )
1293{
sewardj6e9de462011-06-28 07:25:29 +00001294# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
1295 || defined(VGP_arm_linux) \
1296 || defined(VGP_ppc32_linux) || defined(VGO_darwin) \
1297 || defined(VGP_s390x_linux)
sewardj53ee1fc2005-12-23 02:29:58 +00001298 return f;
sewardj6e9de462011-06-28 07:25:29 +00001299# elif defined(VGP_ppc64_linux)
1300 /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
1301 3-word function descriptor, of which the first word is the entry
1302 address. */
sewardjf1c91e02006-10-17 01:35:58 +00001303 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +00001304 return (void*)(descr[0]);
sewardj6e9de462011-06-28 07:25:29 +00001305# else
1306# error "Unknown platform"
1307# endif
sewardj53ee1fc2005-12-23 02:29:58 +00001308}
1309
njnf536bbb2005-06-13 04:21:38 +00001310/*--------------------------------------------------------------------*/
1311/*--- end ---*/
1312/*--------------------------------------------------------------------*/