⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jm-insns.c

📁 The Valgrind distribution has multiple tools. The most popular is the memory checking tool (called M
💻 C
📖 第 1 页 / 共 5 页
字号:
/* HOW TO COMPILE:* 32bit build:   gcc -Winline -Wall -g -O -mregnames -DHAS_ALTIVEC -maltivec* 64bit build:   gcc -Winline -Wall -g -O -mregnames -DHAS_ALTIVEC -maltivec -m64This program is useful, but the register usage conventions init are a complete dog.  In particular, _patch_op_imm has tobe inlined, else you wind up with it segfaulting incompletely different places due to corruption (of r20 in thecase I chased).*//* * test-ppc.c: * PPC tests for qemu-PPC CPU emulation checks *  * Copyright (c) 2005 Jocelyn Mayer *  *   This program is free software; you can redistribute it and/or *   modify it under the terms of the GNU General Public License V2 *   as published by the Free Software Foundation * *   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 *//* * Theory of operations: * a few registers are reserved for the test program: * r14 => r18 * f14 => f18 * I do preload test values in r14 thru r17 (or less, depending on the number * of register operands needed), patch the test opcode if any immediate * operands are required, execute the tested opcode. * XER, CCR and FPSCR are cleared before every test. * I always get the result in r17 and also save XER and CCR for fixed-point * operations. I also check FPSCR for floating points operations. * * Improvments: * a more clever FPSCR management is needed: for now, I always test * the round-to-zero case. Other rounding modes also need to be tested. *//* * Operation details * ----------------- * The 'test' functions (via all_tests[]) are wrappers of single asm instns * * The 'loops' (e.g. int_loops) do the actual work: *  - loops over as many arguments as the instn needs (regs | imms) *     - sets up the environment (reset cr,xer, assign src regs...) *     - maybe modifies the asm instn to test different imm args *     - calls the test function *     - retrieves relevant register data (rD,cr,xer,...) *     - prints argument and result data. * * More specifically... * * all_tests[i] holds insn tests *  - of which each holds: {instn_test_arr[], description, flags} * * flags hold 3 instn classifiers: {family, type, arg_type} * * // The main test loop: * do_tests( user_ctl_flags ) { *    foreach(curr_test = all_test[i]) { * *       // flags are used to control what tests are run: *       if (curr_test->flags && !user_ctl_flags) *          continue; * *       // a 'loop_family_arr' is chosen based on the 'family' flag... *       switch(curr_test->flags->family) { *       case x: loop_family_arr = int_loops; *      ... *       } * *       // ...and the actual test_loop to run is found by indexing into *       // the loop_family_arr with the 'arg_type' flag: *       test_loop = loop_family[curr_test->flags->arg_type] * *       // finally, loop over all instn tests for this test: *       foreach (instn_test = curr_test->instn_test_arr[i]) { * *          // and call the test_loop with the current instn_test function,name *          test_loop( instn_test->func, instn_test->name ) *       } *    } * } * * * Details of intruction patching for immediate operands * ----------------------------------------------------- * All the immediate insn test functions are of the form {imm_insn, blr} * In order to patch one of these functions, we simply copy both insns * to a stack buffer, and rewrite the immediate part of imm_insn. * We then execute our stack buffer. * All ppc instructions are 32bits wide, which makes this fairly easy. * * Example: * extern void test_addi (void); * asm(".section \".text\"\n" *     "    .align 2\n" *     "    .type test_addi,@function\n" *     "test_addi:\n" *     "    addi\n" *     "    blr\n" *     "    .previous\n" *     ); * * We are interested only in: *      "    addi         17, 14, 0\n" *      "    blr\n" * * In a loop test, we may see: * uint32_t func_buf[2];               // our new stack based 'function' * for imm...                          // loop over imm *   init_function( &func, func_buf );   // copy insns, set func ptr *   patch_op_imm16(&func_buf[0], imm);  // patch 'addi' insn *   ... *   (*func)();                              // exec our rewritten code * * patch_op_imm16() itself simply takes the uint32_t insn and overwrites * the immediate field with the new value (which, for 'addi', is the * low 16 bits). * * So in the loop test, if 'imm' is currently 9, and p[0] is: *   0x3A2E0000   => addi 17, 14, 0 * * after patch_op_imm16(), func_buf[0] becomes: *   0x3A2E0009   => addi 17, 14, 9 * * Note: init_function() needs to be called on every iteration *  - don't ask me why!*//**********************************************************************//* Uncomment to enable many arguments for altivec insns */#define USAGE_SIMPLE/* Uncomment to enable many arguments for altivec insns *///#define ALTIVEC_ARGS_LARGE/* Uncomment to enable output of CR flags for float tests *///#define TEST_FLOAT_FLAGS/* Uncomment to enable debug output *///#define DEBUG_ARGS_BUILD//#define DEBUG_FILTER/* These should be set at build time *///#define NO_FLOAT//#define HAS_ALTIVEC  // CFLAGS += -maltivec//#define IS_PPC405/**********************************************************************/#include <stdint.h>#include <sys/mman.h>/* Something of the same size as void*, so can be safely be coerced   to/from a pointer type. Also same size as the host's gp registers. */#ifndef __powerpc64__typedef uint32_t  HWord_t;#elsetypedef uint64_t  HWord_t;#endif // #ifndef __powerpc64__register double f14 __asm__ ("f14");register double f15 __asm__ ("f15");register double f16 __asm__ ("f16");register double f17 __asm__ ("f17");register double f18 __asm__ ("f18");register HWord_t r14 __asm__ ("r14");register HWord_t r15 __asm__ ("r15");register HWord_t r16 __asm__ ("r16");register HWord_t r17 __asm__ ("r17");register HWord_t r18 __asm__ ("r18");#if defined (HAS_ALTIVEC)#   include <altivec.h>#endif#include <assert.h>#include <ctype.h>     // isspace//#include <fcntl.h>//#include <fenv.h>//#include <math.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>    // getopt#include <malloc.h>#ifndef __powerpc64__#define ASSEMBLY_FUNC(__fname, __insn)     \asm(".section \".text\"\n"                 \    "\t.align 2\n"                         \    "\t.type "__fname",@function\n"        \    __fname":\n"                           \    "\t"__insn"\n"                         \    "\tblr\n"                              \    "\t.previous\n"                        \    )#else#define ASSEMBLY_FUNC(__fname, __insn)     \asm(".section  \".text\"\n"                \    "\t.align 2\n"                         \    "\t.global "__fname"\n"                \    "\t.section \".opd\",\"aw\"\n"         \    "\t.align 3\n"                         \    ""__fname":\n"                         \    "\t.quad ."__fname",.TOC.@tocbase,0\n" \    "\t.previous\n"                        \    "\t.type ."__fname",@function\n"       \    "\t.global  ."__fname"\n"              \    "."__fname":\n"                        \    "\t"__insn"\n"                         \    "\tblr\n"                              \    )#endif // #ifndef __powerpc64__/* Return a pointer to a 1-page area where is is safe to both write   and execute instructions.  Area is filled with 'trap' insns. */staticuint32_t* get_rwx_area ( void ){   int i;   static uint32_t* p = NULL;   if (p == NULL) {      p = mmap(NULL, 4096, PROT_READ|PROT_WRITE|PROT_EXEC,                           MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);      assert(p != MAP_FAILED);   }   for (i = 0; i < 4096/sizeof(uint32_t); i++)      p[i] = 0x7fe00008; /* trap */   return p;}/* -------------- BEGIN #include "test-ppc.h" -------------- *//* * test-ppc.h: * PPC tests for qemu-PPC CPU emulation checks - definitions *  * Copyright (c) 2005 Jocelyn Mayer *  *   This program is free software; you can redistribute it and/or *   modify it under the terms of the GNU General Public License V2 *   as published by the Free Software Foundation * *   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 */#if !defined (__TEST_PPC_H__)#define __TEST_PPC_H__#include <stdint.h>typedef void (*test_func_t) (void);typedef struct test_t test_t;typedef struct test_table_t test_table_t;struct test_t {    test_func_t func;    const char *name;};struct test_table_t {    test_t *tests;    const char *name;    uint32_t flags;};typedef void (*test_loop_t) (const char *name, test_func_t func,                             uint32_t flags);enum test_flags {    /* Nb arguments */    PPC_ONE_ARG    = 0x00000001,    PPC_TWO_ARGS   = 0x00000002,    PPC_THREE_ARGS = 0x00000003,    PPC_CMP_ARGS   = 0x00000004,  // family: compare    PPC_CMPI_ARGS  = 0x00000005,  // family: compare    PPC_TWO_I16    = 0x00000006,  // family: arith/logical    PPC_SPECIAL    = 0x00000007,  // family: logical    PPC_LD_ARGS    = 0x00000008,  // family: ldst    PPC_LDX_ARGS   = 0x00000009,  // family: ldst    PPC_ST_ARGS    = 0x0000000A,  // family: ldst    PPC_STX_ARGS   = 0x0000000B,  // family: ldst    PPC_NB_ARGS    = 0x0000000F,    /* Type */    PPC_ARITH      = 0x00000100,    PPC_LOGICAL    = 0x00000200,    PPC_COMPARE    = 0x00000300,    PPC_CROP       = 0x00000400,    PPC_LDST       = 0x00000500,    PPC_TYPE       = 0x00000F00,    /* Family */    PPC_INTEGER    = 0x00010000,    PPC_FLOAT      = 0x00020000,    PPC_405        = 0x00030000,    PPC_ALTIVEC    = 0x00040000,    PPC_FALTIVEC   = 0x00050000,    PPC_FAMILY     = 0x000F0000,    /* Flags: these may be combined, so use separate bitfields. */    PPC_CR         = 0x01000000,    PPC_XER_CA     = 0x02000000,};#endif /* !defined (__TEST_PPC_H__) *//* -------------- END #include "test-ppc.h" -------------- */#if defined (DEBUG_ARGS_BUILD)#define AB_DPRINTF(fmt, args...) do { fprintf(stderr, fmt , ##args); } while (0)#else#define AB_DPRINTF(fmt, args...) do { } while (0)#endif#if defined (DEBUG_FILTER)#define FDPRINTF(fmt, args...) do { fprintf(stderr, fmt , ##args); } while (0)#else#define FDPRINTF(fmt, args...) do { } while (0)#endif/* Produce the 64-bit pattern corresponding to the supplied double. */static uint64_t double_to_bits ( double d ){   union { uint64_t i; double d; } u;   assert(8 == sizeof(uint64_t));   assert(8 == sizeof(double));   assert(8 == sizeof(u));   u.d = d;   return u.i;}#if 0static float bits_to_float ( uint32_t i ){   union { uint32_t i; float f; } u;   assert(4 == sizeof(uint32_t));   assert(4 == sizeof(float));   assert(4 == sizeof(u));   u.i = i;   return u.f;}#endif#if defined (HAS_ALTIVEC)static void AB_DPRINTF_VEC32x4 ( vector unsigned int v ){#if defined (DEBUG_ARGS_BUILD)   int i;   unsigned int* p_int = (unsigned int*)&v;   AB_DPRINTF("val");   for (i=0; i<4; i++) {      AB_DPRINTF(" %08x", p_int[i]);   }   AB_DPRINTF("\n");#endif}#endif#define unused __attribute__ (( unused ))/* -------------- BEGIN #include "ops-ppc.c" -------------- *//* #include "test-ppc.h" */static void test_add (void){    __asm__ __volatile__ ("add          17, 14, 15");}static void test_addo (void){    __asm__ __volatile__ ("addo         17, 14, 15");}static void test_addc (void){    __asm__ __volatile__ ("addc         17, 14, 15");}static void test_addco (void){    __asm__ __volatile__ ("addco        17, 14, 15");}static void test_divw (void){    __asm__ __volatile__ ("divw         17, 14, 15");}static void test_divwo (void){    __asm__ __volatile__ ("divwo        17, 14, 15");}static void test_divwu (void){    __asm__ __volatile__ ("divwu        17, 14, 15");}static void test_divwuo (void){    __asm__ __volatile__ ("divwuo       17, 14, 15");}static void test_mulhw (void){    __asm__ __volatile__ ("mulhw        17, 14, 15");}static void test_mulhwu (void){    __asm__ __volatile__ ("mulhwu       17, 14, 15");}static void test_mullw (void){    __asm__ __volatile__ ("mullw        17, 14, 15");}static void test_mullwo (void){    __asm__ __volatile__ ("mullwo       17, 14, 15");}static void test_subf (void){    __asm__ __volatile__ ("subf         17, 14, 15");}static void test_subfo (void){    __asm__ __volatile__ ("subfo        17, 14, 15");}static void test_subfc (void){    __asm__ __volatile__ ("subfc        17, 14, 15");}static void test_subfco (void){    __asm__ __volatile__ ("subfco       17, 14, 15");}#ifdef __powerpc64__static void test_mulld (void){    __asm__ __volatile__ ("mulld        17, 14, 15");}static void test_mulhd (void){    __asm__ __volatile__ ("mulhd        17, 14, 15");}static void test_mulhdu (void){    __asm__ __volatile__ ("mulhdu       17, 14, 15");}static void test_divd (void){    __asm__ __volatile__ ("divd         17, 14, 15");}static void test_divdu (void){    __asm__ __volatile__ ("divdu        17, 14, 15");}#endif // #ifdef __powerpc64__static test_t tests_ia_ops_two[] = {    { &test_add             , "         add", },    { &test_addo            , "        addo", },    { &test_addc            , "        addc", },    { &test_addco           , "       addco", },    { &test_divw            , "        divw", },    { &test_divwo           , "       divwo", },    { &test_divwu           , "       divwu", },    { &test_divwuo          , "      divwuo", },    { &test_mulhw           , "       mulhw", },    { &test_mulhwu          , "      mulhwu", },

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -