1 /* -*- mode: C; c-basic-offset: 3; -*- */
4 This file is part of MemCheck, a heavyweight Valgrind tool for
5 detecting memory errors.
7 Copyright (C) 2012-2017 Florian Krohm
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.
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.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 The GNU General Public License is contained in the file COPYING.
26 #include "memcheck.h" // VALGRIND_SET_VBITS
30 /* Return a completely initialised control block */
32 new_iricb(const irop_t
*op
, test_data_t
*data
)
37 cb
.result
= (HWord
)&data
->result
.value
;
38 cb
.opnd1
= (HWord
)&data
->opnds
[0].value
;
39 cb
.opnd2
= (HWord
)&data
->opnds
[1].value
;
40 cb
.opnd3
= (HWord
)&data
->opnds
[2].value
;
41 cb
.opnd4
= (HWord
)&data
->opnds
[3].value
;
42 cb
.t_result
= data
->result
.type
;
43 cb
.t_opnd1
= data
->opnds
[0].type
;
44 cb
.t_opnd2
= data
->opnds
[1].type
;
45 cb
.t_opnd3
= data
->opnds
[2].type
;
46 cb
.t_opnd4
= data
->opnds
[3].type
;
48 cb
.rounding_mode
= data
->rounding_mode
;
50 cb
.num_operands
= get_num_operands(op
->op
);
52 cb
.immediate_index
= op
->immediate_index
;
53 cb
.immediate_type
= op
->immediate_type
;
59 /* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store
60 such a value from/to a 4-byte container. It uses 32to1 and 1Uto32,
63 valgrind_set_vbits(opnd_t
*opnd
)
65 unsigned rc
, num_bytes
;
67 /* 1-bit wide values cannot be read. So we read a 4 bytes here */
68 num_bytes
= opnd
->type
== Ity_I1
? 4 : sizeof_irtype(opnd
->type
);
69 rc
= VALGRIND_SET_VBITS(&opnd
->value
, &opnd
->vbits
.bits
, num_bytes
);
72 // Make sure the v-bits were set correctly
73 vbits_t actual
= { .num_bits
= opnd
->vbits
.num_bits
};
74 rc
= VALGRIND_GET_VBITS(&opnd
->value
, &actual
.bits
, num_bytes
);
77 assert(equal_vbits(opnd
->vbits
, actual
));
82 valgrind_get_vbits(opnd_t
*opnd
)
84 unsigned rc
, num_bytes
;
86 /* 1-bit wide values cannot be stored. So we store them by writing a
88 num_bytes
= opnd
->type
== Ity_I1
? 4 : sizeof_irtype(opnd
->type
);
89 opnd
->vbits
.num_bits
= bitsof_irtype(opnd
->type
);
90 rc
= VALGRIND_GET_VBITS(&opnd
->value
, &opnd
->vbits
.bits
, num_bytes
);
95 /* Insert a client request that will initialize VEX for IR injection */
97 valgrind_vex_init_for_iri(IRICB
*cb
)
99 VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__VEX_INIT_FOR_IRI
, cb
, 0,0,0,0);
103 /* Insert a special opcode that will cause VEX to inject an IR stmt based
104 on the information passed in the IRICB (in valgrind_vex_init_for_iri). */
106 valgrind_vex_inject_ir(void)
108 VALGRIND_VEX_INJECT_IR();
112 /* Execute the test under valgrind. Well, yes, we're not really executing
113 it here, just preparing for it... */
115 valgrind_execute_test(const irop_t
*op
, test_data_t
*data
)
117 unsigned i
, num_operands
;
119 if (verbose
> 2) printf("---------- Running a test\n");
120 num_operands
= get_num_operands(op
->op
);
122 for (i
= 0; i
< num_operands
; ++i
) {
123 valgrind_set_vbits(&data
->opnds
[i
]);
125 printf("opnd #%u: ", i
);
126 print_opnd(stdout
, &data
->opnds
[i
]);
131 if (data
->rounding_mode
!= NO_ROUNDING_MODE
)
132 printf("rounding mode %u\n", data
->rounding_mode
);
134 valgrind_vex_inject_ir();
135 valgrind_get_vbits(&data
->result
);
138 print_opnd(stdout
, &data
->result
);
142 // Now that we have the vbits recorded, clear all the vbits.
143 for (i
= 0; i
< num_operands
; ++i
) {
144 VALGRIND_MAKE_MEM_DEFINED(&data
->opnds
[i
].value
, sizeof(data
->opnds
[i
].value
));