1 2/*---------------------------------------------------------------*/ 3/*--- begin guest_arm_helpers.c ---*/ 4/*---------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2004-2012 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 31#include "libvex_basictypes.h" 32#include "libvex_emwarn.h" 33#include "libvex_guest_arm.h" 34#include "libvex_ir.h" 35#include "libvex.h" 36 37#include "main_util.h" 38#include "guest_generic_bb_to_IR.h" 39#include "guest_arm_defs.h" 40 41 42/* This file contains helper functions for arm guest code. Calls to 43 these functions are generated by the back end. These calls are of 44 course in the host machine code and this file will be compiled to 45 host machine code, so that all makes sense. 46 47 Only change the signatures of these helper functions very 48 carefully. If you change the signature here, you'll have to change 49 the parameters passed to it in the IR calls constructed by 50 guest-arm/toIR.c. 51*/ 52 53 54/* Set to 1 to get detailed profiling info about individual N, Z, C 55 and V flag evaluation. */ 56#define PROFILE_NZCV_FLAGS 0 57 58#if PROFILE_NZCV_FLAGS 59 60static UInt tab_n_eval[ARMG_CC_OP_NUMBER]; 61static UInt tab_z_eval[ARMG_CC_OP_NUMBER]; 62static UInt tab_c_eval[ARMG_CC_OP_NUMBER]; 63static UInt tab_v_eval[ARMG_CC_OP_NUMBER]; 64static UInt initted = 0; 65static UInt tot_evals = 0; 66 67static void initCounts ( void ) 68{ 69 UInt i; 70 for (i = 0; i < ARMG_CC_OP_NUMBER; i++) { 71 tab_n_eval[i] = tab_z_eval[i] = tab_c_eval[i] = tab_v_eval[i] = 0; 72 } 73 initted = 1; 74} 75 76static void showCounts ( void ) 77{ 78 UInt i; 79 vex_printf("\n N Z C V\n"); 80 vex_printf( "---------------------------------------------------\n"); 81 for (i = 0; i < ARMG_CC_OP_NUMBER; i++) { 82 vex_printf("CC_OP=%d %9d %9d %9d %9d\n", 83 i, 84 tab_n_eval[i], tab_z_eval[i], 85 tab_c_eval[i], tab_v_eval[i] ); 86 } 87} 88 89#define NOTE_N_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_n_eval) 90#define NOTE_Z_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_z_eval) 91#define NOTE_C_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_c_eval) 92#define NOTE_V_EVAL(_cc_op) NOTE_EVAL(_cc_op, tab_v_eval) 93 94#define NOTE_EVAL(_cc_op, _tab) \ 95 do { \ 96 if (!initted) initCounts(); \ 97 vassert( ((UInt)(_cc_op)) < ARMG_CC_OP_NUMBER); \ 98 _tab[(UInt)(_cc_op)]++; \ 99 tot_evals++; \ 100 if (0 == (tot_evals & 0xFFFFF)) \ 101 showCounts(); \ 102 } while (0) 103 104#endif /* PROFILE_NZCV_FLAGS */ 105 106 107/* Calculate the N flag from the supplied thunk components, in the 108 least significant bit of the word. Returned bits 31:1 are zero. */ 109static 110UInt armg_calculate_flag_n ( UInt cc_op, UInt cc_dep1, 111 UInt cc_dep2, UInt cc_dep3 ) 112{ 113# if PROFILE_NZCV_FLAGS 114 NOTE_N_EVAL(cc_op); 115# endif 116 117 switch (cc_op) { 118 case ARMG_CC_OP_COPY: { 119 /* (nzcv:28x0, unused, unused) */ 120 UInt nf = (cc_dep1 >> ARMG_CC_SHIFT_N) & 1; 121 return nf; 122 } 123 case ARMG_CC_OP_ADD: { 124 /* (argL, argR, unused) */ 125 UInt argL = cc_dep1; 126 UInt argR = cc_dep2; 127 UInt res = argL + argR; 128 UInt nf = res >> 31; 129 return nf; 130 } 131 case ARMG_CC_OP_SUB: { 132 /* (argL, argR, unused) */ 133 UInt argL = cc_dep1; 134 UInt argR = cc_dep2; 135 UInt res = argL - argR; 136 UInt nf = res >> 31; 137 return nf; 138 } 139 case ARMG_CC_OP_ADC: { 140 /* (argL, argR, oldC) */ 141 UInt argL = cc_dep1; 142 UInt argR = cc_dep2; 143 UInt oldC = cc_dep3; 144 vassert((oldC & ~1) == 0); 145 UInt res = argL + argR + oldC; 146 UInt nf = res >> 31; 147 return nf; 148 } 149 case ARMG_CC_OP_SBB: { 150 /* (argL, argR, oldC) */ 151 UInt argL = cc_dep1; 152 UInt argR = cc_dep2; 153 UInt oldC = cc_dep3; 154 vassert((oldC & ~1) == 0); 155 UInt res = argL - argR - (oldC ^ 1); 156 UInt nf = res >> 31; 157 return nf; 158 } 159 case ARMG_CC_OP_LOGIC: { 160 /* (res, shco, oldV) */ 161 UInt res = cc_dep1; 162 UInt nf = res >> 31; 163 return nf; 164 } 165 case ARMG_CC_OP_MUL: { 166 /* (res, unused, oldC:oldV) */ 167 UInt res = cc_dep1; 168 UInt nf = res >> 31; 169 return nf; 170 } 171 case ARMG_CC_OP_MULL: { 172 /* (resLo32, resHi32, oldC:oldV) */ 173 UInt resHi32 = cc_dep2; 174 UInt nf = resHi32 >> 31; 175 return nf; 176 } 177 default: 178 /* shouldn't really make these calls from generated code */ 179 vex_printf("armg_calculate_flag_n" 180 "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n", 181 cc_op, cc_dep1, cc_dep2, cc_dep3 ); 182 vpanic("armg_calculate_flags_n"); 183 } 184} 185 186 187/* Calculate the Z flag from the supplied thunk components, in the 188 least significant bit of the word. Returned bits 31:1 are zero. */ 189static 190UInt armg_calculate_flag_z ( UInt cc_op, UInt cc_dep1, 191 UInt cc_dep2, UInt cc_dep3 ) 192{ 193# if PROFILE_NZCV_FLAGS 194 NOTE_Z_EVAL(cc_op); 195# endif 196 197 switch (cc_op) { 198 case ARMG_CC_OP_COPY: { 199 /* (nzcv:28x0, unused, unused) */ 200 UInt zf = (cc_dep1 >> ARMG_CC_SHIFT_Z) & 1; 201 return zf; 202 } 203 case ARMG_CC_OP_ADD: { 204 /* (argL, argR, unused) */ 205 UInt argL = cc_dep1; 206 UInt argR = cc_dep2; 207 UInt res = argL + argR; 208 UInt zf = res == 0; 209 return zf; 210 } 211 case ARMG_CC_OP_SUB: { 212 /* (argL, argR, unused) */ 213 UInt argL = cc_dep1; 214 UInt argR = cc_dep2; 215 UInt res = argL - argR; 216 UInt zf = res == 0; 217 return zf; 218 } 219 case ARMG_CC_OP_ADC: { 220 /* (argL, argR, oldC) */ 221 UInt argL = cc_dep1; 222 UInt argR = cc_dep2; 223 UInt oldC = cc_dep3; 224 vassert((oldC & ~1) == 0); 225 UInt res = argL + argR + oldC; 226 UInt zf = res == 0; 227 return zf; 228 } 229 case ARMG_CC_OP_SBB: { 230 /* (argL, argR, oldC) */ 231 UInt argL = cc_dep1; 232 UInt argR = cc_dep2; 233 UInt oldC = cc_dep3; 234 vassert((oldC & ~1) == 0); 235 UInt res = argL - argR - (oldC ^ 1); 236 UInt zf = res == 0; 237 return zf; 238 } 239 case ARMG_CC_OP_LOGIC: { 240 /* (res, shco, oldV) */ 241 UInt res = cc_dep1; 242 UInt zf = res == 0; 243 return zf; 244 } 245 case ARMG_CC_OP_MUL: { 246 /* (res, unused, oldC:oldV) */ 247 UInt res = cc_dep1; 248 UInt zf = res == 0; 249 return zf; 250 } 251 case ARMG_CC_OP_MULL: { 252 /* (resLo32, resHi32, oldC:oldV) */ 253 UInt resLo32 = cc_dep1; 254 UInt resHi32 = cc_dep2; 255 UInt zf = (resHi32|resLo32) == 0; 256 return zf; 257 } 258 default: 259 /* shouldn't really make these calls from generated code */ 260 vex_printf("armg_calculate_flags_z" 261 "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n", 262 cc_op, cc_dep1, cc_dep2, cc_dep3 ); 263 vpanic("armg_calculate_flags_z"); 264 } 265} 266 267 268/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 269/* Calculate the C flag from the supplied thunk components, in the 270 least significant bit of the word. Returned bits 31:1 are zero. */ 271UInt armg_calculate_flag_c ( UInt cc_op, UInt cc_dep1, 272 UInt cc_dep2, UInt cc_dep3 ) 273{ 274# if PROFILE_NZCV_FLAGS 275 NOTE_C_EVAL(cc_op); 276# endif 277 278 switch (cc_op) { 279 case ARMG_CC_OP_COPY: { 280 /* (nzcv:28x0, unused, unused) */ 281 UInt cf = (cc_dep1 >> ARMG_CC_SHIFT_C) & 1; 282 return cf; 283 } 284 case ARMG_CC_OP_ADD: { 285 /* (argL, argR, unused) */ 286 UInt argL = cc_dep1; 287 UInt argR = cc_dep2; 288 UInt res = argL + argR; 289 UInt cf = res < argL; 290 return cf; 291 } 292 case ARMG_CC_OP_SUB: { 293 /* (argL, argR, unused) */ 294 UInt argL = cc_dep1; 295 UInt argR = cc_dep2; 296 UInt cf = argL >= argR; 297 return cf; 298 } 299 case ARMG_CC_OP_ADC: { 300 /* (argL, argR, oldC) */ 301 UInt argL = cc_dep1; 302 UInt argR = cc_dep2; 303 UInt oldC = cc_dep3; 304 vassert((oldC & ~1) == 0); 305 UInt res = argL + argR + oldC; 306 UInt cf = oldC ? (res <= argL) : (res < argL); 307 return cf; 308 } 309 case ARMG_CC_OP_SBB: { 310 /* (argL, argR, oldC) */ 311 UInt argL = cc_dep1; 312 UInt argR = cc_dep2; 313 UInt oldC = cc_dep3; 314 vassert((oldC & ~1) == 0); 315 UInt cf = oldC ? (argL >= argR) : (argL > argR); 316 return cf; 317 } 318 case ARMG_CC_OP_LOGIC: { 319 /* (res, shco, oldV) */ 320 UInt shco = cc_dep2; 321 vassert((shco & ~1) == 0); 322 UInt cf = shco; 323 return cf; 324 } 325 case ARMG_CC_OP_MUL: { 326 /* (res, unused, oldC:oldV) */ 327 UInt oldC = (cc_dep3 >> 1) & 1; 328 vassert((cc_dep3 & ~3) == 0); 329 UInt cf = oldC; 330 return cf; 331 } 332 case ARMG_CC_OP_MULL: { 333 /* (resLo32, resHi32, oldC:oldV) */ 334 UInt oldC = (cc_dep3 >> 1) & 1; 335 vassert((cc_dep3 & ~3) == 0); 336 UInt cf = oldC; 337 return cf; 338 } 339 default: 340 /* shouldn't really make these calls from generated code */ 341 vex_printf("armg_calculate_flag_c" 342 "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n", 343 cc_op, cc_dep1, cc_dep2, cc_dep3 ); 344 vpanic("armg_calculate_flag_c"); 345 } 346} 347 348 349/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 350/* Calculate the V flag from the supplied thunk components, in the 351 least significant bit of the word. Returned bits 31:1 are zero. */ 352UInt armg_calculate_flag_v ( UInt cc_op, UInt cc_dep1, 353 UInt cc_dep2, UInt cc_dep3 ) 354{ 355# if PROFILE_NZCV_FLAGS 356 NOTE_V_EVAL(cc_op); 357# endif 358 359 switch (cc_op) { 360 case ARMG_CC_OP_COPY: { 361 /* (nzcv:28x0, unused, unused) */ 362 UInt vf = (cc_dep1 >> ARMG_CC_SHIFT_V) & 1; 363 return vf; 364 } 365 case ARMG_CC_OP_ADD: { 366 /* (argL, argR, unused) */ 367 UInt argL = cc_dep1; 368 UInt argR = cc_dep2; 369 UInt res = argL + argR; 370 UInt vf = ((res ^ argL) & (res ^ argR)) >> 31; 371 return vf; 372 } 373 case ARMG_CC_OP_SUB: { 374 /* (argL, argR, unused) */ 375 UInt argL = cc_dep1; 376 UInt argR = cc_dep2; 377 UInt res = argL - argR; 378 UInt vf = ((argL ^ argR) & (argL ^ res)) >> 31; 379 return vf; 380 } 381 case ARMG_CC_OP_ADC: { 382 /* (argL, argR, oldC) */ 383 UInt argL = cc_dep1; 384 UInt argR = cc_dep2; 385 UInt oldC = cc_dep3; 386 vassert((oldC & ~1) == 0); 387 UInt res = argL + argR + oldC; 388 UInt vf = ((res ^ argL) & (res ^ argR)) >> 31; 389 return vf; 390 } 391 case ARMG_CC_OP_SBB: { 392 /* (argL, argR, oldC) */ 393 UInt argL = cc_dep1; 394 UInt argR = cc_dep2; 395 UInt oldC = cc_dep3; 396 vassert((oldC & ~1) == 0); 397 UInt res = argL - argR - (oldC ^ 1); 398 UInt vf = ((argL ^ argR) & (argL ^ res)) >> 31; 399 return vf; 400 } 401 case ARMG_CC_OP_LOGIC: { 402 /* (res, shco, oldV) */ 403 UInt oldV = cc_dep3; 404 vassert((oldV & ~1) == 0); 405 UInt vf = oldV; 406 return vf; 407 } 408 case ARMG_CC_OP_MUL: { 409 /* (res, unused, oldC:oldV) */ 410 UInt oldV = (cc_dep3 >> 0) & 1; 411 vassert((cc_dep3 & ~3) == 0); 412 UInt vf = oldV; 413 return vf; 414 } 415 case ARMG_CC_OP_MULL: { 416 /* (resLo32, resHi32, oldC:oldV) */ 417 UInt oldV = (cc_dep3 >> 0) & 1; 418 vassert((cc_dep3 & ~3) == 0); 419 UInt vf = oldV; 420 return vf; 421 } 422 default: 423 /* shouldn't really make these calls from generated code */ 424 vex_printf("armg_calculate_flag_v" 425 "( op=%u, dep1=0x%x, dep2=0x%x, dep3=0x%x )\n", 426 cc_op, cc_dep1, cc_dep2, cc_dep3 ); 427 vpanic("armg_calculate_flag_v"); 428 } 429} 430 431 432/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 433/* Calculate NZCV from the supplied thunk components, in the positions 434 they appear in the CPSR, viz bits 31:28 for N Z C V respectively. 435 Returned bits 27:0 are zero. */ 436UInt armg_calculate_flags_nzcv ( UInt cc_op, UInt cc_dep1, 437 UInt cc_dep2, UInt cc_dep3 ) 438{ 439 UInt f; 440 UInt res = 0; 441 f = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3); 442 res |= (f << ARMG_CC_SHIFT_N); 443 f = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3); 444 res |= (f << ARMG_CC_SHIFT_Z); 445 f = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3); 446 res |= (f << ARMG_CC_SHIFT_C); 447 f = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3); 448 res |= (f << ARMG_CC_SHIFT_V); 449 return res; 450} 451 452 453/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 454/* Calculate the QC flag from the arguments, in the lowest bit 455 of the word (bit 0). Urr, having this out of line is bizarre. 456 Push back inline. */ 457UInt armg_calculate_flag_qc ( UInt resL1, UInt resL2, 458 UInt resR1, UInt resR2 ) 459{ 460 if (resL1 != resR1 || resL2 != resR2) 461 return 1; 462 else 463 return 0; 464} 465 466/* CALLED FROM GENERATED CODE: CLEAN HELPER */ 467/* Calculate the specified condition from the thunk components, in the 468 lowest bit of the word (bit 0). Returned bits 31:1 are zero. */ 469UInt armg_calculate_condition ( UInt cond_n_op /* (ARMCondcode << 4) | cc_op */, 470 UInt cc_dep1, 471 UInt cc_dep2, UInt cc_dep3 ) 472{ 473 UInt cond = cond_n_op >> 4; 474 UInt cc_op = cond_n_op & 0xF; 475 UInt nf, zf, vf, cf, inv; 476 // vex_printf("XXXXXXXX %x %x %x %x\n", 477 // cond_n_op, cc_dep1, cc_dep2, cc_dep3); 478 479 // skip flags computation in this case 480 if (cond == ARMCondAL) return 1; 481 482 inv = cond & 1; 483 484 switch (cond) { 485 case ARMCondEQ: // Z=1 => z 486 case ARMCondNE: // Z=0 487 zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3); 488 return inv ^ zf; 489 490 case ARMCondHS: // C=1 => c 491 case ARMCondLO: // C=0 492 cf = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3); 493 return inv ^ cf; 494 495 case ARMCondMI: // N=1 => n 496 case ARMCondPL: // N=0 497 nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3); 498 return inv ^ nf; 499 500 case ARMCondVS: // V=1 => v 501 case ARMCondVC: // V=0 502 vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3); 503 return inv ^ vf; 504 505 case ARMCondHI: // C=1 && Z=0 => c & ~z 506 case ARMCondLS: // C=0 || Z=1 507 cf = armg_calculate_flag_c(cc_op, cc_dep1, cc_dep2, cc_dep3); 508 zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3); 509 return inv ^ (cf & ~zf); 510 511 case ARMCondGE: // N=V => ~(n^v) 512 case ARMCondLT: // N!=V 513 nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3); 514 vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3); 515 return inv ^ (1 & ~(nf ^ vf)); 516 517 case ARMCondGT: // Z=0 && N=V => ~z & ~(n^v) => ~(z | (n^v)) 518 case ARMCondLE: // Z=1 || N!=V 519 nf = armg_calculate_flag_n(cc_op, cc_dep1, cc_dep2, cc_dep3); 520 vf = armg_calculate_flag_v(cc_op, cc_dep1, cc_dep2, cc_dep3); 521 zf = armg_calculate_flag_z(cc_op, cc_dep1, cc_dep2, cc_dep3); 522 return inv ^ (1 & ~(zf | (nf ^ vf))); 523 524 case ARMCondAL: // handled above 525 case ARMCondNV: // should never get here: Illegal instr 526 default: 527 /* shouldn't really make these calls from generated code */ 528 vex_printf("armg_calculate_condition(ARM)" 529 "( %u, %u, 0x%x, 0x%x, 0x%x )\n", 530 cond, cc_op, cc_dep1, cc_dep2, cc_dep3 ); 531 vpanic("armg_calculate_condition(ARM)"); 532 } 533} 534 535 536/*---------------------------------------------------------------*/ 537/*--- Flag-helpers translation-time function specialisers. ---*/ 538/*--- These help iropt specialise calls the above run-time ---*/ 539/*--- flags functions. ---*/ 540/*---------------------------------------------------------------*/ 541 542/* Used by the optimiser to try specialisations. Returns an 543 equivalent expression, or NULL if none. */ 544 545static Bool isU32 ( IRExpr* e, UInt n ) 546{ 547 return 548 toBool( e->tag == Iex_Const 549 && e->Iex.Const.con->tag == Ico_U32 550 && e->Iex.Const.con->Ico.U32 == n ); 551} 552 553IRExpr* guest_arm_spechelper ( HChar* function_name, 554 IRExpr** args, 555 IRStmt** precedingStmts, 556 Int n_precedingStmts ) 557{ 558# define unop(_op,_a1) IRExpr_Unop((_op),(_a1)) 559# define binop(_op,_a1,_a2) IRExpr_Binop((_op),(_a1),(_a2)) 560# define mkU32(_n) IRExpr_Const(IRConst_U32(_n)) 561# define mkU8(_n) IRExpr_Const(IRConst_U8(_n)) 562 563 Int i, arity = 0; 564 for (i = 0; args[i]; i++) 565 arity++; 566# if 0 567 vex_printf("spec request:\n"); 568 vex_printf(" %s ", function_name); 569 for (i = 0; i < arity; i++) { 570 vex_printf(" "); 571 ppIRExpr(args[i]); 572 } 573 vex_printf("\n"); 574# endif 575 576 /* --------- specialising "armg_calculate_condition" --------- */ 577 578 if (vex_streq(function_name, "armg_calculate_condition")) { 579 580 /* specialise calls to the "armg_calculate_condition" function. 581 Not sure whether this is strictly necessary, but: the 582 replacement IR must produce only the values 0 or 1. Bits 583 31:1 are required to be zero. */ 584 IRExpr *cond_n_op, *cc_dep1, *cc_dep2, *cc_ndep; 585 vassert(arity == 4); 586 cond_n_op = args[0]; /* (ARMCondcode << 4) | ARMG_CC_OP_* */ 587 cc_dep1 = args[1]; 588 cc_dep2 = args[2]; 589 cc_ndep = args[3]; 590 591 /*---------------- SUB ----------------*/ 592 593 if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_SUB)) { 594 /* EQ after SUB --> test argL == argR */ 595 return unop(Iop_1Uto32, 596 binop(Iop_CmpEQ32, cc_dep1, cc_dep2)); 597 } 598 if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_SUB)) { 599 /* NE after SUB --> test argL != argR */ 600 return unop(Iop_1Uto32, 601 binop(Iop_CmpNE32, cc_dep1, cc_dep2)); 602 } 603 604 if (isU32(cond_n_op, (ARMCondGT << 4) | ARMG_CC_OP_SUB)) { 605 /* GT after SUB --> test argL >s argR 606 --> test argR <s argL */ 607 return unop(Iop_1Uto32, 608 binop(Iop_CmpLT32S, cc_dep2, cc_dep1)); 609 } 610 if (isU32(cond_n_op, (ARMCondLE << 4) | ARMG_CC_OP_SUB)) { 611 /* LE after SUB --> test argL <=s argR */ 612 return unop(Iop_1Uto32, 613 binop(Iop_CmpLE32S, cc_dep1, cc_dep2)); 614 } 615 616 if (isU32(cond_n_op, (ARMCondLT << 4) | ARMG_CC_OP_SUB)) { 617 /* LT after SUB --> test argL <s argR */ 618 return unop(Iop_1Uto32, 619 binop(Iop_CmpLT32S, cc_dep1, cc_dep2)); 620 } 621 622 if (isU32(cond_n_op, (ARMCondGE << 4) | ARMG_CC_OP_SUB)) { 623 /* GE after SUB --> test argL >=s argR 624 --> test argR <=s argL */ 625 return unop(Iop_1Uto32, 626 binop(Iop_CmpLE32S, cc_dep2, cc_dep1)); 627 } 628 629 if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SUB)) { 630 /* HS after SUB --> test argL >=u argR 631 --> test argR <=u argL */ 632 return unop(Iop_1Uto32, 633 binop(Iop_CmpLE32U, cc_dep2, cc_dep1)); 634 } 635 if (isU32(cond_n_op, (ARMCondLO << 4) | ARMG_CC_OP_SUB)) { 636 /* LO after SUB --> test argL <u argR */ 637 return unop(Iop_1Uto32, 638 binop(Iop_CmpLT32U, cc_dep1, cc_dep2)); 639 } 640 641 if (isU32(cond_n_op, (ARMCondLS << 4) | ARMG_CC_OP_SUB)) { 642 /* LS after SUB --> test argL <=u argR */ 643 return unop(Iop_1Uto32, 644 binop(Iop_CmpLE32U, cc_dep1, cc_dep2)); 645 } 646 if (isU32(cond_n_op, (ARMCondHI << 4) | ARMG_CC_OP_SUB)) { 647 /* HI after SUB --> test argL >u argR 648 --> test argR <u argL */ 649 return unop(Iop_1Uto32, 650 binop(Iop_CmpLT32U, cc_dep2, cc_dep1)); 651 } 652 653 /*---------------- SBB ----------------*/ 654 655 if (isU32(cond_n_op, (ARMCondHS << 4) | ARMG_CC_OP_SBB)) { 656 /* This seems to happen a lot in softfloat code, eg __divdf3+140 */ 657 /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */ 658 /* HS after SBB (same as C after SBB below) 659 --> oldC ? (argL >=u argR) : (argL >u argR) 660 --> oldC ? (argR <=u argL) : (argR <u argL) 661 */ 662 return 663 IRExpr_Mux0X( 664 unop(Iop_32to8, cc_ndep), 665 /* case oldC == 0 */ 666 unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1)), 667 /* case oldC != 0 */ 668 unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)) 669 ); 670 } 671 672 /*---------------- LOGIC ----------------*/ 673 674 if (isU32(cond_n_op, (ARMCondEQ << 4) | ARMG_CC_OP_LOGIC)) { 675 /* EQ after LOGIC --> test res == 0 */ 676 return unop(Iop_1Uto32, 677 binop(Iop_CmpEQ32, cc_dep1, mkU32(0))); 678 } 679 if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_LOGIC)) { 680 /* NE after LOGIC --> test res != 0 */ 681 return unop(Iop_1Uto32, 682 binop(Iop_CmpNE32, cc_dep1, mkU32(0))); 683 } 684 685 if (isU32(cond_n_op, (ARMCondPL << 4) | ARMG_CC_OP_LOGIC)) { 686 /* PL after LOGIC --> test (res >> 31) == 0 */ 687 return unop(Iop_1Uto32, 688 binop(Iop_CmpEQ32, 689 binop(Iop_Shr32, cc_dep1, mkU8(31)), 690 mkU32(0))); 691 } 692 if (isU32(cond_n_op, (ARMCondMI << 4) | ARMG_CC_OP_LOGIC)) { 693 /* MI after LOGIC --> test (res >> 31) == 1 */ 694 return unop(Iop_1Uto32, 695 binop(Iop_CmpEQ32, 696 binop(Iop_Shr32, cc_dep1, mkU8(31)), 697 mkU32(1))); 698 } 699 700 /*---------------- COPY ----------------*/ 701 702 if (isU32(cond_n_op, (ARMCondNE << 4) | ARMG_CC_OP_COPY)) { 703 /* NE after COPY --> ((cc_dep1 >> ARMG_CC_SHIFT_Z) ^ 1) & 1 */ 704 return binop(Iop_And32, 705 binop(Iop_Xor32, 706 binop(Iop_Shr32, cc_dep1, 707 mkU8(ARMG_CC_SHIFT_Z)), 708 mkU32(1)), 709 mkU32(1)); 710 } 711 712 /*----------------- AL -----------------*/ 713 714 /* A critically important case for Thumb code. 715 716 What we're trying to spot is the case where cond_n_op is an 717 expression of the form Or32(..., 0xE0) since that means the 718 caller is asking for CondAL and we can simply return 1 719 without caring what the ... part is. This is a potentially 720 dodgy kludge in that it assumes that the ... part has zeroes 721 in bits 7:4, so that the result of the Or32 is guaranteed to 722 be 0xE in bits 7:4. Given that the places where this first 723 arg are constructed (in guest_arm_toIR.c) are very 724 constrained, we can get away with this. To make this 725 guaranteed safe would require to have a new primop, Slice44 726 or some such, thusly 727 728 Slice44(arg1, arg2) = 0--(24)--0 arg1[7:4] arg2[3:0] 729 730 and we would then look for Slice44(0xE0, ...) 731 which would give the required safety property. 732 733 It would be infeasibly expensive to scan backwards through 734 the entire block looking for an assignment to the temp, so 735 just look at the previous 16 statements. That should find it 736 if it is an interesting case, as a result of how the 737 boilerplate guff at the start of each Thumb insn translation 738 is made. 739 */ 740 if (cond_n_op->tag == Iex_RdTmp) { 741 Int j; 742 IRTemp look_for = cond_n_op->Iex.RdTmp.tmp; 743 Int limit = n_precedingStmts - 16; 744 if (limit < 0) limit = 0; 745 if (0) vex_printf("scanning %d .. %d\n", n_precedingStmts-1, limit); 746 for (j = n_precedingStmts - 1; j >= limit; j--) { 747 IRStmt* st = precedingStmts[j]; 748 if (st->tag == Ist_WrTmp 749 && st->Ist.WrTmp.tmp == look_for 750 && st->Ist.WrTmp.data->tag == Iex_Binop 751 && st->Ist.WrTmp.data->Iex.Binop.op == Iop_Or32 752 && isU32(st->Ist.WrTmp.data->Iex.Binop.arg2, (ARMCondAL << 4))) 753 return mkU32(1); 754 } 755 /* Didn't find any useful binding to the first arg 756 in the previous 16 stmts. */ 757 } 758 } 759 760 /* --------- specialising "armg_calculate_flag_c" --------- */ 761 762 else 763 if (vex_streq(function_name, "armg_calculate_flag_c")) { 764 765 /* specialise calls to the "armg_calculate_flag_c" function. 766 Note that the returned value must be either 0 or 1; nonzero 767 bits 31:1 are not allowed. In turn, incoming oldV and oldC 768 values (from the thunk) are assumed to have bits 31:1 769 clear. */ 770 IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep; 771 vassert(arity == 4); 772 cc_op = args[0]; /* ARMG_CC_OP_* */ 773 cc_dep1 = args[1]; 774 cc_dep2 = args[2]; 775 cc_ndep = args[3]; 776 777 if (isU32(cc_op, ARMG_CC_OP_LOGIC)) { 778 /* Thunk args are (result, shco, oldV) */ 779 /* C after LOGIC --> shco */ 780 return cc_dep2; 781 } 782 783 if (isU32(cc_op, ARMG_CC_OP_SUB)) { 784 /* Thunk args are (argL, argR, unused) */ 785 /* C after SUB --> argL >=u argR 786 --> argR <=u argL */ 787 return unop(Iop_1Uto32, 788 binop(Iop_CmpLE32U, cc_dep2, cc_dep1)); 789 } 790 791 if (isU32(cc_op, ARMG_CC_OP_SBB)) { 792 /* This happens occasionally in softfloat code, eg __divdf3+140 */ 793 /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */ 794 /* C after SBB (same as HS after SBB above) 795 --> oldC ? (argL >=u argR) : (argL >u argR) 796 --> oldC ? (argR <=u argL) : (argR <u argL) 797 */ 798 return 799 IRExpr_Mux0X( 800 unop(Iop_32to8, cc_ndep), 801 /* case oldC == 0 */ 802 unop(Iop_1Uto32, binop(Iop_CmpLT32U, cc_dep2, cc_dep1)), 803 /* case oldC != 0 */ 804 unop(Iop_1Uto32, binop(Iop_CmpLE32U, cc_dep2, cc_dep1)) 805 ); 806 } 807 808 } 809 810 /* --------- specialising "armg_calculate_flag_v" --------- */ 811 812 else 813 if (vex_streq(function_name, "armg_calculate_flag_v")) { 814 815 /* specialise calls to the "armg_calculate_flag_v" function. 816 Note that the returned value must be either 0 or 1; nonzero 817 bits 31:1 are not allowed. In turn, incoming oldV and oldC 818 values (from the thunk) are assumed to have bits 31:1 819 clear. */ 820 IRExpr *cc_op, *cc_dep1, *cc_dep2, *cc_ndep; 821 vassert(arity == 4); 822 cc_op = args[0]; /* ARMG_CC_OP_* */ 823 cc_dep1 = args[1]; 824 cc_dep2 = args[2]; 825 cc_ndep = args[3]; 826 827 if (isU32(cc_op, ARMG_CC_OP_LOGIC)) { 828 /* Thunk args are (result, shco, oldV) */ 829 /* V after LOGIC --> oldV */ 830 return cc_ndep; 831 } 832 833 if (isU32(cc_op, ARMG_CC_OP_SUB)) { 834 /* Thunk args are (argL, argR, unused) */ 835 /* V after SUB 836 --> let res = argL - argR 837 in ((argL ^ argR) & (argL ^ res)) >> 31 838 --> ((argL ^ argR) & (argL ^ (argL - argR))) >> 31 839 */ 840 IRExpr* argL = cc_dep1; 841 IRExpr* argR = cc_dep2; 842 return 843 binop(Iop_Shr32, 844 binop(Iop_And32, 845 binop(Iop_Xor32, argL, argR), 846 binop(Iop_Xor32, argL, binop(Iop_Sub32, argL, argR)) 847 ), 848 mkU8(31) 849 ); 850 } 851 852 if (isU32(cc_op, ARMG_CC_OP_SBB)) { 853 /* This happens occasionally in softfloat code, eg __divdf3+140 */ 854 /* thunk is: (dep1=argL, dep2=argR, ndep=oldC) */ 855 /* V after SBB 856 --> let res = argL - argR - (oldC ^ 1) 857 in (argL ^ argR) & (argL ^ res) & 1 858 */ 859 return 860 binop( 861 Iop_And32, 862 binop( 863 Iop_And32, 864 // argL ^ argR 865 binop(Iop_Xor32, cc_dep1, cc_dep2), 866 // argL ^ (argL - argR - (oldC ^ 1)) 867 binop(Iop_Xor32, 868 cc_dep1, 869 binop(Iop_Sub32, 870 binop(Iop_Sub32, cc_dep1, cc_dep2), 871 binop(Iop_Xor32, cc_ndep, mkU32(1))) 872 ) 873 ), 874 mkU32(1) 875 ); 876 } 877 878 } 879 880# undef unop 881# undef binop 882# undef mkU32 883# undef mkU8 884 885 return NULL; 886} 887 888 889/*----------------------------------------------*/ 890/*--- The exported fns .. ---*/ 891/*----------------------------------------------*/ 892 893/* VISIBLE TO LIBVEX CLIENT */ 894#if 0 895void LibVEX_GuestARM_put_flags ( UInt flags_native, 896 /*OUT*/VexGuestARMState* vex_state ) 897{ 898 vassert(0); // FIXME 899 900 /* Mask out everything except N Z V C. */ 901 flags_native 902 &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C); 903 904 vex_state->guest_CC_OP = ARMG_CC_OP_COPY; 905 vex_state->guest_CC_DEP1 = flags_native; 906 vex_state->guest_CC_DEP2 = 0; 907 vex_state->guest_CC_NDEP = 0; 908} 909#endif 910 911/* VISIBLE TO LIBVEX CLIENT */ 912UInt LibVEX_GuestARM_get_cpsr ( /*IN*/VexGuestARMState* vex_state ) 913{ 914 UInt cpsr = 0; 915 // NZCV 916 cpsr |= armg_calculate_flags_nzcv( 917 vex_state->guest_CC_OP, 918 vex_state->guest_CC_DEP1, 919 vex_state->guest_CC_DEP2, 920 vex_state->guest_CC_NDEP 921 ); 922 vassert(0 == (cpsr & 0x0FFFFFFF)); 923 // Q 924 if (vex_state->guest_QFLAG32 > 0) 925 cpsr |= (1 << 27); 926 // GE 927 if (vex_state->guest_GEFLAG0 > 0) 928 cpsr |= (1 << 16); 929 if (vex_state->guest_GEFLAG1 > 0) 930 cpsr |= (1 << 17); 931 if (vex_state->guest_GEFLAG2 > 0) 932 cpsr |= (1 << 18); 933 if (vex_state->guest_GEFLAG3 > 0) 934 cpsr |= (1 << 19); 935 // M 936 cpsr |= (1 << 4); // 0b10000 means user-mode 937 // J,T J (bit 24) is zero by initialisation above 938 // T we copy from R15T[0] 939 if (vex_state->guest_R15T & 1) 940 cpsr |= (1 << 5); 941 // ITSTATE we punt on for the time being. Could compute it 942 // if needed though. 943 // E, endianness, 0 (littleendian) from initialisation above 944 // A,I,F disable some async exceptions. Not sure about these. 945 // Leave as zero for the time being. 946 return cpsr; 947} 948 949/* VISIBLE TO LIBVEX CLIENT */ 950void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state ) 951{ 952 vex_state->host_EvC_FAILADDR = 0; 953 vex_state->host_EvC_COUNTER = 0; 954 955 vex_state->guest_R0 = 0; 956 vex_state->guest_R1 = 0; 957 vex_state->guest_R2 = 0; 958 vex_state->guest_R3 = 0; 959 vex_state->guest_R4 = 0; 960 vex_state->guest_R5 = 0; 961 vex_state->guest_R6 = 0; 962 vex_state->guest_R7 = 0; 963 vex_state->guest_R8 = 0; 964 vex_state->guest_R9 = 0; 965 vex_state->guest_R10 = 0; 966 vex_state->guest_R11 = 0; 967 vex_state->guest_R12 = 0; 968 vex_state->guest_R13 = 0; 969 vex_state->guest_R14 = 0; 970 vex_state->guest_R15T = 0; /* NB: implies ARM mode */ 971 972 vex_state->guest_CC_OP = ARMG_CC_OP_COPY; 973 vex_state->guest_CC_DEP1 = 0; 974 vex_state->guest_CC_DEP2 = 0; 975 vex_state->guest_CC_NDEP = 0; 976 vex_state->guest_QFLAG32 = 0; 977 vex_state->guest_GEFLAG0 = 0; 978 vex_state->guest_GEFLAG1 = 0; 979 vex_state->guest_GEFLAG2 = 0; 980 vex_state->guest_GEFLAG3 = 0; 981 982 vex_state->guest_EMWARN = 0; 983 vex_state->guest_TISTART = 0; 984 vex_state->guest_TILEN = 0; 985 vex_state->guest_NRADDR = 0; 986 vex_state->guest_IP_AT_SYSCALL = 0; 987 988 vex_state->guest_D0 = 0; 989 vex_state->guest_D1 = 0; 990 vex_state->guest_D2 = 0; 991 vex_state->guest_D3 = 0; 992 vex_state->guest_D4 = 0; 993 vex_state->guest_D5 = 0; 994 vex_state->guest_D6 = 0; 995 vex_state->guest_D7 = 0; 996 vex_state->guest_D8 = 0; 997 vex_state->guest_D9 = 0; 998 vex_state->guest_D10 = 0; 999 vex_state->guest_D11 = 0; 1000 vex_state->guest_D12 = 0; 1001 vex_state->guest_D13 = 0; 1002 vex_state->guest_D14 = 0; 1003 vex_state->guest_D15 = 0; 1004 vex_state->guest_D16 = 0; 1005 vex_state->guest_D17 = 0; 1006 vex_state->guest_D18 = 0; 1007 vex_state->guest_D19 = 0; 1008 vex_state->guest_D20 = 0; 1009 vex_state->guest_D21 = 0; 1010 vex_state->guest_D22 = 0; 1011 vex_state->guest_D23 = 0; 1012 vex_state->guest_D24 = 0; 1013 vex_state->guest_D25 = 0; 1014 vex_state->guest_D26 = 0; 1015 vex_state->guest_D27 = 0; 1016 vex_state->guest_D28 = 0; 1017 vex_state->guest_D29 = 0; 1018 vex_state->guest_D30 = 0; 1019 vex_state->guest_D31 = 0; 1020 1021 /* ARM encoded; zero is the default as it happens (result flags 1022 (NZCV) cleared, FZ disabled, round to nearest, non-vector mode, 1023 all exns masked, all exn sticky bits cleared). */ 1024 vex_state->guest_FPSCR = 0; 1025 1026 vex_state->guest_TPIDRURO = 0; 1027 1028 /* Not in a Thumb IT block. */ 1029 vex_state->guest_ITSTATE = 0; 1030 1031 vex_state->padding1 = 0; 1032 vex_state->padding2 = 0; 1033 vex_state->padding3 = 0; 1034 vex_state->padding4 = 0; 1035 vex_state->padding5 = 0; 1036} 1037 1038 1039/*-----------------------------------------------------------*/ 1040/*--- Describing the arm guest state, for the benefit ---*/ 1041/*--- of iropt and instrumenters. ---*/ 1042/*-----------------------------------------------------------*/ 1043 1044/* Figure out if any part of the guest state contained in minoff 1045 .. maxoff requires precise memory exceptions. If in doubt return 1046 True (but this is generates significantly slower code). 1047 1048 We enforce precise exns for guest R13(sp), R15T(pc). 1049*/ 1050Bool guest_arm_state_requires_precise_mem_exns ( Int minoff, 1051 Int maxoff) 1052{ 1053 Int sp_min = offsetof(VexGuestARMState, guest_R13); 1054 Int sp_max = sp_min + 4 - 1; 1055 Int pc_min = offsetof(VexGuestARMState, guest_R15T); 1056 Int pc_max = pc_min + 4 - 1; 1057 1058 if (maxoff < sp_min || minoff > sp_max) { 1059 /* no overlap with sp */ 1060 } else { 1061 return True; 1062 } 1063 1064 if (maxoff < pc_min || minoff > pc_max) { 1065 /* no overlap with pc */ 1066 } else { 1067 return True; 1068 } 1069 1070 /* We appear to need precise updates of R11 in order to get proper 1071 stacktraces from non-optimised code. */ 1072 Int r11_min = offsetof(VexGuestARMState, guest_R11); 1073 Int r11_max = r11_min + 4 - 1; 1074 1075 if (maxoff < r11_min || minoff > r11_max) { 1076 /* no overlap with r11 */ 1077 } else { 1078 return True; 1079 } 1080 1081 /* Ditto R7, particularly needed for proper stacktraces in Thumb 1082 code. */ 1083 Int r7_min = offsetof(VexGuestARMState, guest_R7); 1084 Int r7_max = r7_min + 4 - 1; 1085 1086 if (maxoff < r7_min || minoff > r7_max) { 1087 /* no overlap with r7 */ 1088 } else { 1089 return True; 1090 } 1091 1092 return False; 1093} 1094 1095 1096 1097#define ALWAYSDEFD(field) \ 1098 { offsetof(VexGuestARMState, field), \ 1099 (sizeof ((VexGuestARMState*)0)->field) } 1100 1101VexGuestLayout 1102 armGuest_layout 1103 = { 1104 /* Total size of the guest state, in bytes. */ 1105 .total_sizeB = sizeof(VexGuestARMState), 1106 1107 /* Describe the stack pointer. */ 1108 .offset_SP = offsetof(VexGuestARMState,guest_R13), 1109 .sizeof_SP = 4, 1110 1111 /* Describe the instruction pointer. */ 1112 .offset_IP = offsetof(VexGuestARMState,guest_R15T), 1113 .sizeof_IP = 4, 1114 1115 /* Describe any sections to be regarded by Memcheck as 1116 'always-defined'. */ 1117 .n_alwaysDefd = 10, 1118 1119 /* flags thunk: OP is always defd, whereas DEP1 and DEP2 1120 have to be tracked. See detailed comment in gdefs.h on 1121 meaning of thunk fields. */ 1122 .alwaysDefd 1123 = { /* 0 */ ALWAYSDEFD(guest_R15T), 1124 /* 1 */ ALWAYSDEFD(guest_CC_OP), 1125 /* 2 */ ALWAYSDEFD(guest_CC_NDEP), 1126 /* 3 */ ALWAYSDEFD(guest_EMWARN), 1127 /* 4 */ ALWAYSDEFD(guest_TISTART), 1128 /* 5 */ ALWAYSDEFD(guest_TILEN), 1129 /* 6 */ ALWAYSDEFD(guest_NRADDR), 1130 /* 7 */ ALWAYSDEFD(guest_IP_AT_SYSCALL), 1131 /* 8 */ ALWAYSDEFD(guest_TPIDRURO), 1132 /* 9 */ ALWAYSDEFD(guest_ITSTATE) 1133 } 1134 }; 1135 1136 1137/*---------------------------------------------------------------*/ 1138/*--- end guest_arm_helpers.c ---*/ 1139/*---------------------------------------------------------------*/ 1140