Home | History | Annotate | Download | only in vbit-test
      1 /* -*- mode: C; c-basic-offset: 3; -*- */
      2 
      3 #include <assert.h>
      4 #include "memcheck.h"  // VALGRIND_SET_VBITS
      5 #include "vtest.h"
      6 
      7 
      8 /* Return a completely initialised control block */
      9 IRICB
     10 new_iricb(const irop_t *op, test_data_t *data)
     11 {
     12    IRICB cb;
     13 
     14    cb.op = op->op;
     15    cb.result = (HWord)&data->result.value;
     16    cb.opnd1  = (HWord)&data->opnds[0].value;
     17    cb.opnd2  = (HWord)&data->opnds[1].value;
     18    cb.opnd3  = (HWord)&data->opnds[2].value;
     19    cb.opnd4  = (HWord)&data->opnds[3].value;
     20    cb.t_result = data->result.type;
     21    cb.t_opnd1  = data->opnds[0].type;
     22    cb.t_opnd2  = data->opnds[1].type;
     23    cb.t_opnd3  = data->opnds[2].type;
     24    cb.t_opnd4  = data->opnds[3].type;
     25 
     26    cb.rounding_mode = data->rounding_mode;
     27 
     28    cb.num_operands = get_num_operands(op->op);
     29 
     30    cb.shift_amount_is_immediate = op->shift_amount_is_immediate;
     31 
     32    return cb;
     33 }
     34 
     35 
     36 /* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store
     37    such a value from/to a 4-byte container. It uses 32to1 and 1Uto32,
     38    respectively. */
     39 static void
     40 valgrind_set_vbits(opnd_t *opnd)
     41 {
     42    unsigned rc, num_bytes;
     43 
     44    /* 1-bit wide values cannot be read. So we read a 4 bytes here */
     45    num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
     46    rc = VALGRIND_SET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
     47    assert(rc == 1);
     48 
     49    // Make sure the v-bits were set correctly
     50    vbits_t actual = { .num_bits = opnd->vbits.num_bits };
     51    rc = VALGRIND_GET_VBITS(&opnd->value, &actual.bits, num_bytes);
     52    assert(rc == 1);
     53 
     54    assert(equal_vbits(opnd->vbits, actual));
     55 }
     56 
     57 
     58 static void
     59 valgrind_get_vbits(opnd_t *opnd)
     60 {
     61    unsigned rc, num_bytes;
     62 
     63    /* 1-bit wide values cannot be stored. So we store them by writing a
     64       single byte */
     65    num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type);
     66    opnd->vbits.num_bits = bitsof_irtype(opnd->type);
     67    rc = VALGRIND_GET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes);
     68    assert(rc == 1);
     69 }
     70 
     71 
     72 /* Insert a client request that will initialize VEX for IR injection */
     73 void
     74 valgrind_vex_init_for_iri(IRICB *cb)
     75 {
     76    VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__VEX_INIT_FOR_IRI, cb, 0,0,0,0);
     77 }
     78 
     79 
     80 /* Insert a special opcode that will cause VEX to inject an IR stmt based
     81    on the information passed in the IRICB (in valgrind_vex_init_for_iri). */
     82 static void
     83 valgrind_vex_inject_ir(void)
     84 {
     85    VALGRIND_VEX_INJECT_IR();
     86 }
     87 
     88 
     89 /* Execute the test under valgrind. Well, yes, we're not really executing
     90    it here, just preparing for it... */
     91 void
     92 valgrind_execute_test(const irop_t *op, test_data_t *data)
     93 {
     94    unsigned i, num_operands;
     95 
     96    if (verbose > 2) printf("---------- Running a test\n");
     97    num_operands = get_num_operands(op->op);
     98 
     99    for (i = 0; i < num_operands; ++i) {
    100       valgrind_set_vbits(&data->opnds[i]);
    101       if (verbose > 2) {
    102          printf("opnd #%u:  ", i);
    103          print_opnd(stdout, &data->opnds[i]);
    104          printf("\n");
    105       }
    106    }
    107    if (verbose > 2)
    108       if (data->rounding_mode != NO_ROUNDING_MODE)
    109          printf("rounding mode %u\n", data->rounding_mode);
    110 
    111    valgrind_vex_inject_ir();
    112    valgrind_get_vbits(&data->result);
    113    if (verbose > 2) {
    114       printf("result:   ");
    115       print_opnd(stdout, &data->result);
    116       printf("\n");
    117    }
    118 }
    119