1 /* -*- mode: C; c-basic-offset: 3; -*- */ 2 3 /*--------------------------------------------------------------------*/ 4 /*--- MemCheck: some non-generic asm implementations of mc_main.c */ 5 /*--- functions ---*/ 6 /*--- mc_main_asm.c ---*/ 7 /*--------------------------------------------------------------------*/ 8 9 /* 10 This file is part of MemCheck, a heavyweight Valgrind tool for 11 detecting memory errors. 12 13 Copyright (C) 2000-2018 Julian Seward 14 jseward@acm.org 15 16 This program is free software; you can redistribute it and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of the 19 License, or (at your option) any later version. 20 21 This program is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received a copy of the GNU General Public License 27 along with this program; if not, write to the Free Software 28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29 02111-1307, USA. 30 31 The GNU General Public License is contained in the file COPYING. 32 */ 33 34 /* Having these in mc_main.c gives undefined references at link time, 35 when compiling with lto. Having them in a separate file solves this. 36 Also, for some toolchain, we might maybe need to disable lto. */ 37 38 // A bunch of include only needed for mc_include.h 39 #include "pub_tool_basics.h" 40 #include "pub_tool_poolalloc.h" 41 #include "pub_tool_hashtable.h" 42 #include "pub_tool_tooliface.h" 43 44 #include "mc_include.h" 45 46 // Non-generic assembly for arm32-linux 47 #if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ 48 && defined(VGP_arm_linux) 49 __asm__( /* Derived from the 32 bit assembly helper */ 50 ".text \n" 51 ".align 2 \n" 52 ".global vgMemCheck_helperc_LOADV64le \n" 53 ".type vgMemCheck_helperc_LOADV64le, %function \n" 54 "vgMemCheck_helperc_LOADV64le: \n" 55 " tst r0, #7 \n" 56 " movw r3, #:lower16:primary_map \n" 57 " bne .LLV64LEc4 \n" // if misaligned 58 " lsr r2, r0, #16 \n" 59 " movt r3, #:upper16:primary_map \n" 60 " ldr r2, [r3, r2, lsl #2] \n" 61 " uxth r1, r0 \n" // r1 is 0-(16)-0 X-(13)-X 000 62 " movw r3, #0xAAAA \n" 63 " lsr r1, r1, #2 \n" // r1 is 0-(16)-0 00 X-(13)-X 0 64 " ldrh r1, [r2, r1] \n" 65 " cmp r1, r3 \n" // 0xAAAA == VA_BITS16_DEFINED 66 " bne .LLV64LEc0 \n" // if !all_defined 67 " mov r1, #0x0 \n" // 0x0 == V_BITS32_DEFINED 68 " mov r0, #0x0 \n" // 0x0 == V_BITS32_DEFINED 69 " bx lr \n" 70 ".LLV64LEc0: \n" 71 " movw r3, #0x5555 \n" 72 " cmp r1, r3 \n" // 0x5555 == VA_BITS16_UNDEFINED 73 " bne .LLV64LEc4 \n" // if !all_undefined 74 " mov r1, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED 75 " mov r0, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED 76 " bx lr \n" 77 ".LLV64LEc4: \n" 78 " push {r4, lr} \n" 79 " mov r2, #0 \n" 80 " mov r1, #64 \n" 81 " bl mc_LOADVn_slow \n" 82 " pop {r4, pc} \n" 83 ".size vgMemCheck_helperc_LOADV64le, .-vgMemCheck_helperc_LOADV64le \n" 84 ".previous\n" 85 ); 86 87 #elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ 88 && (defined(VGP_x86_linux) || defined(VGP_x86_solaris)) 89 __asm__( 90 ".text\n" 91 ".align 16\n" 92 ".global vgMemCheck_helperc_LOADV64le\n" 93 ".type vgMemCheck_helperc_LOADV64le, @function\n" 94 "vgMemCheck_helperc_LOADV64le:\n" 95 " test $0x7, %eax\n" 96 " jne .LLV64LE2\n" /* jump if not aligned */ 97 " mov %eax, %ecx\n" 98 " movzwl %ax, %edx\n" 99 " shr $0x10, %ecx\n" 100 " mov primary_map(,%ecx,4), %ecx\n" 101 " shr $0x3, %edx\n" 102 " movzwl (%ecx,%edx,2), %edx\n" 103 " cmp $0xaaaa, %edx\n" 104 " jne .LLV64LE1\n" /* jump if not all defined */ 105 " xor %eax, %eax\n" /* return 0 in edx:eax */ 106 " xor %edx, %edx\n" 107 " ret\n" 108 ".LLV64LE1:\n" 109 " cmp $0x5555, %edx\n" 110 " jne .LLV64LE2\n" /* jump if not all undefined */ 111 " or $0xffffffff, %eax\n" /* else return all bits set in edx:eax */ 112 " or $0xffffffff, %edx\n" 113 " ret\n" 114 ".LLV64LE2:\n" 115 " xor %ecx, %ecx\n" /* tail call to mc_LOADVn_slow(a, 64, 0) */ 116 " mov $64, %edx\n" 117 " jmp mc_LOADVn_slow\n" 118 ".size vgMemCheck_helperc_LOADV64le, .-vgMemCheck_helperc_LOADV64le\n" 119 ".previous\n" 120 ); 121 122 #else 123 // Generic for all platforms except {arm32,x86}-linux and x86-solaris 124 // is in mc_main.c 125 #endif 126 127 128 // Non-generic assembly for arm32-linux 129 #if ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ 130 && defined(VGP_arm_linux) 131 __asm__( /* Derived from NCode template */ 132 ".text \n" 133 ".align 2 \n" 134 ".global vgMemCheck_helperc_LOADV32le \n" 135 ".type vgMemCheck_helperc_LOADV32le, %function \n" 136 "vgMemCheck_helperc_LOADV32le: \n" 137 " tst r0, #3 \n" // 1 138 " movw r3, #:lower16:primary_map \n" // 1 139 " bne .LLV32LEc4 \n" // 2 if misaligned 140 " lsr r2, r0, #16 \n" // 3 141 " movt r3, #:upper16:primary_map \n" // 3 142 " ldr r2, [r3, r2, lsl #2] \n" // 4 143 " uxth r1, r0 \n" // 4 144 " ldrb r1, [r2, r1, lsr #2] \n" // 5 145 " cmp r1, #0xAA \n" // 6 0xAA == VA_BITS8_DEFINED 146 " bne .LLV32LEc0 \n" // 7 if !all_defined 147 " mov r0, #0x0 \n" // 8 0x0 == V_BITS32_DEFINED 148 " bx lr \n" // 9 149 ".LLV32LEc0: \n" 150 " cmp r1, #0x55 \n" // 0x55 == VA_BITS8_UNDEFINED 151 " bne .LLV32LEc4 \n" // if !all_undefined 152 " mov r0, #0xFFFFFFFF \n" // 0xFFFFFFFF == V_BITS32_UNDEFINED 153 " bx lr \n" 154 ".LLV32LEc4: \n" 155 " push {r4, lr} \n" 156 " mov r2, #0 \n" 157 " mov r1, #32 \n" 158 " bl mc_LOADVn_slow \n" 159 " pop {r4, pc} \n" 160 ".size vgMemCheck_helperc_LOADV32le, .-vgMemCheck_helperc_LOADV32le \n" 161 ".previous\n" 162 ); 163 164 #elif ENABLE_ASSEMBLY_HELPERS && defined(PERF_FAST_LOADV) \ 165 && (defined(VGP_x86_linux) || defined(VGP_x86_solaris)) 166 __asm__( 167 ".text\n" 168 ".align 16\n" 169 ".global vgMemCheck_helperc_LOADV32le\n" 170 ".type vgMemCheck_helperc_LOADV32le, @function\n" 171 "vgMemCheck_helperc_LOADV32le:\n" 172 " test $0x3, %eax\n" 173 " jnz .LLV32LE2\n" /* jump if misaligned */ 174 " mov %eax, %edx\n" 175 " shr $16, %edx\n" 176 " mov primary_map(,%edx,4), %ecx\n" 177 " movzwl %ax, %edx\n" 178 " shr $2, %edx\n" 179 " movzbl (%ecx,%edx,1), %edx\n" 180 " cmp $0xaa, %edx\n" /* compare to VA_BITS8_DEFINED */ 181 " jne .LLV32LE1\n" /* jump if not completely defined */ 182 " xor %eax, %eax\n" /* else return V_BITS32_DEFINED */ 183 " ret\n" 184 ".LLV32LE1:\n" 185 " cmp $0x55, %edx\n" /* compare to VA_BITS8_UNDEFINED */ 186 " jne .LLV32LE2\n" /* jump if not completely undefined */ 187 " or $0xffffffff, %eax\n" /* else return V_BITS32_UNDEFINED */ 188 " ret\n" 189 ".LLV32LE2:\n" 190 " xor %ecx, %ecx\n" /* tail call mc_LOADVn_slow(a, 32, 0) */ 191 " mov $32, %edx\n" 192 " jmp mc_LOADVn_slow\n" 193 ".size vgMemCheck_helperc_LOADV32le, .-vgMemCheck_helperc_LOADV32le\n" 194 ".previous\n" 195 ); 196 197 #else 198 // Generic for all platforms except {arm32,x86}-linux and x86-solaris 199 // is in mc_main.c 200 #endif 201 202 /*--------------------------------------------------------------------*/ 203 /*--- end ---*/ 204 /*--------------------------------------------------------------------*/ 205