1
2 /*---------------------------------------------------------------*/
3 /*--- begin guest_ppc_helpers.c ---*/
4 /*---------------------------------------------------------------*/
5
6 /*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
10 Copyright (C) 2004-2017 OpenWorks LLP
11 info@open-works.net
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29
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.
34 */
35
36 #include "libvex_basictypes.h"
37 #include "libvex_emnote.h"
38 #include "libvex_guest_ppc32.h"
39 #include "libvex_guest_ppc64.h"
40 #include "libvex_ir.h"
41 #include "libvex.h"
42
43 #include "main_util.h"
44 #include "main_globals.h"
45 #include "guest_generic_bb_to_IR.h"
46 #include "guest_ppc_defs.h"
47
48
49 /* 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.
53
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
57 guest-ppc/toIR.c.
58 */
59
60
61 /*---------------------------------------------------------------*/
62 /*--- Misc integer helpers. ---*/
63 /*---------------------------------------------------------------*/
64
65 /* CALLED FROM GENERATED CODE */
66 /* DIRTY HELPER (non-referentially-transparent) */
67 /* Horrible hack. On non-ppc platforms, return 1. */
68 /* Reads a complete, consistent 64-bit TB value. */
ppcg_dirtyhelper_MFTB(void)69 ULong ppcg_dirtyhelper_MFTB ( void )
70 {
71 # if defined(__powerpc__)
72 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
92 /* CALLED FROM GENERATED CODE */
93 /* DIRTY HELPER (non-referentially transparent) */
ppc32g_dirtyhelper_MFSPR_268_269(UInt r269)94 UInt ppc32g_dirtyhelper_MFSPR_268_269 ( UInt r269 )
95 {
96 # if defined(__powerpc__)
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 */
111 /* DIRTY HELPER (I'm not really sure what the side effects are) */
ppc32g_dirtyhelper_MFSPR_287(void)112 UInt ppc32g_dirtyhelper_MFSPR_287 ( void )
113 {
114 # if defined(__powerpc__)
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 */
125 /* DIRTY HELPER (reads guest state, writes guest mem) */
ppc32g_dirtyhelper_LVS(VexGuestPPC32State * gst,UInt vD_off,UInt sh,UInt shift_right)126 void ppc32g_dirtyhelper_LVS ( VexGuestPPC32State* gst,
127 UInt vD_off, UInt sh, UInt shift_right )
128 {
129 static
130 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 };
134 U128* pU128_src;
135 U128* pU128_dst;
136
137 vassert( vD_off <= sizeof(VexGuestPPC32State)-8 );
138 vassert( sh <= 15 );
139 vassert( shift_right <= 1 );
140 if (shift_right)
141 sh = 16-sh;
142 /* else shift left */
143
144 pU128_src = (U128*)&ref[sh];
145 pU128_dst = (U128*)( ((UChar*)gst) + vD_off );
146
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
153 /* CALLED FROM GENERATED CODE */
154 /* DIRTY HELPER (reads guest state, writes guest mem) */
ppc64g_dirtyhelper_LVS(VexGuestPPC64State * gst,UInt vD_off,UInt sh,UInt shift_right,UInt endness)155 void ppc64g_dirtyhelper_LVS ( VexGuestPPC64State* gst,
156 UInt vD_off, UInt sh, UInt shift_right,
157 UInt endness )
158 {
159 UChar ref[32];
160 ULong i;
161 Int k;
162 /* 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
171 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
184 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 }
197 }
198
199
200 /* Helper-function specialiser. */
201
guest_ppc32_spechelper(const HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)202 IRExpr* guest_ppc32_spechelper ( const HChar* function_name,
203 IRExpr** args,
204 IRStmt** precedingStmts,
205 Int n_precedingStmts )
206 {
207 return NULL;
208 }
209
guest_ppc64_spechelper(const HChar * function_name,IRExpr ** args,IRStmt ** precedingStmts,Int n_precedingStmts)210 IRExpr* guest_ppc64_spechelper ( const HChar* function_name,
211 IRExpr** args,
212 IRStmt** precedingStmts,
213 Int n_precedingStmts )
214 {
215 return NULL;
216 }
217
218
219 /*---------------------------------------------------------------*/
220 /*--- Misc BCD clean helpers. ---*/
221 /*---------------------------------------------------------------*/
222
223 /* NOTE, the clean and dirty helpers need to called using the
224 * fnptr_to_fnentry() function wrapper to handle the Big Endian
225 * pointer-to-function ABI and the Little Endian ABI.
226 */
227
228 /* This C-helper takes a 128-bit BCD value as two 64-bit pieces.
229 * It checks the string to see if it is a valid 128-bit BCD value.
230 * A valid BCD value has a sign value in bits [3:0] between 0xA
231 * and 0xF inclusive. each of the BCD digits represented as a 4-bit
232 * hex number in bits BCD value[128:4] mut be between 0 and 9
233 * inclusive. Returns an unsigned 64-bit value if valid.
234 */
is_BCDstring128_helper(ULong Signed,ULong bcd_string_hi,ULong bcd_string_low)235 ULong is_BCDstring128_helper( ULong Signed, ULong bcd_string_hi,
236 ULong bcd_string_low ) {
237 Int i;
238 ULong valid_bcd, sign_valid = False;
239 ULong digit;
240 UInt sign;
241
242 if ( Signed == True ) {
243 sign = bcd_string_low & 0xF;
244 if( ( sign >= 0xA ) && ( sign <= 0xF ) )
245 sign_valid = True;
246
247 /* Change the sign digit to a zero
248 * so the for loop below works the same
249 * for signed and unsigned BCD stings
250 */
251 bcd_string_low &= 0xFFFFFFFFFFFFFFF0ULL;
252
253 } else {
254 sign_valid = True; /* set sign to True so result is only
255 based on the validity of the digits */
256 }
257
258 valid_bcd = True; // Assume true to start
259 for( i = 0; i < 32; i++ ) {
260 /* check high and low 64-bit strings in parallel */
261 digit = bcd_string_low & 0xF;
262 if ( digit > 0x9 )
263 valid_bcd = False;
264 bcd_string_low = bcd_string_low >> 4;
265
266 digit = bcd_string_hi & 0xF;
267 if ( digit > 0x9 )
268 valid_bcd = False;
269 bcd_string_hi = bcd_string_hi >> 4;
270 }
271
272 return valid_bcd & sign_valid;
273 }
274
275 /* This clean helper takes a signed 32-bit BCD value and a carry in
276 * and adds 1 to the value of the BCD value. The BCD value is passed
277 * in as a single 64-bit value. The incremented value is returned in
278 * the lower 32 bits of the result. If the input was signed the sign of
279 * the result is the same as the input. The carry out is returned in
280 * bits [35:32] of the result.
281 */
increment_BCDstring32_helper(ULong Signed,ULong bcd_string,ULong carry_in)282 ULong increment_BCDstring32_helper( ULong Signed,
283 ULong bcd_string, ULong carry_in ) {
284 UInt i, num_digits = 8;
285 ULong bcd_value, result = 0;
286 ULong carry, digit, new_digit;
287
288 carry = carry_in;
289
290 if ( Signed == True ) {
291 bcd_value = bcd_string >> 4; /* remove sign */
292 num_digits = num_digits - 1;
293 } else {
294 bcd_value = bcd_string;
295 }
296
297 for( i = 0; i < num_digits; i++ ) {
298 digit = bcd_value & 0xF;
299 bcd_value = bcd_value >> 4;
300 new_digit = digit + carry;
301
302 if ( new_digit > 10 ) {
303 carry = 1;
304 new_digit = new_digit - 10;
305
306 } else {
307 carry = 0;
308 }
309 result = result | (new_digit << (i*4) );
310 }
311
312 if ( Signed == True ) {
313 result = ( carry << 32) | ( result << 4 ) | ( bcd_string & 0xF );
314 } else {
315 result = ( carry << 32) | result;
316 }
317
318 return result;
319 }
320
321 /*---------------------------------------------------------------*/
322 /*--- Misc packed decimal clean helpers. ---*/
323 /*---------------------------------------------------------------*/
324
325 /* This C-helper takes a 64-bit packed decimal value stored in a
326 * 64-bit value. It converts the zoned decimal format. The lower
327 * byte may contain a sign value, set it to zero. If return_upper
328 * is zero, return lower 64 bits of result, otherwise return upper
329 * 64 bits of the result.
330 */
convert_to_zoned_helper(ULong src_hi,ULong src_low,ULong upper_byte,ULong return_upper)331 ULong convert_to_zoned_helper( ULong src_hi, ULong src_low,
332 ULong upper_byte, ULong return_upper ) {
333 UInt i, sh;
334 ULong tmp = 0, new_value;
335
336 /* Remove the sign from the source. Put in the upper byte of result.
337 * Sign inserted later.
338 */
339 if ( return_upper == 0 ) { /* return lower 64-bit result */
340 for(i = 0; i < 7; i++) {
341 sh = ( 8 - i ) * 4;
342 new_value = ( ( src_low >> sh ) & 0xf ) | upper_byte;
343 tmp = tmp | ( new_value << ( ( 7 - i ) * 8 ) );
344 }
345
346 } else {
347 /* Byte for i=0 is in upper 64-bit of the source, do it separately */
348 new_value = ( src_hi & 0xf ) | upper_byte;
349 tmp = tmp | new_value << 56;
350
351 for( i = 1; i < 8; i++ ) {
352 sh = ( 16 - i ) * 4;
353 new_value = ( ( src_low >> sh ) & 0xf ) | upper_byte;
354 tmp = tmp | ( new_value << ( ( 7 - i ) * 8 ) );
355 }
356 }
357 return tmp;
358 }
359
360 /* This C-helper takes the lower 64-bits of the 128-bit packed decimal
361 * src value. It converts the src value to a 128-bit national format.
362 * If return_upper is zero, the helper returns lower 64 bits of result,
363 * otherwise it returns the upper 64-bits of the result.
364 */
convert_to_national_helper(ULong src,ULong return_upper)365 ULong convert_to_national_helper( ULong src, ULong return_upper ) {
366
367 UInt i;
368 UInt sh = 3, max = 4, min = 0; /* initialize max, min for return upper */
369 ULong tmp = 0, new_value;
370
371 if ( return_upper == 0 ) { /* return lower 64-bit result */
372 min = 4;
373 max = 7;
374 sh = 7;
375 }
376
377 for( i = min; i < max; i++ ) {
378 new_value = ( ( src >> ( ( 7 - i ) * 4 ) ) & 0xf ) | 0x0030;
379 tmp = tmp | ( new_value << ( ( sh - i ) * 16 ) );
380 }
381 return tmp;
382 }
383
384 /* This C-helper takes a 128-bit zoned value stored in a 128-bit
385 * value. It converts it to the packed 64-bit decimal format without a
386 * a sign value. The sign is supposed to be in bits [3:0] and the packed
387 * value in bits [67:4]. This helper leaves it to the caller to put the
388 * result into a V128 and shift the returned value over and put the sign
389 * in.
390 */
convert_from_zoned_helper(ULong src_hi,ULong src_low)391 ULong convert_from_zoned_helper( ULong src_hi, ULong src_low ) {
392 UInt i;
393 ULong tmp = 0, nibble;
394
395 /* Unroll the i = 0 iteration so the sizes of the loop for the upper
396 * and lower extraction match. Skip sign in lease significant byte.
397 */
398 nibble = ( src_hi >> 56 ) & 0xF;
399 tmp = tmp | ( nibble << 60 );
400
401 for( i = 1; i < 8; i++ ) {
402 /* get the high nibbles, put into result */
403 nibble = ( src_hi >> ( ( 7 - i ) * 8 ) ) & 0xF;
404 tmp = tmp | ( nibble << ( ( 15 - i ) * 4 ) );
405
406 /* get the low nibbles, put into result */
407 nibble = ( src_low >> ( ( 8 - i ) * 8 ) ) & 0xF;
408 tmp = tmp | ( nibble << ( ( 8 - i ) * 4 ) );
409 }
410 return tmp;
411 }
412
413 /* This C-helper takes a 128-bit national value stored in a 128-bit
414 * value. It converts it to a signless packed 64-bit decimal format.
415 */
convert_from_national_helper(ULong src_hi,ULong src_low)416 ULong convert_from_national_helper( ULong src_hi, ULong src_low ) {
417 UInt i;
418 ULong tmp = 0, hword;
419
420 src_low = src_low & 0xFFFFFFFFFFFFFFF0ULL; /* remove the sign */
421
422 for( i = 0; i < 4; i++ ) {
423 /* get the high half-word, put into result */
424 hword = ( src_hi >> ( ( 3 - i ) * 16 ) ) & 0xF;
425 tmp = tmp | ( hword << ( ( 7 - i ) * 4 ) );
426
427 /* get the low half-word, put into result */
428 hword = ( src_low >> ( ( 3 - i ) * 16 ) ) & 0xF;
429 tmp = tmp | ( hword << ( ( 3 - i ) * 4 ) );
430 }
431 return tmp;
432 }
433
434 /*----------------------------------------------*/
435 /*--- The exported fns .. ---*/
436 /*----------------------------------------------*/
437
438 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestPPC32_get_CR(const VexGuestPPC32State * vex_state)439 UInt LibVEX_GuestPPC32_get_CR ( /*IN*/const VexGuestPPC32State* vex_state )
440 {
441 # define FIELD(_n) \
442 ( ( (UInt) \
443 ( (vex_state->guest_CR##_n##_321 & (7<<1)) \
444 | (vex_state->guest_CR##_n##_0 & 1) \
445 ) \
446 ) \
447 << (4 * (7-(_n))) \
448 )
449
450 return
451 FIELD(0) | FIELD(1) | FIELD(2) | FIELD(3)
452 | FIELD(4) | FIELD(5) | FIELD(6) | FIELD(7);
453
454 # undef FIELD
455 }
456
457
458 /* VISIBLE TO LIBVEX CLIENT */
459 /* Note: %CR is 32 bits even for ppc64 */
LibVEX_GuestPPC64_get_CR(const VexGuestPPC64State * vex_state)460 UInt LibVEX_GuestPPC64_get_CR ( /*IN*/const VexGuestPPC64State* vex_state )
461 {
462 # define FIELD(_n) \
463 ( ( (UInt) \
464 ( (vex_state->guest_CR##_n##_321 & (7<<1)) \
465 | (vex_state->guest_CR##_n##_0 & 1) \
466 ) \
467 ) \
468 << (4 * (7-(_n))) \
469 )
470
471 return
472 FIELD(0) | FIELD(1) | FIELD(2) | FIELD(3)
473 | FIELD(4) | FIELD(5) | FIELD(6) | FIELD(7);
474
475 # undef FIELD
476 }
477
478
479 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestPPC32_put_CR(UInt cr_native,VexGuestPPC32State * vex_state)480 void LibVEX_GuestPPC32_put_CR ( UInt cr_native,
481 /*OUT*/VexGuestPPC32State* vex_state )
482 {
483 UInt t;
484
485 # define FIELD(_n) \
486 do { \
487 t = cr_native >> (4*(7-(_n))); \
488 vex_state->guest_CR##_n##_0 = toUChar(t & 1); \
489 vex_state->guest_CR##_n##_321 = toUChar(t & (7<<1)); \
490 } while (0)
491
492 FIELD(0);
493 FIELD(1);
494 FIELD(2);
495 FIELD(3);
496 FIELD(4);
497 FIELD(5);
498 FIELD(6);
499 FIELD(7);
500
501 # undef FIELD
502 }
503
504
505 /* VISIBLE TO LIBVEX CLIENT */
506 /* Note: %CR is 32 bits even for ppc64 */
LibVEX_GuestPPC64_put_CR(UInt cr_native,VexGuestPPC64State * vex_state)507 void LibVEX_GuestPPC64_put_CR ( UInt cr_native,
508 /*OUT*/VexGuestPPC64State* vex_state )
509 {
510 UInt t;
511
512 # define FIELD(_n) \
513 do { \
514 t = cr_native >> (4*(7-(_n))); \
515 vex_state->guest_CR##_n##_0 = toUChar(t & 1); \
516 vex_state->guest_CR##_n##_321 = toUChar(t & (7<<1)); \
517 } while (0)
518
519 FIELD(0);
520 FIELD(1);
521 FIELD(2);
522 FIELD(3);
523 FIELD(4);
524 FIELD(5);
525 FIELD(6);
526 FIELD(7);
527
528 # undef FIELD
529 }
530
531
532 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestPPC32_get_XER(const VexGuestPPC32State * vex_state)533 UInt LibVEX_GuestPPC32_get_XER ( /*IN*/const VexGuestPPC32State* vex_state )
534 {
535 UInt w = 0;
536 w |= ( ((UInt)vex_state->guest_XER_BC) & 0xFF );
537 w |= ( (((UInt)vex_state->guest_XER_SO) & 0x1) << 31 );
538 w |= ( (((UInt)vex_state->guest_XER_OV) & 0x1) << 30 );
539 w |= ( (((UInt)vex_state->guest_XER_CA) & 0x1) << 29 );
540 w |= ( (((UInt)vex_state->guest_XER_OV32) & 0x1) << 19 );
541 w |= ( (((UInt)vex_state->guest_XER_CA32) & 0x1) << 18 );
542 return w;
543 }
544
545
546 /* VISIBLE TO LIBVEX CLIENT */
547 /* Note: %XER is 32 bits even for ppc64 */
LibVEX_GuestPPC64_get_XER(const VexGuestPPC64State * vex_state)548 UInt LibVEX_GuestPPC64_get_XER ( /*IN*/const VexGuestPPC64State* vex_state )
549 {
550 UInt w = 0;
551 w |= ( ((UInt)vex_state->guest_XER_BC) & 0xFF );
552 w |= ( (((UInt)vex_state->guest_XER_SO) & 0x1) << 31 );
553 w |= ( (((UInt)vex_state->guest_XER_OV) & 0x1) << 30 );
554 w |= ( (((UInt)vex_state->guest_XER_CA) & 0x1) << 29 );
555 w |= ( (((UInt)vex_state->guest_XER_OV32) & 0x1) << 19 );
556 w |= ( (((UInt)vex_state->guest_XER_CA32) & 0x1) << 18 );
557 return w;
558 }
559
560
561 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestPPC32_put_XER(UInt xer_native,VexGuestPPC32State * vex_state)562 void LibVEX_GuestPPC32_put_XER ( UInt xer_native,
563 /*OUT*/VexGuestPPC32State* vex_state )
564 {
565 vex_state->guest_XER_BC = toUChar(xer_native & 0xFF);
566 vex_state->guest_XER_SO = toUChar((xer_native >> 31) & 0x1);
567 vex_state->guest_XER_OV = toUChar((xer_native >> 30) & 0x1);
568 vex_state->guest_XER_CA = toUChar((xer_native >> 29) & 0x1);
569 vex_state->guest_XER_OV32 = toUChar((xer_native >> 19) & 0x1);
570 vex_state->guest_XER_CA32 = toUChar((xer_native >> 18) & 0x1);
571 }
572
573 /* VISIBLE TO LIBVEX CLIENT */
574 /* Note: %XER is 32 bits even for ppc64 */
LibVEX_GuestPPC64_put_XER(UInt xer_native,VexGuestPPC64State * vex_state)575 void LibVEX_GuestPPC64_put_XER ( UInt xer_native,
576 /*OUT*/VexGuestPPC64State* vex_state )
577 {
578 vex_state->guest_XER_BC = toUChar(xer_native & 0xFF);
579 vex_state->guest_XER_SO = toUChar((xer_native >> 31) & 0x1);
580 vex_state->guest_XER_OV = toUChar((xer_native >> 30) & 0x1);
581 vex_state->guest_XER_CA = toUChar((xer_native >> 29) & 0x1);
582 vex_state->guest_XER_OV32 = toUChar((xer_native >> 19) & 0x1);
583 vex_state->guest_XER_CA32 = toUChar((xer_native >> 18) & 0x1);
584 }
585
586 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestPPC32_initialise(VexGuestPPC32State * vex_state)587 void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state )
588 {
589 Int i;
590 vex_state->host_EvC_FAILADDR = 0;
591 vex_state->host_EvC_COUNTER = 0;
592 vex_state->pad3 = 0;
593 vex_state->pad4 = 0;
594
595 vex_state->guest_GPR0 = 0;
596 vex_state->guest_GPR1 = 0;
597 vex_state->guest_GPR2 = 0;
598 vex_state->guest_GPR3 = 0;
599 vex_state->guest_GPR4 = 0;
600 vex_state->guest_GPR5 = 0;
601 vex_state->guest_GPR6 = 0;
602 vex_state->guest_GPR7 = 0;
603 vex_state->guest_GPR8 = 0;
604 vex_state->guest_GPR9 = 0;
605 vex_state->guest_GPR10 = 0;
606 vex_state->guest_GPR11 = 0;
607 vex_state->guest_GPR12 = 0;
608 vex_state->guest_GPR13 = 0;
609 vex_state->guest_GPR14 = 0;
610 vex_state->guest_GPR15 = 0;
611 vex_state->guest_GPR16 = 0;
612 vex_state->guest_GPR17 = 0;
613 vex_state->guest_GPR18 = 0;
614 vex_state->guest_GPR19 = 0;
615 vex_state->guest_GPR20 = 0;
616 vex_state->guest_GPR21 = 0;
617 vex_state->guest_GPR22 = 0;
618 vex_state->guest_GPR23 = 0;
619 vex_state->guest_GPR24 = 0;
620 vex_state->guest_GPR25 = 0;
621 vex_state->guest_GPR26 = 0;
622 vex_state->guest_GPR27 = 0;
623 vex_state->guest_GPR28 = 0;
624 vex_state->guest_GPR29 = 0;
625 vex_state->guest_GPR30 = 0;
626 vex_state->guest_GPR31 = 0;
627
628 /* Initialise the vector state. */
629 # define VECZERO(_vr) _vr[0]=_vr[1]=_vr[2]=_vr[3] = 0;
630
631 VECZERO(vex_state->guest_VSR0 );
632 VECZERO(vex_state->guest_VSR1 );
633 VECZERO(vex_state->guest_VSR2 );
634 VECZERO(vex_state->guest_VSR3 );
635 VECZERO(vex_state->guest_VSR4 );
636 VECZERO(vex_state->guest_VSR5 );
637 VECZERO(vex_state->guest_VSR6 );
638 VECZERO(vex_state->guest_VSR7 );
639 VECZERO(vex_state->guest_VSR8 );
640 VECZERO(vex_state->guest_VSR9 );
641 VECZERO(vex_state->guest_VSR10);
642 VECZERO(vex_state->guest_VSR11);
643 VECZERO(vex_state->guest_VSR12);
644 VECZERO(vex_state->guest_VSR13);
645 VECZERO(vex_state->guest_VSR14);
646 VECZERO(vex_state->guest_VSR15);
647 VECZERO(vex_state->guest_VSR16);
648 VECZERO(vex_state->guest_VSR17);
649 VECZERO(vex_state->guest_VSR18);
650 VECZERO(vex_state->guest_VSR19);
651 VECZERO(vex_state->guest_VSR20);
652 VECZERO(vex_state->guest_VSR21);
653 VECZERO(vex_state->guest_VSR22);
654 VECZERO(vex_state->guest_VSR23);
655 VECZERO(vex_state->guest_VSR24);
656 VECZERO(vex_state->guest_VSR25);
657 VECZERO(vex_state->guest_VSR26);
658 VECZERO(vex_state->guest_VSR27);
659 VECZERO(vex_state->guest_VSR28);
660 VECZERO(vex_state->guest_VSR29);
661 VECZERO(vex_state->guest_VSR30);
662 VECZERO(vex_state->guest_VSR31);
663 VECZERO(vex_state->guest_VSR32);
664 VECZERO(vex_state->guest_VSR33);
665 VECZERO(vex_state->guest_VSR34);
666 VECZERO(vex_state->guest_VSR35);
667 VECZERO(vex_state->guest_VSR36);
668 VECZERO(vex_state->guest_VSR37);
669 VECZERO(vex_state->guest_VSR38);
670 VECZERO(vex_state->guest_VSR39);
671 VECZERO(vex_state->guest_VSR40);
672 VECZERO(vex_state->guest_VSR41);
673 VECZERO(vex_state->guest_VSR42);
674 VECZERO(vex_state->guest_VSR43);
675 VECZERO(vex_state->guest_VSR44);
676 VECZERO(vex_state->guest_VSR45);
677 VECZERO(vex_state->guest_VSR46);
678 VECZERO(vex_state->guest_VSR47);
679 VECZERO(vex_state->guest_VSR48);
680 VECZERO(vex_state->guest_VSR49);
681 VECZERO(vex_state->guest_VSR50);
682 VECZERO(vex_state->guest_VSR51);
683 VECZERO(vex_state->guest_VSR52);
684 VECZERO(vex_state->guest_VSR53);
685 VECZERO(vex_state->guest_VSR54);
686 VECZERO(vex_state->guest_VSR55);
687 VECZERO(vex_state->guest_VSR56);
688 VECZERO(vex_state->guest_VSR57);
689 VECZERO(vex_state->guest_VSR58);
690 VECZERO(vex_state->guest_VSR59);
691 VECZERO(vex_state->guest_VSR60);
692 VECZERO(vex_state->guest_VSR61);
693 VECZERO(vex_state->guest_VSR62);
694 VECZERO(vex_state->guest_VSR63);
695
696 # undef VECZERO
697
698 vex_state->guest_CIA = 0;
699 vex_state->guest_LR = 0;
700 vex_state->guest_CTR = 0;
701
702 vex_state->guest_XER_SO = 0;
703 vex_state->guest_XER_OV = 0;
704 vex_state->guest_XER_CA = 0;
705 vex_state->guest_XER_BC = 0;
706
707 vex_state->guest_XER_OV32 = 0;
708 vex_state->guest_XER_CA32 = 0;
709
710 vex_state->guest_CR0_321 = 0;
711 vex_state->guest_CR0_0 = 0;
712 vex_state->guest_CR1_321 = 0;
713 vex_state->guest_CR1_0 = 0;
714 vex_state->guest_CR2_321 = 0;
715 vex_state->guest_CR2_0 = 0;
716 vex_state->guest_CR3_321 = 0;
717 vex_state->guest_CR3_0 = 0;
718 vex_state->guest_CR4_321 = 0;
719 vex_state->guest_CR4_0 = 0;
720 vex_state->guest_CR5_321 = 0;
721 vex_state->guest_CR5_0 = 0;
722 vex_state->guest_CR6_321 = 0;
723 vex_state->guest_CR6_0 = 0;
724 vex_state->guest_CR7_321 = 0;
725 vex_state->guest_CR7_0 = 0;
726
727 vex_state->guest_FPROUND = PPCrm_NEAREST;
728 vex_state->guest_DFPROUND = PPCrm_NEAREST;
729 vex_state->guest_C_FPCC = 0;
730 vex_state->pad2 = 0;
731
732 vex_state->guest_VRSAVE = 0;
733
734 vex_state->guest_VSCR = 0x0; // Non-Java mode = 0
735
736 vex_state->guest_EMNOTE = EmNote_NONE;
737
738 vex_state->guest_CMSTART = 0;
739 vex_state->guest_CMLEN = 0;
740
741 vex_state->guest_NRADDR = 0;
742 vex_state->guest_NRADDR_GPR2 = 0;
743
744 vex_state->guest_REDIR_SP = -1;
745 for (i = 0; i < VEX_GUEST_PPC32_REDIR_STACK_SIZE; i++)
746 vex_state->guest_REDIR_STACK[i] = 0;
747
748 vex_state->guest_IP_AT_SYSCALL = 0;
749 vex_state->guest_SPRG3_RO = 0;
750 vex_state->guest_PPR = 0x4ULL << 50; // medium priority
751 vex_state->guest_PSPB = 0x100; // an arbitrary non-zero value to start with
752
753 vex_state->padding1 = 0;
754 /* vex_state->padding2 = 0; currently not used */
755 }
756
757
758 /* VISIBLE TO LIBVEX CLIENT */
LibVEX_GuestPPC64_initialise(VexGuestPPC64State * vex_state)759 void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state )
760 {
761 Int i;
762 vex_state->host_EvC_FAILADDR = 0;
763 vex_state->host_EvC_COUNTER = 0;
764 vex_state->pad0 = 0;
765 vex_state->guest_GPR0 = 0;
766 vex_state->guest_GPR1 = 0;
767 vex_state->guest_GPR2 = 0;
768 vex_state->guest_GPR3 = 0;
769 vex_state->guest_GPR4 = 0;
770 vex_state->guest_GPR5 = 0;
771 vex_state->guest_GPR6 = 0;
772 vex_state->guest_GPR7 = 0;
773 vex_state->guest_GPR8 = 0;
774 vex_state->guest_GPR9 = 0;
775 vex_state->guest_GPR10 = 0;
776 vex_state->guest_GPR11 = 0;
777 vex_state->guest_GPR12 = 0;
778 vex_state->guest_GPR13 = 0;
779 vex_state->guest_GPR14 = 0;
780 vex_state->guest_GPR15 = 0;
781 vex_state->guest_GPR16 = 0;
782 vex_state->guest_GPR17 = 0;
783 vex_state->guest_GPR18 = 0;
784 vex_state->guest_GPR19 = 0;
785 vex_state->guest_GPR20 = 0;
786 vex_state->guest_GPR21 = 0;
787 vex_state->guest_GPR22 = 0;
788 vex_state->guest_GPR23 = 0;
789 vex_state->guest_GPR24 = 0;
790 vex_state->guest_GPR25 = 0;
791 vex_state->guest_GPR26 = 0;
792 vex_state->guest_GPR27 = 0;
793 vex_state->guest_GPR28 = 0;
794 vex_state->guest_GPR29 = 0;
795 vex_state->guest_GPR30 = 0;
796 vex_state->guest_GPR31 = 0;
797
798 /* Initialise the vector state. */
799 # define VECZERO(_vr) _vr[0]=_vr[1]=_vr[2]=_vr[3] = 0;
800
801 VECZERO(vex_state->guest_VSR0 );
802 VECZERO(vex_state->guest_VSR1 );
803 VECZERO(vex_state->guest_VSR2 );
804 VECZERO(vex_state->guest_VSR3 );
805 VECZERO(vex_state->guest_VSR4 );
806 VECZERO(vex_state->guest_VSR5 );
807 VECZERO(vex_state->guest_VSR6 );
808 VECZERO(vex_state->guest_VSR7 );
809 VECZERO(vex_state->guest_VSR8 );
810 VECZERO(vex_state->guest_VSR9 );
811 VECZERO(vex_state->guest_VSR10);
812 VECZERO(vex_state->guest_VSR11);
813 VECZERO(vex_state->guest_VSR12);
814 VECZERO(vex_state->guest_VSR13);
815 VECZERO(vex_state->guest_VSR14);
816 VECZERO(vex_state->guest_VSR15);
817 VECZERO(vex_state->guest_VSR16);
818 VECZERO(vex_state->guest_VSR17);
819 VECZERO(vex_state->guest_VSR18);
820 VECZERO(vex_state->guest_VSR19);
821 VECZERO(vex_state->guest_VSR20);
822 VECZERO(vex_state->guest_VSR21);
823 VECZERO(vex_state->guest_VSR22);
824 VECZERO(vex_state->guest_VSR23);
825 VECZERO(vex_state->guest_VSR24);
826 VECZERO(vex_state->guest_VSR25);
827 VECZERO(vex_state->guest_VSR26);
828 VECZERO(vex_state->guest_VSR27);
829 VECZERO(vex_state->guest_VSR28);
830 VECZERO(vex_state->guest_VSR29);
831 VECZERO(vex_state->guest_VSR30);
832 VECZERO(vex_state->guest_VSR31);
833 VECZERO(vex_state->guest_VSR32);
834 VECZERO(vex_state->guest_VSR33);
835 VECZERO(vex_state->guest_VSR34);
836 VECZERO(vex_state->guest_VSR35);
837 VECZERO(vex_state->guest_VSR36);
838 VECZERO(vex_state->guest_VSR37);
839 VECZERO(vex_state->guest_VSR38);
840 VECZERO(vex_state->guest_VSR39);
841 VECZERO(vex_state->guest_VSR40);
842 VECZERO(vex_state->guest_VSR41);
843 VECZERO(vex_state->guest_VSR42);
844 VECZERO(vex_state->guest_VSR43);
845 VECZERO(vex_state->guest_VSR44);
846 VECZERO(vex_state->guest_VSR45);
847 VECZERO(vex_state->guest_VSR46);
848 VECZERO(vex_state->guest_VSR47);
849 VECZERO(vex_state->guest_VSR48);
850 VECZERO(vex_state->guest_VSR49);
851 VECZERO(vex_state->guest_VSR50);
852 VECZERO(vex_state->guest_VSR51);
853 VECZERO(vex_state->guest_VSR52);
854 VECZERO(vex_state->guest_VSR53);
855 VECZERO(vex_state->guest_VSR54);
856 VECZERO(vex_state->guest_VSR55);
857 VECZERO(vex_state->guest_VSR56);
858 VECZERO(vex_state->guest_VSR57);
859 VECZERO(vex_state->guest_VSR58);
860 VECZERO(vex_state->guest_VSR59);
861 VECZERO(vex_state->guest_VSR60);
862 VECZERO(vex_state->guest_VSR61);
863 VECZERO(vex_state->guest_VSR62);
864 VECZERO(vex_state->guest_VSR63);
865
866 # undef VECZERO
867
868 vex_state->guest_CIA = 0;
869 vex_state->guest_LR = 0;
870 vex_state->guest_CTR = 0;
871
872 vex_state->guest_XER_SO = 0;
873 vex_state->guest_XER_OV = 0;
874 vex_state->guest_XER_CA = 0;
875 vex_state->guest_XER_BC = 0;
876
877 vex_state->guest_CR0_321 = 0;
878 vex_state->guest_CR0_0 = 0;
879 vex_state->guest_CR1_321 = 0;
880 vex_state->guest_CR1_0 = 0;
881 vex_state->guest_CR2_321 = 0;
882 vex_state->guest_CR2_0 = 0;
883 vex_state->guest_CR3_321 = 0;
884 vex_state->guest_CR3_0 = 0;
885 vex_state->guest_CR4_321 = 0;
886 vex_state->guest_CR4_0 = 0;
887 vex_state->guest_CR5_321 = 0;
888 vex_state->guest_CR5_0 = 0;
889 vex_state->guest_CR6_321 = 0;
890 vex_state->guest_CR6_0 = 0;
891 vex_state->guest_CR7_321 = 0;
892 vex_state->guest_CR7_0 = 0;
893
894 vex_state->guest_FPROUND = PPCrm_NEAREST;
895 vex_state->guest_DFPROUND = PPCrm_NEAREST;
896 vex_state->guest_C_FPCC = 0;
897 vex_state->pad2 = 0;
898
899 vex_state->guest_VRSAVE = 0;
900
901 vex_state->guest_VSCR = 0x0; // Non-Java mode = 0
902
903 vex_state->guest_EMNOTE = EmNote_NONE;
904
905 vex_state->padding = 0;
906
907 vex_state->guest_CMSTART = 0;
908 vex_state->guest_CMLEN = 0;
909
910 vex_state->guest_NRADDR = 0;
911 vex_state->guest_NRADDR_GPR2 = 0;
912
913 vex_state->guest_REDIR_SP = -1;
914 for (i = 0; i < VEX_GUEST_PPC64_REDIR_STACK_SIZE; i++)
915 vex_state->guest_REDIR_STACK[i] = 0;
916
917 vex_state->guest_IP_AT_SYSCALL = 0;
918 vex_state->guest_SPRG3_RO = 0;
919 vex_state->guest_TFHAR = 0;
920 vex_state->guest_TFIAR = 0;
921 vex_state->guest_TEXASR = 0;
922 vex_state->guest_PPR = 0x4ULL << 50; // medium priority
923 vex_state->guest_PSPB = 0x100; // an arbitrary non-zero value to start with
924 }
925
926
927 /*-----------------------------------------------------------*/
928 /*--- Describing the ppc guest state, for the benefit ---*/
929 /*--- of iropt and instrumenters. ---*/
930 /*-----------------------------------------------------------*/
931
932 /* Figure out if any part of the guest state contained in minoff
933 .. maxoff requires precise memory exceptions. If in doubt return
934 True (but this is generates significantly slower code).
935
936 By default we enforce precise exns for guest R1 (stack pointer),
937 CIA (current insn address) and LR (link register). These are the
938 minimum needed to extract correct stack backtraces from ppc
939 code. [[NB: not sure if keeping LR up to date is actually
940 necessary.]]
941
942 Only R1 is needed in mode VexRegUpdSpAtMemAccess.
943 */
guest_ppc32_state_requires_precise_mem_exns(Int minoff,Int maxoff,VexRegisterUpdates pxControl)944 Bool guest_ppc32_state_requires_precise_mem_exns (
945 Int minoff, Int maxoff, VexRegisterUpdates pxControl
946 )
947 {
948 Int lr_min = offsetof(VexGuestPPC32State, guest_LR);
949 Int lr_max = lr_min + 4 - 1;
950 Int r1_min = offsetof(VexGuestPPC32State, guest_GPR1);
951 Int r1_max = r1_min + 4 - 1;
952 Int cia_min = offsetof(VexGuestPPC32State, guest_CIA);
953 Int cia_max = cia_min + 4 - 1;
954
955 if (maxoff < r1_min || minoff > r1_max) {
956 /* no overlap with R1 */
957 if (pxControl == VexRegUpdSpAtMemAccess)
958 return False; // We only need to check stack pointer.
959 } else {
960 return True;
961 }
962
963 if (maxoff < lr_min || minoff > lr_max) {
964 /* no overlap with LR */
965 } else {
966 return True;
967 }
968
969 if (maxoff < cia_min || minoff > cia_max) {
970 /* no overlap with CIA */
971 } else {
972 return True;
973 }
974
975 return False;
976 }
977
guest_ppc64_state_requires_precise_mem_exns(Int minoff,Int maxoff,VexRegisterUpdates pxControl)978 Bool guest_ppc64_state_requires_precise_mem_exns (
979 Int minoff, Int maxoff, VexRegisterUpdates pxControl
980 )
981 {
982 /* Given that R2 is a Big Deal in the ELF ppc64 ABI, it seems
983 prudent to be conservative with it, even though thus far there
984 is no evidence to suggest that it actually needs to be kept up
985 to date wrt possible exceptions. */
986 Int lr_min = offsetof(VexGuestPPC64State, guest_LR);
987 Int lr_max = lr_min + 8 - 1;
988 Int r1_min = offsetof(VexGuestPPC64State, guest_GPR1);
989 Int r1_max = r1_min + 8 - 1;
990 Int r2_min = offsetof(VexGuestPPC64State, guest_GPR2);
991 Int r2_max = r2_min + 8 - 1;
992 Int cia_min = offsetof(VexGuestPPC64State, guest_CIA);
993 Int cia_max = cia_min + 8 - 1;
994
995 if (maxoff < r1_min || minoff > r1_max) {
996 /* no overlap with R1 */
997 if (pxControl == VexRegUpdSpAtMemAccess)
998 return False; // We only need to check stack pointer.
999 } else {
1000 return True;
1001 }
1002
1003 if (maxoff < lr_min || minoff > lr_max) {
1004 /* no overlap with LR */
1005 } else {
1006 return True;
1007 }
1008
1009 if (maxoff < r2_min || minoff > r2_max) {
1010 /* no overlap with R2 */
1011 } else {
1012 return True;
1013 }
1014
1015 if (maxoff < cia_min || minoff > cia_max) {
1016 /* no overlap with CIA */
1017 } else {
1018 return True;
1019 }
1020
1021 return False;
1022 }
1023
1024
1025 #define ALWAYSDEFD32(field) \
1026 { offsetof(VexGuestPPC32State, field), \
1027 (sizeof ((VexGuestPPC32State*)0)->field) }
1028
1029 VexGuestLayout
1030 ppc32Guest_layout
1031 = {
1032 /* Total size of the guest state, in bytes. */
1033 .total_sizeB = sizeof(VexGuestPPC32State),
1034
1035 /* Describe the stack pointer. */
1036 .offset_SP = offsetof(VexGuestPPC32State,guest_GPR1),
1037 .sizeof_SP = 4,
1038
1039 /* Describe the frame pointer. */
1040 .offset_FP = offsetof(VexGuestPPC32State,guest_GPR1),
1041 .sizeof_FP = 4,
1042
1043 /* Describe the instruction pointer. */
1044 .offset_IP = offsetof(VexGuestPPC32State,guest_CIA),
1045 .sizeof_IP = 4,
1046
1047 /* Describe any sections to be regarded by Memcheck as
1048 'always-defined'. */
1049 .n_alwaysDefd = 12,
1050
1051 .alwaysDefd
1052 = { /* 0 */ ALWAYSDEFD32(guest_CIA),
1053 /* 1 */ ALWAYSDEFD32(guest_EMNOTE),
1054 /* 2 */ ALWAYSDEFD32(guest_CMSTART),
1055 /* 3 */ ALWAYSDEFD32(guest_CMLEN),
1056 /* 4 */ ALWAYSDEFD32(guest_VSCR),
1057 /* 5 */ ALWAYSDEFD32(guest_FPROUND),
1058 /* 6 */ ALWAYSDEFD32(guest_NRADDR),
1059 /* 7 */ ALWAYSDEFD32(guest_NRADDR_GPR2),
1060 /* 8 */ ALWAYSDEFD32(guest_REDIR_SP),
1061 /* 9 */ ALWAYSDEFD32(guest_REDIR_STACK),
1062 /* 10 */ ALWAYSDEFD32(guest_IP_AT_SYSCALL),
1063 /* 11 */ ALWAYSDEFD32(guest_C_FPCC)
1064 }
1065 };
1066
1067 #define ALWAYSDEFD64(field) \
1068 { offsetof(VexGuestPPC64State, field), \
1069 (sizeof ((VexGuestPPC64State*)0)->field) }
1070
1071 VexGuestLayout
1072 ppc64Guest_layout
1073 = {
1074 /* Total size of the guest state, in bytes. */
1075 .total_sizeB = sizeof(VexGuestPPC64State),
1076
1077 /* Describe the stack pointer. */
1078 .offset_SP = offsetof(VexGuestPPC64State,guest_GPR1),
1079 .sizeof_SP = 8,
1080
1081 /* Describe the frame pointer. */
1082 .offset_FP = offsetof(VexGuestPPC64State,guest_GPR1),
1083 .sizeof_FP = 8,
1084
1085 /* Describe the instruction pointer. */
1086 .offset_IP = offsetof(VexGuestPPC64State,guest_CIA),
1087 .sizeof_IP = 8,
1088
1089 /* Describe any sections to be regarded by Memcheck as
1090 'always-defined'. */
1091 .n_alwaysDefd = 12,
1092
1093 .alwaysDefd
1094 = { /* 0 */ ALWAYSDEFD64(guest_CIA),
1095 /* 1 */ ALWAYSDEFD64(guest_EMNOTE),
1096 /* 2 */ ALWAYSDEFD64(guest_CMSTART),
1097 /* 3 */ ALWAYSDEFD64(guest_CMLEN),
1098 /* 4 */ ALWAYSDEFD64(guest_VSCR),
1099 /* 5 */ ALWAYSDEFD64(guest_FPROUND),
1100 /* 6 */ ALWAYSDEFD64(guest_NRADDR),
1101 /* 7 */ ALWAYSDEFD64(guest_NRADDR_GPR2),
1102 /* 8 */ ALWAYSDEFD64(guest_REDIR_SP),
1103 /* 9 */ ALWAYSDEFD64(guest_REDIR_STACK),
1104 /* 10 */ ALWAYSDEFD64(guest_IP_AT_SYSCALL),
1105 /* 11 */ ALWAYSDEFD64(guest_C_FPCC)
1106 }
1107 };
1108
1109 /*---------------------------------------------------------------*/
1110 /*--- end guest_ppc_helpers.c ---*/
1111 /*---------------------------------------------------------------*/
1112