cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 1 | |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 2 | /*--------------------------------------------------------------------*/ |
| 3 | /*--- The core dispatch loop, for jumping to a code address. ---*/ |
sewardj | 0ddf76c | 2006-10-17 02:08:26 +0000 | [diff] [blame] | 4 | /*--- dispatch-ppc32-linux.S ---*/ |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 5 | /*--------------------------------------------------------------------*/ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 6 | |
| 7 | /* |
| 8 | This file is part of Valgrind, a dynamic binary instrumentation |
| 9 | framework. |
| 10 | |
sewardj | b3a1e4b | 2015-08-21 11:32:26 +0000 | [diff] [blame] | 11 | Copyright (C) 2005-2015 Cerion Armour-Brown <cerion@open-works.co.uk> |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 12 | |
| 13 | This program is free software; you can redistribute it and/or |
| 14 | modify it under the terms of the GNU General Public License as |
| 15 | published by the Free Software Foundation; either version 2 of the |
| 16 | License, or (at your option) any later version. |
| 17 | |
| 18 | This program is distributed in the hope that it will be useful, but |
| 19 | WITHOUT ANY WARRANTY; without even the implied warranty of |
| 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 21 | General Public License for more details. |
| 22 | |
| 23 | You should have received a copy of the GNU General Public License |
| 24 | along with this program; if not, write to the Free Software |
| 25 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 26 | 02111-1307, USA. |
| 27 | |
| 28 | The GNU General Public License is contained in the file COPYING. |
| 29 | */ |
| 30 | |
florian | 3f1d613 | 2015-09-30 20:30:48 +0000 | [diff] [blame] | 31 | #include "pub_core_basics_asm.h" |
| 32 | |
njn | 8b68b64 | 2009-06-24 00:37:09 +0000 | [diff] [blame] | 33 | #if defined(VGP_ppc32_linux) |
| 34 | |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 35 | #include "pub_core_dispatch_asm.h" |
| 36 | #include "pub_core_transtab_asm.h" |
| 37 | #include "libvex_guest_offsets.h" /* for OFFSET_ppc32_CIA */ |
| 38 | |
| 39 | |
| 40 | /*------------------------------------------------------------*/ |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 41 | /*--- ---*/ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 42 | /*--- The dispatch loop. VG_(disp_run_translations) is ---*/ |
| 43 | /*--- used to run all translations, ---*/ |
| 44 | /*--- including no-redir ones. ---*/ |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 45 | /*--- ---*/ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 46 | /*------------------------------------------------------------*/ |
| 47 | |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 48 | /*----------------------------------------------------*/ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 49 | /*--- Entry and preamble (set everything up) ---*/ |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 50 | /*----------------------------------------------------*/ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 51 | |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 52 | /* signature: |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 53 | void VG_(disp_run_translations)( UWord* two_words, |
| 54 | void* guest_state, |
| 55 | Addr host_addr ); |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 56 | */ |
| 57 | .text |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 58 | .globl VG_(disp_run_translations) |
| 59 | .type VG_(disp_run_translations), @function |
| 60 | VG_(disp_run_translations): |
| 61 | /* r3 holds two_words */ |
| 62 | /* r4 holds guest_state */ |
| 63 | /* r5 holds host_addr */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 64 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 65 | /* ----- entry point to VG_(disp_run_translations) ----- */ |
cerion | 51ce791 | 2005-11-11 01:00:36 +0000 | [diff] [blame] | 66 | /* For Linux/ppc32 we need the SysV ABI, which uses |
| 67 | LR->4(parent_sp), CR->anywhere. |
cerion | 1ade697 | 2005-12-20 20:48:50 +0000 | [diff] [blame] | 68 | (The AIX ABI, used on Darwin, |
cerion | 51ce791 | 2005-11-11 01:00:36 +0000 | [diff] [blame] | 69 | uses LR->8(prt_sp), CR->4(prt_sp)) |
| 70 | */ |
| 71 | |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 72 | /* Save lr */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 73 | mflr 6 |
| 74 | stw 6,4(1) |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 75 | |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 76 | /* New stack frame */ |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 77 | stwu 1,-496(1) /* sp should maintain 16-byte alignment */ |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 78 | |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 79 | /* Save callee-saved registers... */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 80 | /* r3, r4, r5 are live here, so use r6 */ |
| 81 | lis 6,VG_(machine_ppc32_has_FP)@ha |
| 82 | lwz 6,VG_(machine_ppc32_has_FP)@l(6) |
| 83 | cmplwi 6,0 |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 84 | beq LafterFP1 |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 85 | |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 86 | /* Floating-point reg save area : 144 bytes */ |
| 87 | stfd 31,488(1) |
| 88 | stfd 30,480(1) |
| 89 | stfd 29,472(1) |
| 90 | stfd 28,464(1) |
| 91 | stfd 27,456(1) |
| 92 | stfd 26,448(1) |
| 93 | stfd 25,440(1) |
| 94 | stfd 24,432(1) |
| 95 | stfd 23,424(1) |
| 96 | stfd 22,416(1) |
| 97 | stfd 21,408(1) |
| 98 | stfd 20,400(1) |
| 99 | stfd 19,392(1) |
| 100 | stfd 18,384(1) |
| 101 | stfd 17,376(1) |
| 102 | stfd 16,368(1) |
| 103 | stfd 15,360(1) |
| 104 | stfd 14,352(1) |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 105 | LafterFP1: |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 106 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 107 | /* General reg save area : 76 bytes */ |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 108 | stw 31,348(1) |
| 109 | stw 30,344(1) |
| 110 | stw 29,340(1) |
| 111 | stw 28,336(1) |
| 112 | stw 27,332(1) |
| 113 | stw 26,328(1) |
| 114 | stw 25,324(1) |
| 115 | stw 24,320(1) |
| 116 | stw 23,316(1) |
| 117 | stw 22,312(1) |
| 118 | stw 21,308(1) |
| 119 | stw 20,304(1) |
| 120 | stw 19,300(1) |
| 121 | stw 18,296(1) |
| 122 | stw 17,292(1) |
| 123 | stw 16,288(1) |
| 124 | stw 15,284(1) |
| 125 | stw 14,280(1) |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 126 | stw 13,276(1) |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 127 | stw 3,272(1) /* save two_words for later */ |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 128 | |
cerion | 51ce791 | 2005-11-11 01:00:36 +0000 | [diff] [blame] | 129 | /* It's necessary to save/restore VRSAVE in the AIX / Darwin ABI. |
| 130 | The Linux kernel might not actually use VRSAVE for its intended |
| 131 | purpose, but it should be harmless to preserve anyway. */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 132 | /* r3, r4, r5 are live here, so use r6 */ |
| 133 | lis 6,VG_(machine_ppc32_has_VMX)@ha |
| 134 | lwz 6,VG_(machine_ppc32_has_VMX)@l(6) |
| 135 | cmplwi 6,0 |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 136 | beq LafterVMX1 |
cerion | 51ce791 | 2005-11-11 01:00:36 +0000 | [diff] [blame] | 137 | |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 138 | #ifdef HAS_ALTIVEC |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 139 | /* VRSAVE save word : 32 bytes */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 140 | mfspr 6,256 /* vrsave reg is spr number 256 */ |
| 141 | stw 6,244(1) |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 142 | |
| 143 | /* Alignment padding : 4 bytes */ |
| 144 | |
| 145 | /* Vector reg save area (quadword aligned) : 192 bytes */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 146 | li 6,224 |
| 147 | stvx 31,6,1 |
| 148 | li 6,208 |
| 149 | stvx 30,6,1 |
| 150 | li 6,192 |
| 151 | stvx 29,6,1 |
| 152 | li 6,176 |
| 153 | stvx 28,6,1 |
| 154 | li 6,160 |
| 155 | stvx 27,6,1 |
| 156 | li 6,144 |
| 157 | stvx 26,6,1 |
| 158 | li 6,128 |
| 159 | stvx 25,6,1 |
| 160 | li 6,112 |
sewardj | bed0746 | 2015-08-21 13:43:07 +0000 | [diff] [blame] | 161 | stvx 24,6,1 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 162 | li 6,96 |
| 163 | stvx 23,6,1 |
| 164 | li 6,80 |
| 165 | stvx 22,6,1 |
| 166 | li 6,64 |
| 167 | stvx 21,6,1 |
| 168 | li 6,48 |
| 169 | stvx 20,6,1 |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 170 | #endif |
| 171 | |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 172 | LafterVMX1: |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 173 | |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 174 | /* Save cr */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 175 | mfcr 6 |
| 176 | stw 6,44(1) |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 177 | |
cerion | 51ce791 | 2005-11-11 01:00:36 +0000 | [diff] [blame] | 178 | /* Local variable space... */ |
| 179 | |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 180 | /* 32(sp) used later to check FPSCR[RM] */ |
| 181 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 182 | /* r3 holds two_words */ |
| 183 | /* r4 holds guest_state */ |
| 184 | /* r5 holds host_addr */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 185 | |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 186 | /* 24(sp) used later to stop ctr reg being clobbered */ |
cerion | a5422db | 2005-12-01 19:05:41 +0000 | [diff] [blame] | 187 | /* 20(sp) used later to load fpscr with zero */ |
| 188 | /* 8:16(sp) free */ |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 189 | |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 190 | /* Linkage Area (reserved) |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 191 | 4(sp) : LR |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 192 | 0(sp) : back-chain |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 193 | */ |
| 194 | |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 195 | /* set host FPU control word to the default mode expected |
cerion | 1936d8d | 2005-07-05 18:24:22 +0000 | [diff] [blame] | 196 | by VEX-generated code. See comments in libvex.h for |
| 197 | more info. */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 198 | lis 6,VG_(machine_ppc32_has_FP)@ha |
| 199 | lwz 6,VG_(machine_ppc32_has_FP)@l(6) |
| 200 | cmplwi 6,0 |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 201 | beq LafterFP2 |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 202 | |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 203 | /* get zero into f3 (tedious) */ |
| 204 | /* note: fsub 3,3,3 is not a reliable way to do this, |
| 205 | since if f3 holds a NaN or similar then we don't necessarily |
| 206 | wind up with zero. */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 207 | li 6,0 |
| 208 | stw 6,20(1) |
cerion | a5422db | 2005-12-01 19:05:41 +0000 | [diff] [blame] | 209 | lfs 3,20(1) |
cerion | 2108204 | 2005-12-06 19:07:08 +0000 | [diff] [blame] | 210 | mtfsf 0xFF,3 /* fpscr = f3 */ |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 211 | LafterFP2: |
cerion | 1936d8d | 2005-07-05 18:24:22 +0000 | [diff] [blame] | 212 | |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 213 | /* set host AltiVec control word to the default mode expected |
| 214 | by VEX-generated code. */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 215 | lis 6,VG_(machine_ppc32_has_VMX)@ha |
| 216 | lwz 6,VG_(machine_ppc32_has_VMX)@l(6) |
| 217 | cmplwi 6,0 |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 218 | beq LafterVMX2 |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 219 | |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 220 | #ifdef HAS_ALTIVEC |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 221 | vspltisw 3,0x0 /* generate zero */ |
cerion | 1936d8d | 2005-07-05 18:24:22 +0000 | [diff] [blame] | 222 | mtvscr 3 |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 223 | #endif |
| 224 | |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 225 | LafterVMX2: |
| 226 | |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 227 | /* make a stack frame for the code we are calling */ |
| 228 | stwu 1,-16(1) |
| 229 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 230 | /* Set up the guest state ptr */ |
| 231 | mr 31,4 /* r31 (generated code gsp) = r4 */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 232 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 233 | /* and jump into the code cache. Chained translations in |
| 234 | the code cache run, until for whatever reason, they can't |
| 235 | continue. When that happens, the translation in question |
| 236 | will jump (or call) to one of the continuation points |
| 237 | VG_(cp_...) below. */ |
| 238 | mtctr 5 |
| 239 | bctr |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 240 | /*NOTREACHED*/ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 241 | |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 242 | /*----------------------------------------------------*/ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 243 | /*--- Postamble and exit. ---*/ |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 244 | /*----------------------------------------------------*/ |
| 245 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 246 | postamble: |
| 247 | /* At this point, r6 and r7 contain two |
| 248 | words to be returned to the caller. r6 |
| 249 | holds a TRC value, and r7 optionally may |
| 250 | hold another word (for CHAIN_ME exits, the |
| 251 | address of the place to patch.) */ |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 252 | |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 253 | /* We're leaving. Check that nobody messed with |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 254 | VSCR or FPSCR in ways we don't expect. */ |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 255 | /* Using r10 - value used again further on, so don't trash! */ |
| 256 | lis 10,VG_(machine_ppc32_has_FP)@ha |
| 257 | lwz 10,VG_(machine_ppc32_has_FP)@l(10) |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 258 | |
| 259 | /* Using r11 - value used again further on, so don't trash! */ |
| 260 | lis 11,VG_(machine_ppc32_has_VMX)@ha |
| 261 | lwz 11,VG_(machine_ppc32_has_VMX)@l(11) |
| 262 | |
| 263 | cmplwi 10,0 /* Do we have FP ? */ |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 264 | beq LafterFP8 |
| 265 | |
sewardj | e68ddf7 | 2006-02-06 05:14:31 +0000 | [diff] [blame] | 266 | /* Set fpscr back to a known state, since vex-generated code |
| 267 | may have messed with fpscr[rm]. */ |
| 268 | li 5,0 |
| 269 | addi 1,1,-16 |
| 270 | stw 5,0(1) |
| 271 | lfs 3,0(1) |
| 272 | addi 1,1,16 |
| 273 | mtfsf 0xFF,3 /* fpscr = f3 */ |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 274 | LafterFP8: |
| 275 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 276 | cmplwi 11,0 /* Do we have altivec? */ |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 277 | beq LafterVMX8 |
| 278 | |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 279 | #ifdef HAS_ALTIVEC |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 280 | /* Check VSCR[NJ] == 1 */ |
| 281 | /* first generate 4x 0x00010000 */ |
| 282 | vspltisw 4,0x1 /* 4x 0x00000001 */ |
| 283 | vspltisw 5,0x0 /* zero */ |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 284 | vsldoi 6,4,5,0x2 /* <<2*8 => 4x 0x00010000 */ |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 285 | /* retrieve VSCR and mask wanted bits */ |
| 286 | mfvscr 7 |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 287 | vand 7,7,6 /* gives NJ flag */ |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 288 | vspltw 7,7,0x3 /* flags-word to all lanes */ |
cerion | 1b6b2b3 | 2005-11-18 20:45:18 +0000 | [diff] [blame] | 289 | vcmpequw. 8,6,7 /* CR[24] = 1 if v6 == v7 */ |
| 290 | bt 24,invariant_violation /* branch if all_equal */ |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 291 | #endif |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 292 | |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 293 | LafterVMX8: |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 294 | /* otherwise we're OK */ |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 295 | b remove_frame |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 296 | |
| 297 | invariant_violation: |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 298 | li 6,VG_TRC_INVARIANT_FAILED |
| 299 | li 7,0 |
| 300 | /* fall through */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 301 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 302 | remove_frame: |
| 303 | /* Restore FP regs */ |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 304 | /* r10 already holds VG_(machine_ppc32_has_FP) value */ |
| 305 | cmplwi 10,0 |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 306 | beq LafterFP9 |
| 307 | |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 308 | /* Floating-point regs */ |
| 309 | lfd 31,488(1) |
| 310 | lfd 30,480(1) |
| 311 | lfd 29,472(1) |
| 312 | lfd 28,464(1) |
| 313 | lfd 27,456(1) |
| 314 | lfd 26,448(1) |
| 315 | lfd 25,440(1) |
| 316 | lfd 24,432(1) |
| 317 | lfd 23,424(1) |
| 318 | lfd 22,416(1) |
| 319 | lfd 21,408(1) |
| 320 | lfd 20,400(1) |
| 321 | lfd 19,392(1) |
| 322 | lfd 18,384(1) |
| 323 | lfd 17,376(1) |
| 324 | lfd 16,368(1) |
| 325 | lfd 15,360(1) |
| 326 | lfd 14,352(1) |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 327 | LafterFP9: |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 328 | |
cerion | 3d11e0e | 2005-11-16 20:22:11 +0000 | [diff] [blame] | 329 | /* r11 already holds VG_(machine_ppc32_has_VMX) value */ |
| 330 | cmplwi 11,0 |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 331 | beq LafterVMX9 |
| 332 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 333 | /* Restore Altivec regs */ |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 334 | #ifdef HAS_ALTIVEC |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 335 | /* VRSAVE */ |
| 336 | lwz 4,244(1) |
| 337 | mfspr 4,256 /* VRSAVE reg is spr number 256 */ |
| 338 | |
| 339 | /* Vector regs */ |
| 340 | li 4,224 |
| 341 | lvx 31,4,1 |
| 342 | li 4,208 |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 343 | lvx 30,4,1 |
| 344 | li 4,192 |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 345 | lvx 29,4,1 |
| 346 | li 4,176 |
| 347 | lvx 28,4,1 |
| 348 | li 4,160 |
| 349 | lvx 27,4,1 |
| 350 | li 4,144 |
| 351 | lvx 26,4,1 |
| 352 | li 4,128 |
| 353 | lvx 25,4,1 |
| 354 | li 4,112 |
| 355 | lvx 24,4,1 |
| 356 | li 4,96 |
| 357 | lvx 23,4,1 |
| 358 | li 4,80 |
| 359 | lvx 22,4,1 |
| 360 | li 4,64 |
| 361 | lvx 21,4,1 |
| 362 | li 4,48 |
| 363 | lvx 20,4,1 |
bart | b892884 | 2010-06-13 14:49:04 +0000 | [diff] [blame] | 364 | #endif |
sewardj | 2c36d42 | 2005-11-13 01:59:22 +0000 | [diff] [blame] | 365 | LafterVMX9: |
cerion | e51a42c | 2005-11-08 22:03:07 +0000 | [diff] [blame] | 366 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 367 | /* restore int regs, including importantly r3 (two_words) */ |
| 368 | addi 1,1,16 |
| 369 | lwz 31,348(1) |
| 370 | lwz 30,344(1) |
| 371 | lwz 29,340(1) |
| 372 | lwz 28,336(1) |
| 373 | lwz 27,332(1) |
| 374 | lwz 26,328(1) |
| 375 | lwz 25,324(1) |
| 376 | lwz 24,320(1) |
| 377 | lwz 23,316(1) |
| 378 | lwz 22,312(1) |
| 379 | lwz 21,308(1) |
| 380 | lwz 20,304(1) |
| 381 | lwz 19,300(1) |
| 382 | lwz 18,296(1) |
| 383 | lwz 17,292(1) |
| 384 | lwz 16,288(1) |
| 385 | lwz 15,284(1) |
| 386 | lwz 14,280(1) |
| 387 | lwz 13,276(1) |
| 388 | lwz 3,272(1) |
| 389 | /* Stash return values */ |
| 390 | stw 6,0(3) |
| 391 | stw 7,4(3) |
| 392 | |
| 393 | /* restore lr & sp, and leave */ |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 394 | lwz 0,500(1) /* stack_size + 4 */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 395 | mtlr 0 |
cerion | 3e35756 | 2005-11-09 14:13:08 +0000 | [diff] [blame] | 396 | addi 1,1,496 /* stack_size */ |
cerion | 85665ca | 2005-06-20 15:51:07 +0000 | [diff] [blame] | 397 | blr |
| 398 | |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 399 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 400 | /*----------------------------------------------------*/ |
| 401 | /*--- Continuation points ---*/ |
| 402 | /*----------------------------------------------------*/ |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 403 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 404 | /* ------ Chain me to slow entry point ------ */ |
| 405 | .global VG_(disp_cp_chain_me_to_slowEP) |
| 406 | VG_(disp_cp_chain_me_to_slowEP): |
| 407 | /* We got called. The return address indicates |
| 408 | where the patching needs to happen. Collect |
| 409 | the return address and, exit back to C land, |
| 410 | handing the caller the pair (Chain_me_S, RA) */ |
| 411 | li 6, VG_TRC_CHAIN_ME_TO_SLOW_EP |
| 412 | mflr 7 |
| 413 | /* 8 = imm32-fixed2 r30, disp_cp_chain_me_to_slowEP |
| 414 | 4 = mtctr r30 |
| 415 | 4 = btctr |
| 416 | */ |
| 417 | subi 7,7,8+4+4 |
| 418 | b postamble |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 419 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 420 | /* ------ Chain me to fast entry point ------ */ |
| 421 | .global VG_(disp_cp_chain_me_to_fastEP) |
| 422 | VG_(disp_cp_chain_me_to_fastEP): |
| 423 | /* We got called. The return address indicates |
| 424 | where the patching needs to happen. Collect |
| 425 | the return address and, exit back to C land, |
| 426 | handing the caller the pair (Chain_me_S, RA) */ |
| 427 | li 6, VG_TRC_CHAIN_ME_TO_FAST_EP |
| 428 | mflr 7 |
| 429 | /* 8 = imm32-fixed2 r30, disp_cp_chain_me_to_fastEP |
| 430 | 4 = mtctr r30 |
| 431 | 4 = btctr |
| 432 | */ |
| 433 | subi 7,7,8+4+4 |
| 434 | b postamble |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 435 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 436 | /* ------ Indirect but boring jump ------ */ |
| 437 | .global VG_(disp_cp_xindir) |
| 438 | VG_(disp_cp_xindir): |
| 439 | /* Where are we going? */ |
| 440 | lwz 3,OFFSET_ppc32_CIA(31) |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 441 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 442 | /* stats only */ |
sewardj | 96b3c20 | 2012-04-21 23:28:34 +0000 | [diff] [blame] | 443 | lis 5,VG_(stats__n_xindirs_32)@ha |
| 444 | addi 5,5,VG_(stats__n_xindirs_32)@l |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 445 | lwz 6,0(5) |
sewardj | 96b3c20 | 2012-04-21 23:28:34 +0000 | [diff] [blame] | 446 | addi 6,6,1 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 447 | stw 6,0(5) |
| 448 | |
| 449 | /* r5 = &VG_(tt_fast) */ |
| 450 | lis 5,VG_(tt_fast)@ha |
| 451 | addi 5,5,VG_(tt_fast)@l /* & VG_(tt_fast) */ |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 452 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 453 | /* try a fast lookup in the translation cache */ |
| 454 | /* r4 = VG_TT_FAST_HASH(addr) * sizeof(FastCacheEntry) |
| 455 | = ((r3 >>u 2) & VG_TT_FAST_MASK) << 3 */ |
| 456 | rlwinm 4,3,1, 29-VG_TT_FAST_BITS, 28 /* entry# * 8 */ |
| 457 | add 5,5,4 /* & VG_(tt_fast)[entry#] */ |
| 458 | lwz 6,0(5) /* .guest */ |
| 459 | lwz 7,4(5) /* .host */ |
| 460 | cmpw 3,6 |
| 461 | bne fast_lookup_failed |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 462 | |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 463 | /* Found a match. Jump to .host. */ |
| 464 | mtctr 7 |
| 465 | bctr |
| 466 | |
| 467 | fast_lookup_failed: |
| 468 | /* stats only */ |
sewardj | 96b3c20 | 2012-04-21 23:28:34 +0000 | [diff] [blame] | 469 | lis 5,VG_(stats__n_xindir_misses_32)@ha |
| 470 | addi 5,5,VG_(stats__n_xindir_misses_32)@l |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 471 | lwz 6,0(5) |
sewardj | 96b3c20 | 2012-04-21 23:28:34 +0000 | [diff] [blame] | 472 | addi 6,6,1 |
sewardj | 291849f | 2012-04-20 23:58:55 +0000 | [diff] [blame] | 473 | stw 6,0(5) |
| 474 | |
| 475 | li 6,VG_TRC_INNER_FASTMISS |
| 476 | li 7,0 |
| 477 | b postamble |
| 478 | /*NOTREACHED*/ |
| 479 | |
| 480 | /* ------ Assisted jump ------ */ |
| 481 | .global VG_(disp_cp_xassisted) |
| 482 | VG_(disp_cp_xassisted): |
| 483 | /* r31 contains the TRC */ |
| 484 | mr 6,31 |
| 485 | li 7,0 |
| 486 | b postamble |
| 487 | |
| 488 | /* ------ Event check failed ------ */ |
| 489 | .global VG_(disp_cp_evcheck_fail) |
| 490 | VG_(disp_cp_evcheck_fail): |
| 491 | li 6,VG_TRC_INNER_COUNTERZERO |
| 492 | li 7,0 |
| 493 | b postamble |
| 494 | |
| 495 | |
| 496 | .size VG_(disp_run_translations), .-VG_(disp_run_translations) |
sewardj | a591a05 | 2006-01-12 14:04:46 +0000 | [diff] [blame] | 497 | |
njn | 8b68b64 | 2009-06-24 00:37:09 +0000 | [diff] [blame] | 498 | #endif // defined(VGP_ppc32_linux) |
| 499 | |
florian | 3f1d613 | 2015-09-30 20:30:48 +0000 | [diff] [blame] | 500 | /* Let the linker know we don't need an executable stack */ |
| 501 | MARK_STACK_NO_EXEC |
| 502 | |
sewardj | 5d3a1c9 | 2005-12-15 21:40:34 +0000 | [diff] [blame] | 503 | /*--------------------------------------------------------------------*/ |
| 504 | /*--- end ---*/ |
| 505 | /*--------------------------------------------------------------------*/ |