1/* -*- mode: C; c-basic-offset: 3; -*- */ 2 3/* 4 This file is part of MemCheck, a heavyweight Valgrind tool for 5 detecting memory errors. 6 7 Copyright (C) 2012-2015 Florian Krohm 8 9 This program is free software; you can redistribute it and/or 10 modify it under the terms of the GNU General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, but 15 WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 22 02111-1307, USA. 23 24 The GNU General Public License is contained in the file COPYING. 25*/ 26 27#include <assert.h> 28#include "memcheck.h" // VALGRIND_SET_VBITS 29#include "vtest.h" 30 31 32/* Return a completely initialised control block */ 33IRICB 34new_iricb(const irop_t *op, test_data_t *data) 35{ 36 IRICB cb; 37 38 cb.op = op->op; 39 cb.result = (HWord)&data->result.value; 40 cb.opnd1 = (HWord)&data->opnds[0].value; 41 cb.opnd2 = (HWord)&data->opnds[1].value; 42 cb.opnd3 = (HWord)&data->opnds[2].value; 43 cb.opnd4 = (HWord)&data->opnds[3].value; 44 cb.t_result = data->result.type; 45 cb.t_opnd1 = data->opnds[0].type; 46 cb.t_opnd2 = data->opnds[1].type; 47 cb.t_opnd3 = data->opnds[2].type; 48 cb.t_opnd4 = data->opnds[3].type; 49 50 cb.rounding_mode = data->rounding_mode; 51 52 cb.num_operands = get_num_operands(op->op); 53 54 cb.shift_amount_is_immediate = op->shift_amount_is_immediate; 55 56 return cb; 57} 58 59 60/* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store 61 such a value from/to a 4-byte container. It uses 32to1 and 1Uto32, 62 respectively. */ 63static void 64valgrind_set_vbits(opnd_t *opnd) 65{ 66 unsigned rc, num_bytes; 67 68 /* 1-bit wide values cannot be read. So we read a 4 bytes here */ 69 num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type); 70 rc = VALGRIND_SET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes); 71 assert(rc == 1); 72 73 // Make sure the v-bits were set correctly 74 vbits_t actual = { .num_bits = opnd->vbits.num_bits }; 75 rc = VALGRIND_GET_VBITS(&opnd->value, &actual.bits, num_bytes); 76 assert(rc == 1); 77 78 assert(equal_vbits(opnd->vbits, actual)); 79} 80 81 82static void 83valgrind_get_vbits(opnd_t *opnd) 84{ 85 unsigned rc, num_bytes; 86 87 /* 1-bit wide values cannot be stored. So we store them by writing a 88 single byte */ 89 num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type); 90 opnd->vbits.num_bits = bitsof_irtype(opnd->type); 91 rc = VALGRIND_GET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes); 92 assert(rc == 1); 93} 94 95 96/* Insert a client request that will initialize VEX for IR injection */ 97void 98valgrind_vex_init_for_iri(IRICB *cb) 99{ 100 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__VEX_INIT_FOR_IRI, cb, 0,0,0,0); 101} 102 103 104/* Insert a special opcode that will cause VEX to inject an IR stmt based 105 on the information passed in the IRICB (in valgrind_vex_init_for_iri). */ 106static void 107valgrind_vex_inject_ir(void) 108{ 109 VALGRIND_VEX_INJECT_IR(); 110} 111 112 113/* Execute the test under valgrind. Well, yes, we're not really executing 114 it here, just preparing for it... */ 115void 116valgrind_execute_test(const irop_t *op, test_data_t *data) 117{ 118 unsigned i, num_operands; 119 120 if (verbose > 2) printf("---------- Running a test\n"); 121 num_operands = get_num_operands(op->op); 122 123 for (i = 0; i < num_operands; ++i) { 124 valgrind_set_vbits(&data->opnds[i]); 125 if (verbose > 2) { 126 printf("opnd #%u: ", i); 127 print_opnd(stdout, &data->opnds[i]); 128 printf("\n"); 129 } 130 } 131 if (verbose > 2) 132 if (data->rounding_mode != NO_ROUNDING_MODE) 133 printf("rounding mode %u\n", data->rounding_mode); 134 135 valgrind_vex_inject_ir(); 136 valgrind_get_vbits(&data->result); 137 if (verbose > 2) { 138 printf("result: "); 139 print_opnd(stdout, &data->result); 140 printf("\n"); 141 } 142} 143