| /* -*- mode: C; c-basic-offset: 3; -*- */ |
| |
| /* |
| This file is part of MemCheck, a heavyweight Valgrind tool for |
| detecting memory errors. |
| |
| Copyright (C) 2012-2017 Florian Krohm |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License as |
| published by the Free Software Foundation; either version 2 of the |
| License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program; if not, write to the Free Software |
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307, USA. |
| |
| The GNU General Public License is contained in the file COPYING. |
| */ |
| |
| #ifndef VTEST_H |
| #define VTEST_H |
| |
| /* Main header file for the V-bit tester */ |
| |
| #include <stdint.h> // uint64_t |
| #include "libvex.h" // IROp |
| #include "vbits.h" // vbits_t |
| |
| |
| /* How undefinedness propagates from input to output */ |
| |
| typedef enum { |
| // For any undefined input bit, all output bits are defined. |
| UNDEF_NONE, |
| |
| // For any undefined input bit, all output bits are undefined. |
| UNDEF_ALL, |
| |
| // For each undefined input bit, the corresponding output bit |
| // in the same position is undefined. No other bit is undefined. |
| UNDEF_SAME, |
| |
| // For each undefined input bit, the corresponding output bit |
| // in the same position is undefined. No other bit is undefined. |
| // If the corresponding output bit does not exist, the input bit |
| // does not cause any output bits to be undefined. |
| UNDEF_TRUNC, |
| |
| // For each undefined input bit, the corresponding output bit |
| // in the same position is undefined. No other bit is undefined. |
| // Output bits that do no not have a corresponding input bit are |
| // defined. |
| UNDEF_ZEXT, |
| |
| // For each undefined input bit, the corresponding output bit |
| // in the same position is undefined. If the MSB of the input value |
| // is undefined, so are all output bits with higher significance |
| // than the MSB input bit. |
| UNDEF_SEXT, |
| |
| // For each undefined input bit, the corresponding output bit |
| // and all output bits with higher significance are undefined. |
| UNDEF_LEFT, |
| |
| UNDEF_CONCAT, // nHLto2n ops e.g. Iop_32HLto64 |
| UNDEF_UPPER, // 2nHIton ops e.g. Iop_64HIto32 |
| UNDEF_SHL, // shift-left |
| UNDEF_SHR, // logical shift-right |
| UNDEF_SAR, // arithmetic shift-right |
| UNDEF_OR, // bitwise OR operation |
| UNDEF_AND, // bitwise AND operation |
| |
| UNDEF_ORD, // Iop_CmpORD compare |
| |
| /* For each of the following UNDEF_ALL_BxE, E is the number of |
| * elements and B is the number of bits in the element. |
| * |
| * If any bits in one of the E elements is not defined, then the |
| * return value has all bits in the corresponding element set to 1. |
| */ |
| UNDEF_ALL_64x2, // 128-bit vector, two 64-bit elements |
| UNDEF_ALL_32x4, // 128-bit vector, four 32-bit elements |
| UNDEF_ALL_16x8, // 128-bit vector, eight 16-bit elements |
| UNDEF_ALL_8x16, // 128-bit vector, sixteen 8-bit elements |
| |
| /* For each of the following UNDEF_ALL_BxE_EVEN, E is the number of |
| * elements and B is the number of bits in the element. Elements are |
| * numbered from right to left starting with element number 0. |
| * |
| * If any bits in one of the even numbered elements is not defined, then |
| * the return value has all bits in the corresponding element set to 1. |
| * The bits in the odd numbered elements are not checked |
| */ |
| UNDEF_ALL_32x4_EVEN, // 128-bit vector, four 32-bit elements |
| UNDEF_ALL_16x8_EVEN, // 128-bit vector, eight 16-bit elements |
| UNDEF_ALL_8x16_EVEN, // 128-bit vector, sixteen 8-bit elements |
| |
| /* For each of the following UNDEF_BxE_TRANSPOSE, E is the number of |
| * elements and B is the number of bits in the element. |
| * |
| * Concatenate bit i from each byte j. Place concatenated 8 bit value |
| * into byte i of the result. Do for each bit i from 0 to 7 and |
| * byte j from 0 to 7 of each 64-bit element. |
| */ |
| UNDEF_64x2_TRANSPOSE, |
| |
| /* For each of the following UNDEF_BxE_ROTATE, E is the number of |
| * elements and B is the number of bits in the element. |
| * |
| * The result is the undefined bits in each element rotated by the |
| * specified amount. Bits rotated out of the element are discarded. |
| * No additional bits are set to undefined. |
| */ |
| UNDEF_64x2_ROTATE, /* 128-bit vector, two 64-bit elements, rotate |
| * elements left. |
| */ |
| UNDEF_32x4_ROTATE, /* 128-bit vector, four 32-bit elements, rotate |
| * elements left. |
| */ |
| UNDEF_16x8_ROTATE, /* 128-bit vector, eight 16-bit elements, rotate |
| * elements left. |
| */ |
| UNDEF_8x16_ROTATE, /* 128-bit vector, sixteen 8-bit elements, rotate |
| * elements left. |
| */ |
| |
| /* If the input had some vbits set, the result will have one or more |
| * vbits set. Minimal test when the vbit propagation can not be easily |
| * calculated. |
| */ |
| UNDEF_SOME, |
| |
| /* For UNDEF_NARROW256_AtoB, narrow the elements of size A-bits in |
| * the 256-bit source (stored in two 128-bit values) to a 128-bit |
| * result with elements of size B-bits. |
| * |
| * If the source element will fit into the corresponding destination |
| * element, then only the undefined bits in the source element are |
| * undefined in the corresponding bit position of the destination element. |
| * |
| * If the source element will not fit into the destination element, then |
| * only the lower B undefined bits of the source element will be |
| * undefined in the corresponding result element unless the saturate |
| * flag is true. If the saturate flag is true and the element in the |
| * source will not fit into the corresponding destination element, then |
| * all of the bits in the corresponding destination element are set to one. |
| */ |
| UNDEF_NARROW256_AtoB, |
| |
| // For IROps I don't know anything about |
| UNDEF_UNKNOWN |
| } undef_t; |
| |
| |
| // Everything we want to know about an IROp |
| typedef struct { |
| IROp op; |
| const char *name; |
| undef_t undef_kind; |
| /* The following two members describe if this operand has immediate |
| * operands. There are a few restrictions: |
| * (1) An operator can have at most one immediate operand. |
| * (2) If there is an immediate operand, it is the right-most operand. |
| * An immediate_index of 0 means there is no immediate operand. |
| */ |
| unsigned immediate_index; |
| unsigned immediate_type; |
| |
| // Indicate whether IROp can be tested on a particular architecture |
| unsigned s390x : 1; |
| unsigned amd64 : 1; |
| unsigned ppc32 : 1; |
| unsigned ppc64 : 1; |
| unsigned arm : 1; |
| unsigned arm64 : 1; |
| unsigned x86 : 1; |
| unsigned mips32 : 1; |
| unsigned mips64 : 1; |
| } irop_t; |
| |
| |
| /* The maximum number of input operands */ |
| #define MAX_OPERANDS 4 |
| |
| /* An operand of an IROp (also used for the result) */ |
| typedef struct { |
| IRType type; |
| vbits_t vbits; |
| value_t value; |
| } opnd_t; |
| |
| |
| /* Carries the data needed to execute and evaluate a test. I.e. |
| inputs and results (V-bits and actual value). */ |
| typedef struct { |
| opnd_t result; |
| opnd_t opnds[MAX_OPERANDS]; |
| unsigned rounding_mode; |
| } test_data_t; |
| |
| |
| /* Function prototypes */ |
| irop_t *get_irop(IROp); |
| int is_floating_point_op_with_rounding_mode(IROp); |
| int get_num_operands(IROp); |
| |
| void print_opnd(FILE *, const opnd_t *); |
| |
| int test_unary_op(const irop_t *, test_data_t *); |
| int test_binary_op(const irop_t *, test_data_t *); |
| int test_ternary_op(const irop_t *, test_data_t *); |
| int test_qernary_op(const irop_t *, test_data_t *); |
| |
| void valgrind_vex_init_for_iri(IRICB *); |
| void valgrind_execute_test(const irop_t *, test_data_t *); |
| |
| IRICB new_iricb(const irop_t *, test_data_t *); |
| |
| void panic(const char *) __attribute__((noreturn)); |
| void complain(const irop_t *, const test_data_t *, vbits_t expected); |
| |
| /* Imported from VEX */ |
| unsigned sizeof_irtype(IRType); |
| void typeof_primop(IROp, IRType *t_dst, IRType *t_arg1, IRType *t_arg2, |
| IRType *t_arg3, IRType *t_arg4); |
| |
| static __inline__ unsigned bitsof_irtype(IRType type) |
| { |
| return type == Ity_I1 ? 1 : sizeof_irtype(type) * 8; |
| } |
| |
| |
| /* Exported variables */ |
| extern int verbose; |
| |
| #endif // VTEST_H |