blob: 870c5350a499b02a6d45674e08fe1797dfb1c0b3 [file] [log] [blame]
florianbb913cd2012-08-28 16:50:39 +00001/* -*- mode: C; c-basic-offset: 3; -*- */
2
florian5aa9d1e2015-09-22 07:21:50 +00003/*
4 This file is part of MemCheck, a heavyweight Valgrind tool for
5 detecting memory errors.
6
Elliott Hughesed398002017-06-21 14:41:24 -07007 Copyright (C) 2012-2017 Florian Krohm
florian5aa9d1e2015-09-22 07:21:50 +00008
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
florianbb913cd2012-08-28 16:50:39 +000027#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
Elliott Hughesa0664b92017-04-18 17:46:52 -070054 cb.immediate_index = op->immediate_index;
55 cb.immediate_type = op->immediate_type;
florianf74f5422012-09-13 19:41:12 +000056
florianbb913cd2012-08-28 16:50:39 +000057 return cb;
58}
59
60
61/* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store
62 such a value from/to a 4-byte container. It uses 32to1 and 1Uto32,
63 respectively. */
64static void
65valgrind_set_vbits(opnd_t *opnd)
66{
67 unsigned rc, num_bytes;
68
69 /* 1-bit wide values cannot be read. So we read a 4 bytes here */
70 num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
71 rc = VALGRIND_SET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
72 assert(rc == 1);
73
74 // Make sure the v-bits were set correctly
75 vbits_t actual = { .num_bits = opnd->vbits.num_bits };
76 rc = VALGRIND_GET_VBITS(&opnd->value, &actual.bits, num_bytes);
77 assert(rc == 1);
78
79 assert(equal_vbits(opnd->vbits, actual));
80}
81
82
83static void
84valgrind_get_vbits(opnd_t *opnd)
85{
86 unsigned rc, num_bytes;
87
88 /* 1-bit wide values cannot be stored. So we store them by writing a
89 single byte */
90 num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
91 opnd->vbits.num_bits = bitsof_irtype(opnd->type);
92 rc = VALGRIND_GET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
93 assert(rc == 1);
94}
95
96
97/* Insert a client request that will initialize VEX for IR injection */
98void
99valgrind_vex_init_for_iri(IRICB *cb)
100{
101 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__VEX_INIT_FOR_IRI, cb, 0,0,0,0);
102}
103
104
105/* Insert a special opcode that will cause VEX to inject an IR stmt based
106 on the information passed in the IRICB (in valgrind_vex_init_for_iri). */
107static void
108valgrind_vex_inject_ir(void)
109{
110 VALGRIND_VEX_INJECT_IR();
111}
112
113
114/* Execute the test under valgrind. Well, yes, we're not really executing
115 it here, just preparing for it... */
116void
117valgrind_execute_test(const irop_t *op, test_data_t *data)
118{
119 unsigned i, num_operands;
120
carll24c9e7f2012-11-16 19:41:21 +0000121 if (verbose > 2) printf("---------- Running a test\n");
florianbb913cd2012-08-28 16:50:39 +0000122 num_operands = get_num_operands(op->op);
123
124 for (i = 0; i < num_operands; ++i) {
125 valgrind_set_vbits(&data->opnds[i]);
carll24c9e7f2012-11-16 19:41:21 +0000126 if (verbose > 2) {
florianbb913cd2012-08-28 16:50:39 +0000127 printf("opnd #%u: ", i);
128 print_opnd(stdout, &data->opnds[i]);
129 printf("\n");
130 }
131 }
florian3a142cf2013-02-08 23:34:31 +0000132 if (verbose > 2)
133 if (data->rounding_mode != NO_ROUNDING_MODE)
134 printf("rounding mode %u\n", data->rounding_mode);
135
florianbb913cd2012-08-28 16:50:39 +0000136 valgrind_vex_inject_ir();
137 valgrind_get_vbits(&data->result);
carll24c9e7f2012-11-16 19:41:21 +0000138 if (verbose > 2) {
florianbb913cd2012-08-28 16:50:39 +0000139 printf("result: ");
140 print_opnd(stdout, &data->result);
141 printf("\n");
142 }
143}