1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* -*- mode: C; c-basic-offset: 3; -*- */
2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include <assert.h>
4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "memcheck.h"  // VALGRIND_SET_VBITS
5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "vtest.h"
6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Return a completely initialised control block */
9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovIRICB
10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovnew_iricb(const irop_t *op, test_data_t *data)
11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   IRICB cb;
13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.op = op->op;
15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.result = (HWord)&data->result.value;
16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.opnd1  = (HWord)&data->opnds[0].value;
17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.opnd2  = (HWord)&data->opnds[1].value;
18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.opnd3  = (HWord)&data->opnds[2].value;
19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.opnd4  = (HWord)&data->opnds[3].value;
20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.t_result = data->result.type;
21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.t_opnd1  = data->opnds[0].type;
22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.t_opnd2  = data->opnds[1].type;
23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.t_opnd3  = data->opnds[2].type;
24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.t_opnd4  = data->opnds[3].type;
25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.rounding_mode = data->rounding_mode;
27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.num_operands = get_num_operands(op->op);
29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   cb.shift_amount_is_immediate = op->shift_amount_is_immediate;
31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   return cb;
33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store
37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   such a value from/to a 4-byte container. It uses 32to1 and 1Uto32,
38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   respectively. */
39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void
40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvalgrind_set_vbits(opnd_t *opnd)
41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   unsigned rc, num_bytes;
43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* 1-bit wide values cannot be read. So we read a 4 bytes here */
45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   rc = VALGRIND_SET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   assert(rc == 1);
48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   // Make sure the v-bits were set correctly
50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   vbits_t actual = { .num_bits = opnd->vbits.num_bits };
51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   rc = VALGRIND_GET_VBITS(&opnd->value, &actual.bits, num_bytes);
52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   assert(rc == 1);
53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   assert(equal_vbits(opnd->vbits, actual));
55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void
59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvalgrind_get_vbits(opnd_t *opnd)
60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   unsigned rc, num_bytes;
62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   /* 1-bit wide values cannot be stored. So we store them by writing a
64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      single byte */
65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   opnd->vbits.num_bits = bitsof_irtype(opnd->type);
67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   rc = VALGRIND_GET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   assert(rc == 1);
69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Insert a client request that will initialize VEX for IR injection */
73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid
74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvalgrind_vex_init_for_iri(IRICB *cb)
75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__VEX_INIT_FOR_IRI, cb, 0,0,0,0);
77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Insert a special opcode that will cause VEX to inject an IR stmt based
81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   on the information passed in the IRICB (in valgrind_vex_init_for_iri). */
82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void
83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvalgrind_vex_inject_ir(void)
84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   VALGRIND_VEX_INJECT_IR();
86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/* Execute the test under valgrind. Well, yes, we're not really executing
90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   it here, just preparing for it... */
91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid
92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvalgrind_execute_test(const irop_t *op, test_data_t *data)
93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov{
94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   unsigned i, num_operands;
95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (verbose > 2) printf("---------- Running a test\n");
97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   num_operands = get_num_operands(op->op);
98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   for (i = 0; i < num_operands; ++i) {
100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      valgrind_set_vbits(&data->opnds[i]);
101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (verbose > 2) {
102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         printf("opnd #%u:  ", i);
103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         print_opnd(stdout, &data->opnds[i]);
104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         printf("\n");
105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      }
106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (verbose > 2)
108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      if (data->rounding_mode != NO_ROUNDING_MODE)
109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov         printf("rounding mode %u\n", data->rounding_mode);
110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov
111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   valgrind_vex_inject_ir();
112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   valgrind_get_vbits(&data->result);
113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   if (verbose > 2) {
114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      printf("result:   ");
115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      print_opnd(stdout, &data->result);
116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov      printf("\n");
117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov   }
118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov}
119