/* -*- mode: C; c-basic-offset: 3; -*- */ /*--------------------------------------------------------------------*/ /*--- MemCheck: some non-generic asm implementations of mc_main.c */ /*--- functions ---*/ /*--- mc_main_asm.c ---*/ /*--------------------------------------------------------------------*/ /* This file is part of MemCheck, a heavyweight Valgrind tool for detecting memory errors. Copyright (C) 2000-2018 Julian Seward jseward@acm.org 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, see . The GNU General Public License is contained in the file COPYING. */ /* Having these in mc_main.c gives undefined references at link time, when compiling with lto. Having them in a separate file solves this. Also, for some toolchain, we might maybe need to disable lto. */ // A bunch of include only needed for mc_include.h #include "pub_tool_basics.h" #include "pub_tool_poolalloc.h" #include "pub_tool_hashtable.h" #include "pub_tool_tooliface.h" #include "mc_include.h" // Non-generic assembly for arm32-linux #if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ && defined(VGP_arm_linux) __asm__( /* Derived from the 32 bit assembly helper */ ".text \n" ".align 2 \n" ".global vgMemCheck_helperc_LOADV64le \n" ".type vgMemCheck_helperc_LOADV64le, %function \n" "vgMemCheck_helperc_LOADV64le: \n" " tst r0, #7 \n" " movw r3, #:lower16:primary_map \n" " bne .LLV64LEc4 \n" // if misaligned " lsr r2, r0, #16 \n" " movt r3, #:upper16:primary_map \n" " ldr r2, [r3, r2, lsl #2] \n" " uxth r1, r0 \n" // r1 is 0-(16)-0 X-(13)-X 000 " movw r3, #0xAAAA \n" " lsr r1, r1, #2 \n" // r1 is 0-(16)-0 00 X-(13)-X 0 " ldrh r1, [r2, r1] \n" " cmp r1, r3 \n" // 0xAAAA == VA_BITS16_DEFINED " bne .LLV64LEc0 \n" // if !all_defined " mov r1, #0x0 \n" // 0x0 == V_BITS32_DEFINED " mov r0, #0x0 \n" // 0x0 == V_BITS32_DEFINED " bx lr \n" ".LLV64LEc0: \n" " movw r3, #0x5555 \n" " cmp r1, r3 \n" // 0x5555 == VA_BITS16_UNDEFINED " bne .LLV64LEc4 \n" // if !all_undefined " mov r1, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED " mov r0, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED " bx lr \n" ".LLV64LEc4: \n" " push {r4, lr} \n" " mov r2, #0 \n" " mov r1, #64 \n" " bl mc_LOADVn_slow \n" " pop {r4, pc} \n" ".size vgMemCheck_helperc_LOADV64le, .-vgMemCheck_helperc_LOADV64le \n" ".previous\n" ); #elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ && (defined(VGP_x86_linux) || defined(VGP_x86_solaris)) __asm__( ".text\n" ".align 16\n" ".global vgMemCheck_helperc_LOADV64le\n" ".type vgMemCheck_helperc_LOADV64le, @function\n" "vgMemCheck_helperc_LOADV64le:\n" " test $0x7, %eax\n" " jne .LLV64LE2\n" /* jump if not aligned */ " mov %eax, %ecx\n" " movzwl %ax, %edx\n" " shr $0x10, %ecx\n" " mov primary_map(,%ecx,4), %ecx\n" " shr $0x3, %edx\n" " movzwl (%ecx,%edx,2), %edx\n" " cmp $0xaaaa, %edx\n" " jne .LLV64LE1\n" /* jump if not all defined */ " xor %eax, %eax\n" /* return 0 in edx:eax */ " xor %edx, %edx\n" " ret\n" ".LLV64LE1:\n" " cmp $0x5555, %edx\n" " jne .LLV64LE2\n" /* jump if not all undefined */ " or $0xffffffff, %eax\n" /* else return all bits set in edx:eax */ " or $0xffffffff, %edx\n" " ret\n" ".LLV64LE2:\n" " xor %ecx, %ecx\n" /* tail call to mc_LOADVn_slow(a, 64, 0) */ " mov $64, %edx\n" " jmp mc_LOADVn_slow\n" ".size vgMemCheck_helperc_LOADV64le, .-vgMemCheck_helperc_LOADV64le\n" ".previous\n" ); #else // Generic for all platforms except {arm32,x86}-linux and x86-solaris // is in mc_main.c #endif // Non-generic assembly for arm32-linux #if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ && defined(VGP_arm_linux) __asm__( /* Derived from NCode template */ ".text \n" ".align 2 \n" ".global vgMemCheck_helperc_LOADV32le \n" ".type vgMemCheck_helperc_LOADV32le, %function \n" "vgMemCheck_helperc_LOADV32le: \n" " tst r0, #3 \n" // 1 " movw r3, #:lower16:primary_map \n" // 1 " bne .LLV32LEc4 \n" // 2 if misaligned " lsr r2, r0, #16 \n" // 3 " movt r3, #:upper16:primary_map \n" // 3 " ldr r2, [r3, r2, lsl #2] \n" // 4 " uxth r1, r0 \n" // 4 " ldrb r1, [r2, r1, lsr #2] \n" // 5 " cmp r1, #0xAA \n" // 6 0xAA == VA_BITS8_DEFINED " bne .LLV32LEc0 \n" // 7 if !all_defined " mov r0, #0x0 \n" // 8 0x0 == V_BITS32_DEFINED " bx lr \n" // 9 ".LLV32LEc0: \n" " cmp r1, #0x55 \n" // 0x55 == VA_BITS8_UNDEFINED " bne .LLV32LEc4 \n" // if !all_undefined " mov r0, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED " bx lr \n" ".LLV32LEc4: \n" " push {r4, lr} \n" " mov r2, #0 \n" " mov r1, #32 \n" " bl mc_LOADVn_slow \n" " pop {r4, pc} \n" ".size vgMemCheck_helperc_LOADV32le, .-vgMemCheck_helperc_LOADV32le \n" ".previous\n" ); #elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ && (defined(VGP_x86_linux) || defined(VGP_x86_solaris)) __asm__( ".text\n" ".align 16\n" ".global vgMemCheck_helperc_LOADV32le\n" ".type vgMemCheck_helperc_LOADV32le, @function\n" "vgMemCheck_helperc_LOADV32le:\n" " test $0x3, %eax\n" " jnz .LLV32LE2\n" /* jump if misaligned */ " mov %eax, %edx\n" " shr $16, %edx\n" " mov primary_map(,%edx,4), %ecx\n" " movzwl %ax, %edx\n" " shr $2, %edx\n" " movzbl (%ecx,%edx,1), %edx\n" " cmp $0xaa, %edx\n" /* compare to VA_BITS8_DEFINED */ " jne .LLV32LE1\n" /* jump if not completely defined */ " xor %eax, %eax\n" /* else return V_BITS32_DEFINED */ " ret\n" ".LLV32LE1:\n" " cmp $0x55, %edx\n" /* compare to VA_BITS8_UNDEFINED */ " jne .LLV32LE2\n" /* jump if not completely undefined */ " or $0xffffffff, %eax\n" /* else return V_BITS32_UNDEFINED */ " ret\n" ".LLV32LE2:\n" " xor %ecx, %ecx\n" /* tail call mc_LOADVn_slow(a, 32, 0) */ " mov $32, %edx\n" " jmp mc_LOADVn_slow\n" ".size vgMemCheck_helperc_LOADV32le, .-vgMemCheck_helperc_LOADV32le\n" ".previous\n" ); #else // Generic for all platforms except {arm32,x86}-linux and x86-solaris // is in mc_main.c #endif /*--------------------------------------------------------------------*/ /*--- end ---*/ /*--------------------------------------------------------------------*/