blob: 682aadc589265555a0934c9862b7d178effad367 [file] [log] [blame]
cerion896a1372005-01-25 12:24:25 +00001
2/*---------------------------------------------------------------*/
sewardj752f9062010-05-03 21:38:49 +00003/*--- begin guest_ppc_helpers.c ---*/
cerion896a1372005-01-25 12:24:25 +00004/*---------------------------------------------------------------*/
5
6/*
sewardj752f9062010-05-03 21:38:49 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
cerion896a1372005-01-25 12:24:25 +00009
sewardj89ae8472013-10-18 14:12:58 +000010 Copyright (C) 2004-2013 OpenWorks LLP
sewardj752f9062010-05-03 21:38:49 +000011 info@open-works.net
cerion896a1372005-01-25 12:24:25 +000012
sewardj752f9062010-05-03 21:38:49 +000013 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.
cerion896a1372005-01-25 12:24:25 +000017
sewardj752f9062010-05-03 21:38:49 +000018 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., 51 Franklin Street, Fifth Floor, Boston, MA
sewardj7bd6ffe2005-08-03 16:07:36 +000026 02110-1301, USA.
27
sewardj752f9062010-05-03 21:38:49 +000028 The GNU General Public License is contained in the file COPYING.
cerion896a1372005-01-25 12:24:25 +000029
30 Neither the names of the U.S. Department of Energy nor the
31 University of California nor the names of its contributors may be
32 used to endorse or promote products derived from this software
33 without prior written permission.
cerion896a1372005-01-25 12:24:25 +000034*/
35
36#include "libvex_basictypes.h"
florian33b02432012-08-25 21:48:04 +000037#include "libvex_emnote.h"
cerion1515db92005-01-25 17:21:23 +000038#include "libvex_guest_ppc32.h"
ceriond953ebb2005-11-29 13:27:20 +000039#include "libvex_guest_ppc64.h"
cerion896a1372005-01-25 12:24:25 +000040#include "libvex_ir.h"
41#include "libvex.h"
42
sewardjcef7d3e2009-07-02 12:21:59 +000043#include "main_util.h"
philippe6c46bef2012-08-14 22:29:01 +000044#include "main_globals.h"
sewardjcef7d3e2009-07-02 12:21:59 +000045#include "guest_generic_bb_to_IR.h"
46#include "guest_ppc_defs.h"
cerion896a1372005-01-25 12:24:25 +000047
48
ceriond953ebb2005-11-29 13:27:20 +000049/* This file contains helper functions for ppc32 and ppc64 guest code.
50 Calls to these functions are generated by the back end. These
51 calls are of course in the host machine code and this file will be
52 compiled to host machine code, so that all makes sense.
cerion896a1372005-01-25 12:24:25 +000053
54 Only change the signatures of these helper functions very
55 carefully. If you change the signature here, you'll have to change
56 the parameters passed to it in the IR calls constructed by
ceriond0eae2d2005-12-23 11:43:01 +000057 guest-ppc/toIR.c.
cerion896a1372005-01-25 12:24:25 +000058*/
59
60
sewardj73a91972005-09-06 10:25:46 +000061/*---------------------------------------------------------------*/
62/*--- Misc integer helpers. ---*/
63/*---------------------------------------------------------------*/
64
65/* CALLED FROM GENERATED CODE */
66/* DIRTY HELPER (non-referentially-transparent) */
ceriond0eae2d2005-12-23 11:43:01 +000067/* Horrible hack. On non-ppc platforms, return 1. */
sewardj73a91972005-09-06 10:25:46 +000068/* Reads a complete, consistent 64-bit TB value. */
cerion5b2325f2005-12-23 00:55:09 +000069ULong ppcg_dirtyhelper_MFTB ( void )
sewardj73a91972005-09-06 10:25:46 +000070{
sewardjaca070a2006-10-17 00:28:22 +000071# if defined(__powerpc__) || defined(_AIX)
sewardj73a91972005-09-06 10:25:46 +000072 ULong res;
73 UInt lo, hi1, hi2;
74 while (1) {
75 __asm__ __volatile__ ("\n"
76 "\tmftbu %0\n"
77 "\tmftb %1\n"
78 "\tmftbu %2\n"
79 : "=r" (hi1), "=r" (lo), "=r" (hi2)
80 );
81 if (hi1 == hi2) break;
82 }
83 res = ((ULong)hi1) << 32;
84 res |= (ULong)lo;
85 return res;
86# else
87 return 1ULL;
88# endif
89}
90
91
cerion6f6c6a02005-09-13 18:41:09 +000092/* CALLED FROM GENERATED CODE */
sewardjabb321c2006-12-27 18:39:46 +000093/* DIRTY HELPER (non-referentially transparent) */
94UInt ppc32g_dirtyhelper_MFSPR_268_269 ( UInt r269 )
95{
96# if defined(__powerpc__) || defined(_AIX)
97 UInt spr;
98 if (r269) {
99 __asm__ __volatile__("mfspr %0,269" : "=b"(spr));
100 } else {
101 __asm__ __volatile__("mfspr %0,268" : "=b"(spr));
102 }
103 return spr;
104# else
105 return 0;
106# endif
107}
108
109
110/* CALLED FROM GENERATED CODE */
sewardj37b2ee82009-08-02 14:35:45 +0000111/* DIRTY HELPER (I'm not really sure what the side effects are) */
112UInt ppc32g_dirtyhelper_MFSPR_287 ( void )
113{
114# if defined(__powerpc__) || defined(_AIX)
115 UInt spr;
116 __asm__ __volatile__("mfspr %0,287" : "=b"(spr));
117 return spr;
118# else
119 return 0;
120# endif
121}
122
123
124/* CALLED FROM GENERATED CODE */
cerion6f6c6a02005-09-13 18:41:09 +0000125/* DIRTY HELPER (reads guest state, writes guest mem) */
126void ppc32g_dirtyhelper_LVS ( VexGuestPPC32State* gst,
sewardjd1470942005-10-22 02:01:16 +0000127 UInt vD_off, UInt sh, UInt shift_right )
cerion6f6c6a02005-09-13 18:41:09 +0000128{
sewardj197bd172005-10-12 11:34:33 +0000129 static
cerion6f6c6a02005-09-13 18:41:09 +0000130 UChar ref[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
131 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
132 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
133 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F };
sewardj197bd172005-10-12 11:34:33 +0000134 U128* pU128_src;
135 U128* pU128_dst;
136
sewardjd1470942005-10-22 02:01:16 +0000137 vassert( vD_off <= sizeof(VexGuestPPC32State)-8 );
138 vassert( sh <= 15 );
139 vassert( shift_right <= 1 );
140 if (shift_right)
sewardj197bd172005-10-12 11:34:33 +0000141 sh = 16-sh;
cerion6f6c6a02005-09-13 18:41:09 +0000142 /* else shift left */
143
sewardj197bd172005-10-12 11:34:33 +0000144 pU128_src = (U128*)&ref[sh];
sewardjd1470942005-10-22 02:01:16 +0000145 pU128_dst = (U128*)( ((UChar*)gst) + vD_off );
cerion6f6c6a02005-09-13 18:41:09 +0000146
147 (*pU128_dst)[0] = (*pU128_src)[0];
148 (*pU128_dst)[1] = (*pU128_src)[1];
149 (*pU128_dst)[2] = (*pU128_src)[2];
150 (*pU128_dst)[3] = (*pU128_src)[3];
151}
152
cerion5b2325f2005-12-23 00:55:09 +0000153/* CALLED FROM GENERATED CODE */
154/* DIRTY HELPER (reads guest state, writes guest mem) */
155void ppc64g_dirtyhelper_LVS ( VexGuestPPC64State* gst,
carll1f5fe1f2014-08-07 23:25:23 +0000156 UInt vD_off, UInt sh, UInt shift_right,
157 UInt endness )
cerion5b2325f2005-12-23 00:55:09 +0000158{
sewardj28d672a2011-01-10 17:44:30 +0000159 UChar ref[32];
160 ULong i;
carll1f5fe1f2014-08-07 23:25:23 +0000161 Int k;
sewardj28d672a2011-01-10 17:44:30 +0000162 /* ref[] used to be a static const array, but this doesn't work on
163 ppc64 because VEX doesn't load the TOC pointer for the call here,
164 and so we wind up picking up some totally random other data.
165 (It's a wonder we don't segfault.) So, just to be clear, this
166 "fix" (vex r2073) is really a kludgearound for the fact that
167 VEX's 64-bit ppc code generation doesn't provide a valid TOC
168 pointer for helper function calls. Ick. (Bug 250038) */
169 for (i = 0; i < 32; i++) ref[i] = i;
170
cerion5b2325f2005-12-23 00:55:09 +0000171 U128* pU128_src;
172 U128* pU128_dst;
173
174 vassert( vD_off <= sizeof(VexGuestPPC64State)-8 );
175 vassert( sh <= 15 );
176 vassert( shift_right <= 1 );
177 if (shift_right)
178 sh = 16-sh;
179 /* else shift left */
180
181 pU128_src = (U128*)&ref[sh];
182 pU128_dst = (U128*)( ((UChar*)gst) + vD_off );
183
carll1f5fe1f2014-08-07 23:25:23 +0000184 if ((0x1 & endness) == 0x0) {
185 /* Little endian */
186 unsigned char *srcp, *dstp;
187 srcp = (unsigned char *)pU128_src;
188 dstp = (unsigned char *)pU128_dst;
189 for (k = 15; k >= 0; k--, srcp++)
190 dstp[k] = *srcp;
191 } else {
192 (*pU128_dst)[0] = (*pU128_src)[0];
193 (*pU128_dst)[1] = (*pU128_src)[1];
194 (*pU128_dst)[2] = (*pU128_src)[2];
195 (*pU128_dst)[3] = (*pU128_src)[3];
196 }
cerion5b2325f2005-12-23 00:55:09 +0000197}
198
cerion6f6c6a02005-09-13 18:41:09 +0000199
sewardj73a91972005-09-06 10:25:46 +0000200/* Helper-function specialiser. */
cerion91ad5362005-01-27 23:02:41 +0000201
florian1ff47562012-10-21 02:09:51 +0000202IRExpr* guest_ppc32_spechelper ( const HChar* function_name,
sewardjbe917912010-08-22 12:38:53 +0000203 IRExpr** args,
204 IRStmt** precedingStmts,
205 Int n_precedingStmts )
cerion896a1372005-01-25 12:24:25 +0000206{
207 return NULL;
208}
209
florian1ff47562012-10-21 02:09:51 +0000210IRExpr* guest_ppc64_spechelper ( const HChar* function_name,
sewardjbe917912010-08-22 12:38:53 +0000211 IRExpr** args,
212 IRStmt** precedingStmts,
213 Int n_precedingStmts )
cerionf0de28c2005-12-13 20:21:11 +0000214{
215 return NULL;
216}
217
cerion896a1372005-01-25 12:24:25 +0000218
219/*----------------------------------------------*/
220/*--- The exported fns .. ---*/
221/*----------------------------------------------*/
222
223/* VISIBLE TO LIBVEX CLIENT */
florianefa834a2012-11-24 21:07:14 +0000224UInt LibVEX_GuestPPC32_get_CR ( /*IN*/const VexGuestPPC32State* vex_state )
cerion896a1372005-01-25 12:24:25 +0000225{
sewardjb51f0f42005-07-18 11:38:02 +0000226# define FIELD(_n) \
227 ( ( (UInt) \
228 ( (vex_state->guest_CR##_n##_321 & (7<<1)) \
229 | (vex_state->guest_CR##_n##_0 & 1) \
230 ) \
231 ) \
232 << (4 * (7-(_n))) \
233 )
234
235 return
236 FIELD(0) | FIELD(1) | FIELD(2) | FIELD(3)
237 | FIELD(4) | FIELD(5) | FIELD(6) | FIELD(7);
238
239# undef FIELD
cerion896a1372005-01-25 12:24:25 +0000240}
cerion900f6b52005-07-08 13:34:47 +0000241
sewardjb51f0f42005-07-18 11:38:02 +0000242
cerion900f6b52005-07-08 13:34:47 +0000243/* VISIBLE TO LIBVEX CLIENT */
ceriond953ebb2005-11-29 13:27:20 +0000244/* Note: %CR is 32 bits even for ppc64 */
florianefa834a2012-11-24 21:07:14 +0000245UInt LibVEX_GuestPPC64_get_CR ( /*IN*/const VexGuestPPC64State* vex_state )
ceriond953ebb2005-11-29 13:27:20 +0000246{
247# define FIELD(_n) \
248 ( ( (UInt) \
249 ( (vex_state->guest_CR##_n##_321 & (7<<1)) \
250 | (vex_state->guest_CR##_n##_0 & 1) \
251 ) \
252 ) \
253 << (4 * (7-(_n))) \
254 )
255
256 return
257 FIELD(0) | FIELD(1) | FIELD(2) | FIELD(3)
258 | FIELD(4) | FIELD(5) | FIELD(6) | FIELD(7);
259
260# undef FIELD
261}
262
263
264/* VISIBLE TO LIBVEX CLIENT */
sewardjb51f0f42005-07-18 11:38:02 +0000265void LibVEX_GuestPPC32_put_CR ( UInt cr_native,
cerion900f6b52005-07-08 13:34:47 +0000266 /*OUT*/VexGuestPPC32State* vex_state )
267{
sewardjb51f0f42005-07-18 11:38:02 +0000268 UInt t;
269
270# define FIELD(_n) \
271 do { \
272 t = cr_native >> (4*(7-(_n))); \
sewardjc7cd2142005-09-09 22:31:49 +0000273 vex_state->guest_CR##_n##_0 = toUChar(t & 1); \
274 vex_state->guest_CR##_n##_321 = toUChar(t & (7<<1)); \
sewardjb51f0f42005-07-18 11:38:02 +0000275 } while (0)
276
277 FIELD(0);
278 FIELD(1);
279 FIELD(2);
280 FIELD(3);
281 FIELD(4);
282 FIELD(5);
283 FIELD(6);
284 FIELD(7);
285
286# undef FIELD
cerion900f6b52005-07-08 13:34:47 +0000287}
cerion896a1372005-01-25 12:24:25 +0000288
cerion896a1372005-01-25 12:24:25 +0000289
290/* VISIBLE TO LIBVEX CLIENT */
ceriond953ebb2005-11-29 13:27:20 +0000291/* Note: %CR is 32 bits even for ppc64 */
292void LibVEX_GuestPPC64_put_CR ( UInt cr_native,
293 /*OUT*/VexGuestPPC64State* vex_state )
294{
295 UInt t;
296
297# define FIELD(_n) \
298 do { \
299 t = cr_native >> (4*(7-(_n))); \
300 vex_state->guest_CR##_n##_0 = toUChar(t & 1); \
301 vex_state->guest_CR##_n##_321 = toUChar(t & (7<<1)); \
302 } while (0)
303
304 FIELD(0);
305 FIELD(1);
306 FIELD(2);
307 FIELD(3);
308 FIELD(4);
309 FIELD(5);
310 FIELD(6);
311 FIELD(7);
312
313# undef FIELD
314}
315
316
317/* VISIBLE TO LIBVEX CLIENT */
florianefa834a2012-11-24 21:07:14 +0000318UInt LibVEX_GuestPPC32_get_XER ( /*IN*/const VexGuestPPC32State* vex_state )
cerion51900a22005-07-08 13:10:35 +0000319{
sewardjb51f0f42005-07-18 11:38:02 +0000320 UInt w = 0;
321 w |= ( ((UInt)vex_state->guest_XER_BC) & 0xFF );
322 w |= ( (((UInt)vex_state->guest_XER_SO) & 0x1) << 31 );
323 w |= ( (((UInt)vex_state->guest_XER_OV) & 0x1) << 30 );
324 w |= ( (((UInt)vex_state->guest_XER_CA) & 0x1) << 29 );
325 return w;
cerion51900a22005-07-08 13:10:35 +0000326}
327
sewardjb51f0f42005-07-18 11:38:02 +0000328
329/* VISIBLE TO LIBVEX CLIENT */
ceriond953ebb2005-11-29 13:27:20 +0000330/* Note: %XER is 32 bits even for ppc64 */
florianefa834a2012-11-24 21:07:14 +0000331UInt LibVEX_GuestPPC64_get_XER ( /*IN*/const VexGuestPPC64State* vex_state )
ceriond953ebb2005-11-29 13:27:20 +0000332{
333 UInt w = 0;
334 w |= ( ((UInt)vex_state->guest_XER_BC) & 0xFF );
335 w |= ( (((UInt)vex_state->guest_XER_SO) & 0x1) << 31 );
336 w |= ( (((UInt)vex_state->guest_XER_OV) & 0x1) << 30 );
337 w |= ( (((UInt)vex_state->guest_XER_CA) & 0x1) << 29 );
338 return w;
339}
340
341
342/* VISIBLE TO LIBVEX CLIENT */
sewardjb51f0f42005-07-18 11:38:02 +0000343void LibVEX_GuestPPC32_put_XER ( UInt xer_native,
344 /*OUT*/VexGuestPPC32State* vex_state )
345{
sewardjc7cd2142005-09-09 22:31:49 +0000346 vex_state->guest_XER_BC = toUChar(xer_native & 0xFF);
347 vex_state->guest_XER_SO = toUChar((xer_native >> 31) & 0x1);
348 vex_state->guest_XER_OV = toUChar((xer_native >> 30) & 0x1);
349 vex_state->guest_XER_CA = toUChar((xer_native >> 29) & 0x1);
sewardjb51f0f42005-07-18 11:38:02 +0000350}
351
sewardj20f40612006-01-03 18:40:18 +0000352/* VISIBLE TO LIBVEX CLIENT */
353/* Note: %XER is 32 bits even for ppc64 */
354void LibVEX_GuestPPC64_put_XER ( UInt xer_native,
355 /*OUT*/VexGuestPPC64State* vex_state )
356{
357 vex_state->guest_XER_BC = toUChar(xer_native & 0xFF);
358 vex_state->guest_XER_SO = toUChar((xer_native >> 31) & 0x1);
359 vex_state->guest_XER_OV = toUChar((xer_native >> 30) & 0x1);
360 vex_state->guest_XER_CA = toUChar((xer_native >> 29) & 0x1);
361}
sewardjb51f0f42005-07-18 11:38:02 +0000362
cerion51900a22005-07-08 13:10:35 +0000363/* VISIBLE TO LIBVEX CLIENT */
cerion1515db92005-01-25 17:21:23 +0000364void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state )
cerion896a1372005-01-25 12:24:25 +0000365{
sewardjaca070a2006-10-17 00:28:22 +0000366 Int i;
sewardj3dee8492012-04-20 00:13:28 +0000367 vex_state->host_EvC_FAILADDR = 0;
368 vex_state->host_EvC_COUNTER = 0;
369 vex_state->pad3 = 0;
370 vex_state->pad4 = 0;
371
cerion896a1372005-01-25 12:24:25 +0000372 vex_state->guest_GPR0 = 0;
373 vex_state->guest_GPR1 = 0;
374 vex_state->guest_GPR2 = 0;
375 vex_state->guest_GPR3 = 0;
376 vex_state->guest_GPR4 = 0;
377 vex_state->guest_GPR5 = 0;
378 vex_state->guest_GPR6 = 0;
379 vex_state->guest_GPR7 = 0;
380 vex_state->guest_GPR8 = 0;
381 vex_state->guest_GPR9 = 0;
382 vex_state->guest_GPR10 = 0;
383 vex_state->guest_GPR11 = 0;
384 vex_state->guest_GPR12 = 0;
385 vex_state->guest_GPR13 = 0;
386 vex_state->guest_GPR14 = 0;
387 vex_state->guest_GPR15 = 0;
388 vex_state->guest_GPR16 = 0;
389 vex_state->guest_GPR17 = 0;
390 vex_state->guest_GPR18 = 0;
391 vex_state->guest_GPR19 = 0;
392 vex_state->guest_GPR20 = 0;
393 vex_state->guest_GPR21 = 0;
394 vex_state->guest_GPR22 = 0;
395 vex_state->guest_GPR23 = 0;
396 vex_state->guest_GPR24 = 0;
397 vex_state->guest_GPR25 = 0;
398 vex_state->guest_GPR26 = 0;
399 vex_state->guest_GPR27 = 0;
400 vex_state->guest_GPR28 = 0;
401 vex_state->guest_GPR29 = 0;
402 vex_state->guest_GPR30 = 0;
403 vex_state->guest_GPR31 = 0;
404
cerion51900a22005-07-08 13:10:35 +0000405 /* Initialise the vector state. */
sewardjb51f0f42005-07-18 11:38:02 +0000406# define VECZERO(_vr) _vr[0]=_vr[1]=_vr[2]=_vr[3] = 0;
cerion51900a22005-07-08 13:10:35 +0000407
sewardj66d5ef22011-04-15 11:55:00 +0000408 VECZERO(vex_state->guest_VSR0 );
409 VECZERO(vex_state->guest_VSR1 );
410 VECZERO(vex_state->guest_VSR2 );
411 VECZERO(vex_state->guest_VSR3 );
412 VECZERO(vex_state->guest_VSR4 );
413 VECZERO(vex_state->guest_VSR5 );
414 VECZERO(vex_state->guest_VSR6 );
415 VECZERO(vex_state->guest_VSR7 );
416 VECZERO(vex_state->guest_VSR8 );
417 VECZERO(vex_state->guest_VSR9 );
418 VECZERO(vex_state->guest_VSR10);
419 VECZERO(vex_state->guest_VSR11);
420 VECZERO(vex_state->guest_VSR12);
421 VECZERO(vex_state->guest_VSR13);
422 VECZERO(vex_state->guest_VSR14);
423 VECZERO(vex_state->guest_VSR15);
424 VECZERO(vex_state->guest_VSR16);
425 VECZERO(vex_state->guest_VSR17);
426 VECZERO(vex_state->guest_VSR18);
427 VECZERO(vex_state->guest_VSR19);
428 VECZERO(vex_state->guest_VSR20);
429 VECZERO(vex_state->guest_VSR21);
430 VECZERO(vex_state->guest_VSR22);
431 VECZERO(vex_state->guest_VSR23);
432 VECZERO(vex_state->guest_VSR24);
433 VECZERO(vex_state->guest_VSR25);
434 VECZERO(vex_state->guest_VSR26);
435 VECZERO(vex_state->guest_VSR27);
436 VECZERO(vex_state->guest_VSR28);
437 VECZERO(vex_state->guest_VSR29);
438 VECZERO(vex_state->guest_VSR30);
439 VECZERO(vex_state->guest_VSR31);
440 VECZERO(vex_state->guest_VSR32);
441 VECZERO(vex_state->guest_VSR33);
442 VECZERO(vex_state->guest_VSR34);
443 VECZERO(vex_state->guest_VSR35);
444 VECZERO(vex_state->guest_VSR36);
445 VECZERO(vex_state->guest_VSR37);
446 VECZERO(vex_state->guest_VSR38);
447 VECZERO(vex_state->guest_VSR39);
448 VECZERO(vex_state->guest_VSR40);
449 VECZERO(vex_state->guest_VSR41);
450 VECZERO(vex_state->guest_VSR42);
451 VECZERO(vex_state->guest_VSR43);
452 VECZERO(vex_state->guest_VSR44);
453 VECZERO(vex_state->guest_VSR45);
454 VECZERO(vex_state->guest_VSR46);
455 VECZERO(vex_state->guest_VSR47);
456 VECZERO(vex_state->guest_VSR48);
457 VECZERO(vex_state->guest_VSR49);
458 VECZERO(vex_state->guest_VSR50);
459 VECZERO(vex_state->guest_VSR51);
460 VECZERO(vex_state->guest_VSR52);
461 VECZERO(vex_state->guest_VSR53);
462 VECZERO(vex_state->guest_VSR54);
463 VECZERO(vex_state->guest_VSR55);
464 VECZERO(vex_state->guest_VSR56);
465 VECZERO(vex_state->guest_VSR57);
466 VECZERO(vex_state->guest_VSR58);
467 VECZERO(vex_state->guest_VSR59);
468 VECZERO(vex_state->guest_VSR60);
469 VECZERO(vex_state->guest_VSR61);
470 VECZERO(vex_state->guest_VSR62);
471 VECZERO(vex_state->guest_VSR63);
sewardjb51f0f42005-07-18 11:38:02 +0000472
473# undef VECZERO
cerion51900a22005-07-08 13:10:35 +0000474
ceriondb1941a2005-01-25 16:58:21 +0000475 vex_state->guest_CIA = 0;
cerion91ad5362005-01-27 23:02:41 +0000476 vex_state->guest_LR = 0;
477 vex_state->guest_CTR = 0;
cerion896a1372005-01-25 12:24:25 +0000478
sewardjb51f0f42005-07-18 11:38:02 +0000479 vex_state->guest_XER_SO = 0;
480 vex_state->guest_XER_OV = 0;
481 vex_state->guest_XER_CA = 0;
482 vex_state->guest_XER_BC = 0;
cerion896a1372005-01-25 12:24:25 +0000483
sewardjb51f0f42005-07-18 11:38:02 +0000484 vex_state->guest_CR0_321 = 0;
485 vex_state->guest_CR0_0 = 0;
486 vex_state->guest_CR1_321 = 0;
487 vex_state->guest_CR1_0 = 0;
488 vex_state->guest_CR2_321 = 0;
489 vex_state->guest_CR2_0 = 0;
490 vex_state->guest_CR3_321 = 0;
491 vex_state->guest_CR3_0 = 0;
492 vex_state->guest_CR4_321 = 0;
493 vex_state->guest_CR4_0 = 0;
494 vex_state->guest_CR5_321 = 0;
495 vex_state->guest_CR5_0 = 0;
496 vex_state->guest_CR6_321 = 0;
497 vex_state->guest_CR6_0 = 0;
498 vex_state->guest_CR7_321 = 0;
499 vex_state->guest_CR7_0 = 0;
ceriondb1941a2005-01-25 16:58:21 +0000500
sewardjc6bbd472012-04-02 10:20:48 +0000501 vex_state->guest_FPROUND = PPCrm_NEAREST;
502 vex_state->guest_DFPROUND = PPCrm_NEAREST;
sewardj3dee8492012-04-20 00:13:28 +0000503 vex_state->pad1 = 0;
504 vex_state->pad2 = 0;
cerion094d1392005-06-20 13:45:57 +0000505
cerion51900a22005-07-08 13:10:35 +0000506 vex_state->guest_VRSAVE = 0;
507
cerion8f3bc902005-11-18 20:45:51 +0000508 vex_state->guest_VSCR = 0x0; // Non-Java mode = 0
cerion51900a22005-07-08 13:10:35 +0000509
florian6ef84be2012-08-26 03:20:07 +0000510 vex_state->guest_EMNOTE = EmNote_NONE;
cerion094d1392005-06-20 13:45:57 +0000511
sewardj05f5e012014-05-04 10:52:11 +0000512 vex_state->guest_CMSTART = 0;
513 vex_state->guest_CMLEN = 0;
sewardj7787af42005-08-04 18:32:19 +0000514
sewardjce02aa72006-01-12 12:27:58 +0000515 vex_state->guest_NRADDR = 0;
sewardjaca070a2006-10-17 00:28:22 +0000516 vex_state->guest_NRADDR_GPR2 = 0;
517
518 vex_state->guest_REDIR_SP = -1;
519 for (i = 0; i < VEX_GUEST_PPC32_REDIR_STACK_SIZE; i++)
520 vex_state->guest_REDIR_STACK[i] = 0;
521
sewardje86310f2009-03-19 22:21:40 +0000522 vex_state->guest_IP_AT_SYSCALL = 0;
sewardjaca070a2006-10-17 00:28:22 +0000523 vex_state->guest_SPRG3_RO = 0;
sewardj3dee8492012-04-20 00:13:28 +0000524
carll8943d022013-10-02 16:25:57 +0000525 vex_state->padding1 = 0;
526 vex_state->padding2 = 0;
cerion896a1372005-01-25 12:24:25 +0000527}
528
529
ceriond953ebb2005-11-29 13:27:20 +0000530/* VISIBLE TO LIBVEX CLIENT */
531void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state )
532{
sewardjbe482ae2006-01-17 01:42:56 +0000533 Int i;
sewardj3dee8492012-04-20 00:13:28 +0000534 vex_state->host_EvC_FAILADDR = 0;
535 vex_state->host_EvC_COUNTER = 0;
536 vex_state->pad0 = 0;
ceriond953ebb2005-11-29 13:27:20 +0000537 vex_state->guest_GPR0 = 0;
538 vex_state->guest_GPR1 = 0;
539 vex_state->guest_GPR2 = 0;
540 vex_state->guest_GPR3 = 0;
541 vex_state->guest_GPR4 = 0;
542 vex_state->guest_GPR5 = 0;
543 vex_state->guest_GPR6 = 0;
544 vex_state->guest_GPR7 = 0;
545 vex_state->guest_GPR8 = 0;
546 vex_state->guest_GPR9 = 0;
547 vex_state->guest_GPR10 = 0;
548 vex_state->guest_GPR11 = 0;
549 vex_state->guest_GPR12 = 0;
550 vex_state->guest_GPR13 = 0;
551 vex_state->guest_GPR14 = 0;
552 vex_state->guest_GPR15 = 0;
553 vex_state->guest_GPR16 = 0;
554 vex_state->guest_GPR17 = 0;
555 vex_state->guest_GPR18 = 0;
556 vex_state->guest_GPR19 = 0;
557 vex_state->guest_GPR20 = 0;
558 vex_state->guest_GPR21 = 0;
559 vex_state->guest_GPR22 = 0;
560 vex_state->guest_GPR23 = 0;
561 vex_state->guest_GPR24 = 0;
562 vex_state->guest_GPR25 = 0;
563 vex_state->guest_GPR26 = 0;
564 vex_state->guest_GPR27 = 0;
565 vex_state->guest_GPR28 = 0;
566 vex_state->guest_GPR29 = 0;
567 vex_state->guest_GPR30 = 0;
568 vex_state->guest_GPR31 = 0;
569
ceriond953ebb2005-11-29 13:27:20 +0000570 /* Initialise the vector state. */
571# define VECZERO(_vr) _vr[0]=_vr[1]=_vr[2]=_vr[3] = 0;
572
sewardj66d5ef22011-04-15 11:55:00 +0000573 VECZERO(vex_state->guest_VSR0 );
574 VECZERO(vex_state->guest_VSR1 );
575 VECZERO(vex_state->guest_VSR2 );
576 VECZERO(vex_state->guest_VSR3 );
577 VECZERO(vex_state->guest_VSR4 );
578 VECZERO(vex_state->guest_VSR5 );
579 VECZERO(vex_state->guest_VSR6 );
580 VECZERO(vex_state->guest_VSR7 );
581 VECZERO(vex_state->guest_VSR8 );
582 VECZERO(vex_state->guest_VSR9 );
583 VECZERO(vex_state->guest_VSR10);
584 VECZERO(vex_state->guest_VSR11);
585 VECZERO(vex_state->guest_VSR12);
586 VECZERO(vex_state->guest_VSR13);
587 VECZERO(vex_state->guest_VSR14);
588 VECZERO(vex_state->guest_VSR15);
589 VECZERO(vex_state->guest_VSR16);
590 VECZERO(vex_state->guest_VSR17);
591 VECZERO(vex_state->guest_VSR18);
592 VECZERO(vex_state->guest_VSR19);
593 VECZERO(vex_state->guest_VSR20);
594 VECZERO(vex_state->guest_VSR21);
595 VECZERO(vex_state->guest_VSR22);
596 VECZERO(vex_state->guest_VSR23);
597 VECZERO(vex_state->guest_VSR24);
598 VECZERO(vex_state->guest_VSR25);
599 VECZERO(vex_state->guest_VSR26);
600 VECZERO(vex_state->guest_VSR27);
601 VECZERO(vex_state->guest_VSR28);
602 VECZERO(vex_state->guest_VSR29);
603 VECZERO(vex_state->guest_VSR30);
604 VECZERO(vex_state->guest_VSR31);
605 VECZERO(vex_state->guest_VSR32);
606 VECZERO(vex_state->guest_VSR33);
607 VECZERO(vex_state->guest_VSR34);
608 VECZERO(vex_state->guest_VSR35);
609 VECZERO(vex_state->guest_VSR36);
610 VECZERO(vex_state->guest_VSR37);
611 VECZERO(vex_state->guest_VSR38);
612 VECZERO(vex_state->guest_VSR39);
613 VECZERO(vex_state->guest_VSR40);
614 VECZERO(vex_state->guest_VSR41);
615 VECZERO(vex_state->guest_VSR42);
616 VECZERO(vex_state->guest_VSR43);
617 VECZERO(vex_state->guest_VSR44);
618 VECZERO(vex_state->guest_VSR45);
619 VECZERO(vex_state->guest_VSR46);
620 VECZERO(vex_state->guest_VSR47);
621 VECZERO(vex_state->guest_VSR48);
622 VECZERO(vex_state->guest_VSR49);
623 VECZERO(vex_state->guest_VSR50);
624 VECZERO(vex_state->guest_VSR51);
625 VECZERO(vex_state->guest_VSR52);
626 VECZERO(vex_state->guest_VSR53);
627 VECZERO(vex_state->guest_VSR54);
628 VECZERO(vex_state->guest_VSR55);
629 VECZERO(vex_state->guest_VSR56);
630 VECZERO(vex_state->guest_VSR57);
631 VECZERO(vex_state->guest_VSR58);
632 VECZERO(vex_state->guest_VSR59);
633 VECZERO(vex_state->guest_VSR60);
634 VECZERO(vex_state->guest_VSR61);
635 VECZERO(vex_state->guest_VSR62);
636 VECZERO(vex_state->guest_VSR63);
ceriond953ebb2005-11-29 13:27:20 +0000637
638# undef VECZERO
639
640 vex_state->guest_CIA = 0;
641 vex_state->guest_LR = 0;
642 vex_state->guest_CTR = 0;
643
644 vex_state->guest_XER_SO = 0;
645 vex_state->guest_XER_OV = 0;
646 vex_state->guest_XER_CA = 0;
647 vex_state->guest_XER_BC = 0;
648
649 vex_state->guest_CR0_321 = 0;
650 vex_state->guest_CR0_0 = 0;
651 vex_state->guest_CR1_321 = 0;
652 vex_state->guest_CR1_0 = 0;
653 vex_state->guest_CR2_321 = 0;
654 vex_state->guest_CR2_0 = 0;
655 vex_state->guest_CR3_321 = 0;
656 vex_state->guest_CR3_0 = 0;
657 vex_state->guest_CR4_321 = 0;
658 vex_state->guest_CR4_0 = 0;
659 vex_state->guest_CR5_321 = 0;
660 vex_state->guest_CR5_0 = 0;
661 vex_state->guest_CR6_321 = 0;
662 vex_state->guest_CR6_0 = 0;
663 vex_state->guest_CR7_321 = 0;
664 vex_state->guest_CR7_0 = 0;
665
sewardjc6bbd472012-04-02 10:20:48 +0000666 vex_state->guest_FPROUND = PPCrm_NEAREST;
667 vex_state->guest_DFPROUND = PPCrm_NEAREST;
sewardj3dee8492012-04-20 00:13:28 +0000668 vex_state->pad1 = 0;
669 vex_state->pad2 = 0;
ceriond953ebb2005-11-29 13:27:20 +0000670
671 vex_state->guest_VRSAVE = 0;
672
673 vex_state->guest_VSCR = 0x0; // Non-Java mode = 0
674
florian6ef84be2012-08-26 03:20:07 +0000675 vex_state->guest_EMNOTE = EmNote_NONE;
ceriond953ebb2005-11-29 13:27:20 +0000676
sewardje9d8a262009-07-01 08:06:34 +0000677 vex_state->padding = 0;
sewardjce02aa72006-01-12 12:27:58 +0000678
sewardj05f5e012014-05-04 10:52:11 +0000679 vex_state->guest_CMSTART = 0;
680 vex_state->guest_CMLEN = 0;
ceriond953ebb2005-11-29 13:27:20 +0000681
sewardjce02aa72006-01-12 12:27:58 +0000682 vex_state->guest_NRADDR = 0;
sewardj5ff11dd2006-01-20 14:19:25 +0000683 vex_state->guest_NRADDR_GPR2 = 0;
sewardjbe482ae2006-01-17 01:42:56 +0000684
685 vex_state->guest_REDIR_SP = -1;
686 for (i = 0; i < VEX_GUEST_PPC64_REDIR_STACK_SIZE; i++)
687 vex_state->guest_REDIR_STACK[i] = 0;
sewardjaca070a2006-10-17 00:28:22 +0000688
sewardje86310f2009-03-19 22:21:40 +0000689 vex_state->guest_IP_AT_SYSCALL = 0;
sewardjaca070a2006-10-17 00:28:22 +0000690 vex_state->guest_SPRG3_RO = 0;
carll8943d022013-10-02 16:25:57 +0000691 vex_state->guest_TFHAR = 0;
692 vex_state->guest_TFIAR = 0;
693 vex_state->guest_TEXASR = 0;
ceriond953ebb2005-11-29 13:27:20 +0000694}
695
696
cerion896a1372005-01-25 12:24:25 +0000697/*-----------------------------------------------------------*/
cerion75949202005-12-24 13:14:11 +0000698/*--- Describing the ppc guest state, for the benefit ---*/
cerion896a1372005-01-25 12:24:25 +0000699/*--- of iropt and instrumenters. ---*/
700/*-----------------------------------------------------------*/
701
702/* Figure out if any part of the guest state contained in minoff
703 .. maxoff requires precise memory exceptions. If in doubt return
704 True (but this is generates significantly slower code).
sewardje523a4b2005-06-30 12:21:04 +0000705
706 By default we enforce precise exns for guest R1 (stack pointer),
707 CIA (current insn address) and LR (link register). These are the
cerion75949202005-12-24 13:14:11 +0000708 minimum needed to extract correct stack backtraces from ppc
sewardje523a4b2005-06-30 12:21:04 +0000709 code. [[NB: not sure if keeping LR up to date is actually
710 necessary.]]
philippe6c46bef2012-08-14 22:29:01 +0000711
712 Only R1 is needed in mode VexRegUpdSpAtMemAccess.
cerion896a1372005-01-25 12:24:25 +0000713*/
cerion1515db92005-01-25 17:21:23 +0000714Bool guest_ppc32_state_requires_precise_mem_exns ( Int minoff,
sewardje523a4b2005-06-30 12:21:04 +0000715 Int maxoff )
cerion896a1372005-01-25 12:24:25 +0000716{
sewardje523a4b2005-06-30 12:21:04 +0000717 Int lr_min = offsetof(VexGuestPPC32State, guest_LR);
718 Int lr_max = lr_min + 4 - 1;
719 Int r1_min = offsetof(VexGuestPPC32State, guest_GPR1);
720 Int r1_max = r1_min + 4 - 1;
721 Int cia_min = offsetof(VexGuestPPC32State, guest_CIA);
722 Int cia_max = cia_min + 4 - 1;
723
philippe6c46bef2012-08-14 22:29:01 +0000724 if (maxoff < r1_min || minoff > r1_max) {
725 /* no overlap with R1 */
726 if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
727 return False; // We only need to check stack pointer.
sewardje523a4b2005-06-30 12:21:04 +0000728 } else {
729 return True;
730 }
731
philippe6c46bef2012-08-14 22:29:01 +0000732 if (maxoff < lr_min || minoff > lr_max) {
733 /* no overlap with LR */
sewardje523a4b2005-06-30 12:21:04 +0000734 } else {
735 return True;
736 }
737
738 if (maxoff < cia_min || minoff > cia_max) {
739 /* no overlap with CIA */
740 } else {
741 return True;
742 }
743
744 return False;
cerion896a1372005-01-25 12:24:25 +0000745}
746
cerionf0de28c2005-12-13 20:21:11 +0000747Bool guest_ppc64_state_requires_precise_mem_exns ( Int minoff,
748 Int maxoff )
749{
sewardj5ff11dd2006-01-20 14:19:25 +0000750 /* Given that R2 is a Big Deal in the ELF ppc64 ABI, it seems
751 prudent to be conservative with it, even though thus far there
752 is no evidence to suggest that it actually needs to be kept up
753 to date wrt possible exceptions. */
cerionf0de28c2005-12-13 20:21:11 +0000754 Int lr_min = offsetof(VexGuestPPC64State, guest_LR);
sewardj09bbf502005-12-22 03:01:17 +0000755 Int lr_max = lr_min + 8 - 1;
cerionf0de28c2005-12-13 20:21:11 +0000756 Int r1_min = offsetof(VexGuestPPC64State, guest_GPR1);
sewardj09bbf502005-12-22 03:01:17 +0000757 Int r1_max = r1_min + 8 - 1;
sewardj5ff11dd2006-01-20 14:19:25 +0000758 Int r2_min = offsetof(VexGuestPPC64State, guest_GPR2);
759 Int r2_max = r2_min + 8 - 1;
cerionf0de28c2005-12-13 20:21:11 +0000760 Int cia_min = offsetof(VexGuestPPC64State, guest_CIA);
sewardj09bbf502005-12-22 03:01:17 +0000761 Int cia_max = cia_min + 8 - 1;
cerion896a1372005-01-25 12:24:25 +0000762
philippe6c46bef2012-08-14 22:29:01 +0000763 if (maxoff < r1_min || minoff > r1_max) {
764 /* no overlap with R1 */
765 if (vex_control.iropt_register_updates == VexRegUpdSpAtMemAccess)
766 return False; // We only need to check stack pointer.
cerionf0de28c2005-12-13 20:21:11 +0000767 } else {
768 return True;
769 }
770
philippe6c46bef2012-08-14 22:29:01 +0000771 if (maxoff < lr_min || minoff > lr_max) {
772 /* no overlap with LR */
cerionf0de28c2005-12-13 20:21:11 +0000773 } else {
774 return True;
775 }
776
sewardj5ff11dd2006-01-20 14:19:25 +0000777 if (maxoff < r2_min || minoff > r2_max) {
778 /* no overlap with R2 */
779 } else {
780 return True;
781 }
782
cerionf0de28c2005-12-13 20:21:11 +0000783 if (maxoff < cia_min || minoff > cia_max) {
784 /* no overlap with CIA */
785 } else {
786 return True;
787 }
788
789 return False;
790}
791
792
793#define ALWAYSDEFD32(field) \
cerion1515db92005-01-25 17:21:23 +0000794 { offsetof(VexGuestPPC32State, field), \
795 (sizeof ((VexGuestPPC32State*)0)->field) }
cerion896a1372005-01-25 12:24:25 +0000796
797VexGuestLayout
cerion1515db92005-01-25 17:21:23 +0000798 ppc32Guest_layout
cerion896a1372005-01-25 12:24:25 +0000799 = {
800 /* Total size of the guest state, in bytes. */
cerion1515db92005-01-25 17:21:23 +0000801 .total_sizeB = sizeof(VexGuestPPC32State),
cerion896a1372005-01-25 12:24:25 +0000802
803 /* Describe the stack pointer. */
cerion1515db92005-01-25 17:21:23 +0000804 .offset_SP = offsetof(VexGuestPPC32State,guest_GPR1),
cerion896a1372005-01-25 12:24:25 +0000805 .sizeof_SP = 4,
806
sewardja2033302008-08-19 11:15:10 +0000807 /* Describe the frame pointer. */
808 .offset_FP = offsetof(VexGuestPPC32State,guest_GPR1),
809 .sizeof_FP = 4,
810
cerion896a1372005-01-25 12:24:25 +0000811 /* Describe the instruction pointer. */
cerion1515db92005-01-25 17:21:23 +0000812 .offset_IP = offsetof(VexGuestPPC32State,guest_CIA),
ceriondb1941a2005-01-25 16:58:21 +0000813 .sizeof_IP = 4,
cerion896a1372005-01-25 12:24:25 +0000814
815 /* Describe any sections to be regarded by Memcheck as
816 'always-defined'. */
sewardje9d8a262009-07-01 08:06:34 +0000817 .n_alwaysDefd = 11,
cerion896a1372005-01-25 12:24:25 +0000818
819 .alwaysDefd
cerionf0de28c2005-12-13 20:21:11 +0000820 = { /* 0 */ ALWAYSDEFD32(guest_CIA),
florian6ef84be2012-08-26 03:20:07 +0000821 /* 1 */ ALWAYSDEFD32(guest_EMNOTE),
sewardj05f5e012014-05-04 10:52:11 +0000822 /* 2 */ ALWAYSDEFD32(guest_CMSTART),
823 /* 3 */ ALWAYSDEFD32(guest_CMLEN),
cerionf0de28c2005-12-13 20:21:11 +0000824 /* 4 */ ALWAYSDEFD32(guest_VSCR),
825 /* 5 */ ALWAYSDEFD32(guest_FPROUND),
sewardje9d8a262009-07-01 08:06:34 +0000826 /* 6 */ ALWAYSDEFD32(guest_NRADDR),
827 /* 7 */ ALWAYSDEFD32(guest_NRADDR_GPR2),
828 /* 8 */ ALWAYSDEFD32(guest_REDIR_SP),
829 /* 9 */ ALWAYSDEFD32(guest_REDIR_STACK),
830 /* 10 */ ALWAYSDEFD32(guest_IP_AT_SYSCALL)
sewardj9759a812005-07-24 06:29:34 +0000831 }
cerion896a1372005-01-25 12:24:25 +0000832 };
833
cerionf0de28c2005-12-13 20:21:11 +0000834#define ALWAYSDEFD64(field) \
835 { offsetof(VexGuestPPC64State, field), \
836 (sizeof ((VexGuestPPC64State*)0)->field) }
837
838VexGuestLayout
839 ppc64Guest_layout
840 = {
841 /* Total size of the guest state, in bytes. */
842 .total_sizeB = sizeof(VexGuestPPC64State),
843
844 /* Describe the stack pointer. */
845 .offset_SP = offsetof(VexGuestPPC64State,guest_GPR1),
sewardj09bbf502005-12-22 03:01:17 +0000846 .sizeof_SP = 8,
cerionf0de28c2005-12-13 20:21:11 +0000847
sewardja2033302008-08-19 11:15:10 +0000848 /* Describe the frame pointer. */
849 .offset_FP = offsetof(VexGuestPPC64State,guest_GPR1),
850 .sizeof_FP = 8,
851
cerionf0de28c2005-12-13 20:21:11 +0000852 /* Describe the instruction pointer. */
853 .offset_IP = offsetof(VexGuestPPC64State,guest_CIA),
sewardj09bbf502005-12-22 03:01:17 +0000854 .sizeof_IP = 8,
cerionf0de28c2005-12-13 20:21:11 +0000855
856 /* Describe any sections to be regarded by Memcheck as
857 'always-defined'. */
sewardj9c2f13d2009-07-04 13:07:30 +0000858 .n_alwaysDefd = 11,
cerionf0de28c2005-12-13 20:21:11 +0000859
860 .alwaysDefd
861 = { /* 0 */ ALWAYSDEFD64(guest_CIA),
florian6ef84be2012-08-26 03:20:07 +0000862 /* 1 */ ALWAYSDEFD64(guest_EMNOTE),
sewardj05f5e012014-05-04 10:52:11 +0000863 /* 2 */ ALWAYSDEFD64(guest_CMSTART),
864 /* 3 */ ALWAYSDEFD64(guest_CMLEN),
cerionf0de28c2005-12-13 20:21:11 +0000865 /* 4 */ ALWAYSDEFD64(guest_VSCR),
866 /* 5 */ ALWAYSDEFD64(guest_FPROUND),
sewardje9d8a262009-07-01 08:06:34 +0000867 /* 6 */ ALWAYSDEFD64(guest_NRADDR),
868 /* 7 */ ALWAYSDEFD64(guest_NRADDR_GPR2),
869 /* 8 */ ALWAYSDEFD64(guest_REDIR_SP),
870 /* 9 */ ALWAYSDEFD64(guest_REDIR_STACK),
871 /* 10 */ ALWAYSDEFD64(guest_IP_AT_SYSCALL)
cerionf0de28c2005-12-13 20:21:11 +0000872 }
873 };
cerion896a1372005-01-25 12:24:25 +0000874
875/*---------------------------------------------------------------*/
sewardjcef7d3e2009-07-02 12:21:59 +0000876/*--- end guest_ppc_helpers.c ---*/
cerion896a1372005-01-25 12:24:25 +0000877/*---------------------------------------------------------------*/