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.
25 #include <assert.h> // assert
26 #include <stdio.h> // printf
27 #include <stdlib.h> // malloc
28 #include <string.h> // memset
29 #include "valgrind.h" // RUNNING_ON_VALGRIND
34 new_test_data(const irop_t
*op
)
36 test_data_t
*data
= malloc(sizeof *data
);
38 memset(data
, 0x0, sizeof *data
); // initialise
40 /* Obtain the operand types and set them */
41 IRType t_dst
, t1
, t2
, t3
, t4
;
43 typeof_primop(op
->op
, &t_dst
, &t1
, &t2
, &t3
, &t4
);
44 assert(t_dst
!= Ity_INVALID
);
45 assert(t1
!= Ity_INVALID
);
47 data
->result
.type
= t_dst
;
48 if (is_floating_point_op_with_rounding_mode(op
->op
)) {
49 data
->opnds
[0].type
= t2
;
50 data
->opnds
[1].type
= t3
;
51 data
->opnds
[2].type
= t4
;
52 data
->opnds
[3].type
= Ity_INVALID
;
54 data
->opnds
[0].type
= t1
;
55 data
->opnds
[1].type
= t2
;
56 data
->opnds
[2].type
= t3
;
57 data
->opnds
[3].type
= t4
;
60 /* Set the rounding mode if the operation requires one.
61 FIXME: We should iterate over all rounding modes. For that need
62 FIXME: to distinguish between binary and decimal floating point */
63 if (is_floating_point_op_with_rounding_mode(op
->op
)) {
64 // for now just pick one
65 data
->rounding_mode
= Irrm_NEAREST
; // same as Irrm_DFP_NEAREST
67 data
->rounding_mode
= NO_ROUNDING_MODE
;
76 /* Certain IROps require special handling. */
83 /* Iops with immediate shift value */
84 tmp
= get_irop(Iop_ShlD64
);
86 tmp
->immediate_index
= 2;
87 tmp
->immediate_type
= Ity_I8
;
90 tmp
= get_irop(Iop_ShrD64
);
92 tmp
->immediate_index
= 2;
93 tmp
->immediate_type
= Ity_I8
;
96 tmp
= get_irop(Iop_ShlD128
);
98 tmp
->immediate_index
= 2;
99 tmp
->immediate_type
= Ity_I8
;
102 tmp
= get_irop(Iop_ShrD128
);
104 tmp
->immediate_index
= 2;
105 tmp
->immediate_type
= Ity_I8
;
108 /* Iops with immediate value that controls PPC instruction behavior */
109 tmp
= get_irop(Iop_SHA256
);
111 tmp
->immediate_index
= 2;
112 tmp
->immediate_type
= Ity_I8
;
115 tmp
= get_irop(Iop_SHA512
);
117 tmp
->immediate_index
= 2;
118 tmp
->immediate_type
= Ity_I8
;
125 main(int argc
, char *argv
[])
127 assert(sizeof(long long) == 8);
128 int num_unary_tests
= 0, num_binary_tests
= 0;
129 int num_ternary_tests
= 0, num_qernary_tests
= 0;
131 for (int i
= 1; i
< argc
; ++i
) {
132 if (strcmp(argv
[i
], "-v") == 0) ++verbose
;
133 else if (strcmp(argv
[i
], "--help") == 0) {
134 printf("\nvbit-test [ -v | --help ]\n");
135 printf("\n\t-v verbose mode; show number of tests\n");
136 printf("\n\t-v -v verbose mode; shows IROps being tested\n");
137 printf("\n\t-v -v -v verbose mode, extreme edition\n\n");
140 printf("%s ? Nothing happens.\n", argv
[i
]);
145 if (! RUNNING_ON_VALGRIND
) {
146 fprintf(stderr
, "*** This program needs to run under memcheck.\n");
150 setbuf(stdout
, NULL
); // make stdout unbuffered
152 fixup_irops(); // determine need for special handling
154 // Iterate over all primops
155 IROp first
= Iop_INVALID
+ 1;
156 IROp last
= Iop_LAST
;
159 if (0) { // overwrite for debugging
160 first
= Iop_CasCmpEQ8
; last
= first
+ 1;
163 // Iterate over all IROps in the enum type. That is the only way to
164 // make sure the operator is tested on at least one platform.
166 // Loop assumes no holes in the enumerator values
167 for (opkind
= first
; opkind
< last
; ++opkind
) {
169 const irop_t
*op
= get_irop(opkind
);
170 if (op
== NULL
) continue;
172 if (op
->undef_kind
== UNDEF_UNKNOWN
) {
173 fprintf(stderr
, "...skipping %s; unknown undef propagation\n",
178 test_data_t
*data
= new_test_data(op
);
180 if (verbose
> 1) printf("Testing operator %s\n", op
->name
);
182 IRICB iricb
= new_iricb(op
, data
);
184 valgrind_vex_init_for_iri(&iricb
);
186 switch (iricb
.num_operands
) {
188 num_unary_tests
+= test_unary_op(op
, data
);
192 num_binary_tests
+= test_binary_op(op
, data
);
196 num_ternary_tests
+= test_ternary_op(op
, data
);
200 num_qernary_tests
+= test_qernary_op(op
, data
);
204 panic("operator not handled");
211 printf("\nvbit-test ran %d unary, %d binary, %d ternary and"
212 " %d qernary tests.\n\n",
213 num_unary_tests
, num_binary_tests
, num_ternary_tests
,