Darwin and FreeBSD: new / delete wrappers
[valgrind.git] / coregrind / m_dispatch / dispatch-ppc32-linux.S
blobb679a2eb6a51ed2e56da8a60e550280b3b99d806
2 /*--------------------------------------------------------------------*/
3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
4 /*---                                       dispatch-ppc32-linux.S ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8   This file is part of Valgrind, a dynamic binary instrumentation
9   framework.
11   Copyright (C) 2005-2017 Cerion Armour-Brown <cerion@open-works.co.uk>
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.
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.
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, see <http://www.gnu.org/licenses/>.
26   The GNU General Public License is contained in the file COPYING.
29 #include "pub_core_basics_asm.h"
31 #if defined(VGP_ppc32_linux)
33 #include "pub_core_dispatch_asm.h"
34 #include "pub_core_transtab_asm.h"
35 #include "libvex_guest_offsets.h"       /* for OFFSET_ppc32_CIA */
38 /*------------------------------------------------------------*/
39 /*---                                                      ---*/
40 /*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
41 /*--- used to run all translations,                        ---*/
42 /*--- including no-redir ones.                             ---*/
43 /*---                                                      ---*/
44 /*------------------------------------------------------------*/
46 /*----------------------------------------------------*/
47 /*--- Entry and preamble (set everything up)       ---*/
48 /*----------------------------------------------------*/
50 /* signature:
51 void VG_(disp_run_translations)( UWord* two_words,
52                                  void*  guest_state,
53                                  Addr   host_addr );
55 .text
56 .globl  VG_(disp_run_translations)
57 .type  VG_(disp_run_translations), @function
58 VG_(disp_run_translations):
59         /* r3 holds two_words */
60         /* r4 holds guest_state */
61         /* r5 holds host_addr */
63         /* ----- entry point to VG_(disp_run_translations) ----- */
64         /* For Linux/ppc32 we need the SysV ABI, which uses
65            LR->4(parent_sp), CR->anywhere.
66            (The AIX ABI, used on Darwin,
67            uses LR->8(prt_sp), CR->4(prt_sp))
68         */
70         /* Save lr */
71         mflr    6
72         stw     6,4(1)
74         /* New stack frame */
75         stwu    1,-496(1)  /* sp should maintain 16-byte alignment */
77         /* Save callee-saved registers... */
78         /* r3, r4, r5 are live here, so use r6 */
79         lis     6,VG_(machine_ppc32_has_FP)@ha
80         lwz     6,VG_(machine_ppc32_has_FP)@l(6)
81         cmplwi  6,0
82         beq     LafterFP1
84         /* Floating-point reg save area : 144 bytes */
85         stfd    31,488(1)
86         stfd    30,480(1)
87         stfd    29,472(1)
88         stfd    28,464(1)
89         stfd    27,456(1)
90         stfd    26,448(1)
91         stfd    25,440(1)
92         stfd    24,432(1)
93         stfd    23,424(1)
94         stfd    22,416(1)
95         stfd    21,408(1)
96         stfd    20,400(1)
97         stfd    19,392(1)
98         stfd    18,384(1)
99         stfd    17,376(1)
100         stfd    16,368(1)
101         stfd    15,360(1)
102         stfd    14,352(1)
103 LafterFP1:
105         /* General reg save area : 76 bytes */
106         stw     31,348(1)
107         stw     30,344(1)
108         stw     29,340(1)
109         stw     28,336(1)
110         stw     27,332(1)
111         stw     26,328(1)
112         stw     25,324(1)
113         stw     24,320(1)
114         stw     23,316(1)
115         stw     22,312(1)
116         stw     21,308(1)
117         stw     20,304(1)
118         stw     19,300(1)
119         stw     18,296(1)
120         stw     17,292(1)
121         stw     16,288(1)
122         stw     15,284(1)
123         stw     14,280(1)
124         stw     13,276(1)
125         stw     3,272(1)  /* save two_words for later */
127         /* It's necessary to save/restore VRSAVE in the AIX / Darwin ABI.
128            The Linux kernel might not actually use VRSAVE for its intended
129            purpose, but it should be harmless to preserve anyway. */
130         /* r3, r4, r5 are live here, so use r6 */
131         lis     6,VG_(machine_ppc32_has_VMX)@ha
132         lwz     6,VG_(machine_ppc32_has_VMX)@l(6)
133         cmplwi  6,0
134         beq     LafterVMX1
136 #ifdef HAS_ALTIVEC
137         /* VRSAVE save word : 32 bytes */
138         mfspr   6,256         /* vrsave reg is spr number 256 */
139         stw     6,244(1)
141         /* Alignment padding : 4 bytes */
143         /* Vector reg save area (quadword aligned) : 192 bytes */
144         li      6,224
145         stvx    31,6,1
146         li      6,208
147         stvx    30,6,1
148         li      6,192
149         stvx    29,6,1
150         li      6,176
151         stvx    28,6,1
152         li      6,160
153         stvx    27,6,1
154         li      6,144
155         stvx    26,6,1
156         li      6,128
157         stvx    25,6,1
158         li      6,112
159         stvx    24,6,1
160         li      6,96
161         stvx    23,6,1
162         li      6,80
163         stvx    22,6,1
164         li      6,64
165         stvx    21,6,1
166         li      6,48
167         stvx    20,6,1
168 #endif
169         
170 LafterVMX1:
172         /* Save cr */
173         mfcr    6
174         stw     6,44(1)
176         /* Local variable space... */
178         /* 32(sp) used later to check FPSCR[RM] */
180         /* r3 holds two_words */
181         /* r4 holds guest_state */
182         /* r5 holds host_addr */
184         /* 24(sp) used later to stop ctr reg being clobbered */
185         /* 20(sp) used later to load fpscr with zero */
186         /* 8:16(sp) free */
187         
188         /* Linkage Area (reserved)
189            4(sp)  : LR
190            0(sp)  : back-chain
191         */
193         /* set host FPU control word to the default mode expected 
194            by VEX-generated code.  See comments in libvex.h for
195            more info. */
196         lis     6,VG_(machine_ppc32_has_FP)@ha
197         lwz     6,VG_(machine_ppc32_has_FP)@l(6)
198         cmplwi  6,0
199         beq     LafterFP2
201         /* get zero into f3 (tedious) */
202         /* note: fsub 3,3,3 is not a reliable way to do this, 
203            since if f3 holds a NaN or similar then we don't necessarily
204            wind up with zero. */
205         li      6,0
206         stw     6,20(1)
207         lfs     3,20(1)
208         mtfsf   0xFF,3   /* fpscr = f3 */
209 LafterFP2:
211         /* set host AltiVec control word to the default mode expected 
212            by VEX-generated code. */
213         lis     6,VG_(machine_ppc32_has_VMX)@ha
214         lwz     6,VG_(machine_ppc32_has_VMX)@l(6)
215         cmplwi  6,0
216         beq     LafterVMX2
218 #ifdef HAS_ALTIVEC
219         vspltisw 3,0x0  /* generate zero */
220         mtvscr  3       /* sets VSCR[NJ]=0 */
221 #endif
222         
223 LafterVMX2:
225         /* make a stack frame for the code we are calling */
226         stwu    1,-16(1)
228         /* Set up the guest state ptr */
229         mr      31,4      /* r31 (generated code gsp) = r4 */
231         /* and jump into the code cache.  Chained translations in
232            the code cache run, until for whatever reason, they can't
233            continue.  When that happens, the translation in question
234            will jump (or call) to one of the continuation points
235            VG_(cp_...) below. */
236         mtctr   5
237         bctr
238         /*NOTREACHED*/
240 /*----------------------------------------------------*/
241 /*--- Postamble and exit.                          ---*/
242 /*----------------------------------------------------*/
244 postamble:
245         /* At this point, r6 and r7 contain two
246            words to be returned to the caller.  r6
247            holds a TRC value, and r7 optionally may
248            hold another word (for CHAIN_ME exits, the
249            address of the place to patch.) */
251         /* We're leaving.  Check that nobody messed with
252            VSCR or FPSCR in ways we don't expect. */
253         /* Using r10 - value used again further on, so don't trash! */
254         lis     10,VG_(machine_ppc32_has_FP)@ha
255         lwz     10,VG_(machine_ppc32_has_FP)@l(10)
257         /* Using r11 - value used again further on, so don't trash! */
258         lis     11,VG_(machine_ppc32_has_VMX)@ha
259         lwz     11,VG_(machine_ppc32_has_VMX)@l(11)
261         cmplwi  10,0    /* Do we have FP ? */
262         beq     LafterFP8
264         /* Set fpscr back to a known state, since vex-generated code
265            may have messed with fpscr[rm]. */
266         li      5,0
267         addi    1,1,-16
268         stw     5,0(1)
269         lfs     3,0(1)
270         addi    1,1,16
271         mtfsf   0xFF,3   /* fpscr = f3 */
272 LafterFP8:
274         cmplwi  11,0    /* Do we have altivec? */
275         beq     LafterVMX8
277 #ifdef HAS_ALTIVEC
278         /* Expect VSCR[NJ] to be 0, call invariant_violation if
279            VSCR[NJ] == 1 . */
280         /* first generate 4x 0x00010000 */
281         vspltisw  4,0x1                   /* 4x 0x00000001 */
282         vspltisw  5,0x0                   /* zero */
283         vsldoi    6,4,5,0x2               /* <<2*8 => 4x 0x00010000 */
284         /* retrieve VSCR and mask wanted bits */
285         mfvscr    7
286         vand      7,7,6                   /* gives NJ flag */
287         vspltw    7,7,0x3                 /* flags-word to all lanes */
288         vcmpequw. 8,6,7                   /* CR[24] = 1 if v6 == v7 */
289         bt        24,invariant_violation  /* branch if all_equal */
290 #endif
292 LafterVMX8:
293         /* otherwise we're OK */
294         b       remove_frame
296 invariant_violation:
297         li      6,VG_TRC_INVARIANT_FAILED
298         li      7,0
299         /* fall through */
301 remove_frame:
302         /* Restore FP regs */
303         /* r10 already holds VG_(machine_ppc32_has_FP) value */
304         cmplwi  10,0
305         beq     LafterFP9
307         /* Floating-point regs */
308         lfd     31,488(1)
309         lfd     30,480(1)
310         lfd     29,472(1)
311         lfd     28,464(1)
312         lfd     27,456(1)
313         lfd     26,448(1)
314         lfd     25,440(1)
315         lfd     24,432(1)
316         lfd     23,424(1)
317         lfd     22,416(1)
318         lfd     21,408(1)
319         lfd     20,400(1)
320         lfd     19,392(1)
321         lfd     18,384(1)
322         lfd     17,376(1)
323         lfd     16,368(1)
324         lfd     15,360(1)
325         lfd     14,352(1)
326 LafterFP9:
328         /* r11 already holds VG_(machine_ppc32_has_VMX) value */
329         cmplwi  11,0
330         beq     LafterVMX9
332         /* Restore Altivec regs */
333 #ifdef HAS_ALTIVEC
334         /* VRSAVE */
335         lwz     4,244(1)
336         mfspr   4,256         /* VRSAVE reg is spr number 256 */
338         /* Vector regs */
339         li      4,224
340         lvx     31,4,1
341         li      4,208
342         lvx     30,4,1
343         li      4,192
344         lvx     29,4,1
345         li      4,176
346         lvx     28,4,1
347         li      4,160
348         lvx     27,4,1
349         li      4,144
350         lvx     26,4,1
351         li      4,128
352         lvx     25,4,1
353         li      4,112
354         lvx     24,4,1
355         li      4,96
356         lvx     23,4,1
357         li      4,80
358         lvx     22,4,1
359         li      4,64
360         lvx     21,4,1
361         li      4,48
362         lvx     20,4,1
363 #endif
364 LafterVMX9:
366         /* restore int regs, including importantly r3 (two_words) */
367         addi    1,1,16
368         lwz     31,348(1)
369         lwz     30,344(1)
370         lwz     29,340(1)
371         lwz     28,336(1)
372         lwz     27,332(1)
373         lwz     26,328(1)
374         lwz     25,324(1)
375         lwz     24,320(1)
376         lwz     23,316(1)
377         lwz     22,312(1)
378         lwz     21,308(1)
379         lwz     20,304(1)
380         lwz     19,300(1)
381         lwz     18,296(1)
382         lwz     17,292(1)
383         lwz     16,288(1)
384         lwz     15,284(1)
385         lwz     14,280(1)
386         lwz     13,276(1)
387         lwz     3,272(1)
388         /* Stash return values */
389         stw     6,0(3)
390         stw     7,4(3)
392         /* restore lr & sp, and leave */
393         lwz     0,500(1)  /* stack_size + 4 */
394         mtlr    0
395         addi    1,1,496   /* stack_size */
396         blr
399 /*----------------------------------------------------*/
400 /*--- Continuation points                          ---*/
401 /*----------------------------------------------------*/
403 /* ------ Chain me to slow entry point ------ */
404 .global VG_(disp_cp_chain_me_to_slowEP)
405 VG_(disp_cp_chain_me_to_slowEP):
406         /* We got called.  The return address indicates
407            where the patching needs to happen.  Collect
408            the return address and, exit back to C land,
409            handing the caller the pair (Chain_me_S, RA) */
410         li   6, VG_TRC_CHAIN_ME_TO_SLOW_EP
411         mflr 7
412         /* 8 = imm32-fixed2 r30, disp_cp_chain_me_to_slowEP
413            4 = mtctr r30
414            4 = btctr
415         */
416         subi 7,7,8+4+4
417         b    postamble
419 /* ------ Chain me to fast entry point ------ */
420 .global VG_(disp_cp_chain_me_to_fastEP)
421 VG_(disp_cp_chain_me_to_fastEP):
422         /* We got called.  The return address indicates
423            where the patching needs to happen.  Collect
424            the return address and, exit back to C land,
425            handing the caller the pair (Chain_me_S, RA) */
426         li   6, VG_TRC_CHAIN_ME_TO_FAST_EP
427         mflr 7
428         /* 8 = imm32-fixed2 r30, disp_cp_chain_me_to_fastEP
429            4 = mtctr r30
430            4 = btctr
431         */
432         subi 7,7,8+4+4
433         b    postamble
435 /* ------ Indirect but boring jump ------ */
436 .global VG_(disp_cp_xindir)
437 VG_(disp_cp_xindir):
438         /* Where are we going? */
439         lwz   20, OFFSET_ppc32_CIA(31)
441         /* stats only */
442         lis   24,     VG_(stats__n_xIndirs_32)@ha
443         addi  24, 24, VG_(stats__n_xIndirs_32)@l
444         lwz   25, 0(24)
445         addi  25, 25, 1
446         stw   25, 0(24)
448         // LIVE: r31 (guest state ptr), r20 (guest address to go to).
449         // We use 6 temporaries:
450         //   r26 (to point at the relevant FastCacheSet),
451         //   r21, r22, r23 (scratch, for swapping entries within a set)
452         //   r24, r25 (other scratch)
454         /* Try a fast lookup in the translation cache.  This is pretty much
455            a handcoded version of VG_(lookupInFastCache). */
457         // Compute r26 = VG_TT_FAST_HASH(guest)
458         srwi  26, 20, 2                       // g2 = guest >> 2
459         srwi  25, 20, (VG_TT_FAST_BITS + 2)   // (g2 >> VG_TT_FAST_BITS)
460         xor   26, 26, 25                      // (g2 >> VG_TT_FAST_BITS) ^ g2
461         andi. 26, 26, VG_TT_FAST_MASK         // setNo
462         
463         // Compute r6 = &VG_(tt_fast)[r6]
464         lis   25, VG_(tt_fast)@ha
465         addi  25, 25, VG_(tt_fast)@l
466         slwi  26, 26, VG_FAST_CACHE_SET_BITS
467         add   26, 26, 25
469         // LIVE: r31 (guest state ptr), r20 (guest addr), r26 (cache set)
470         // try way 0
471         lwz   24, FCS_g0(26)   // .guest0
472         lwz   25, FCS_h0(26)   // .host0
473         cmpw  24, 20  // cmp against .guest0
474         bne   1f
475         // hit at way 0
476         // goto .host0
477         mtctr 25
478         bctr
479         /*NOTREACHED*/
481 1:      // try way 1
482         lwz   24, FCS_g1(26)
483         cmpw  24, 20  // cmp against .guest1
484         bne   2f
485         // hit at way 1; swap upwards
486         lwz   21, FCS_g0(26)   // 21 = old .guest0
487         lwz   22, FCS_h0(26)   // 22 = old .host0
488         lwz   23, FCS_h1(26)   // 23 = old .host1
489         stw   20, FCS_g0(26)   // new .guest0 = guest
490         stw   23, FCS_h0(26)   // new .host0 = old .host1
491         stw   21, FCS_g1(26)   // new .guest1 = old .guest0
492         stw   22, FCS_h1(26)   // new .host1 = old .host0
493         // stats only
494         lis   24,     VG_(stats__n_xIndir_hits1_32)@ha
495         addi  24, 24, VG_(stats__n_xIndir_hits1_32)@l
496         lwz   25, 0(24)
497         addi  25, 25, 1
498         stw   25, 0(24)
499         // goto old .host1 a.k.a. new .host0
500         mtctr 23
501         bctr
502         /*NOTREACHED*/
504 2:      // try way 2
505         lwz   24, FCS_g2(26)
506         cmpw  24, 20   // cmp against .guest2
507         bne   3f
508         // hit at way 2; swap upwards
509         lwz   21, FCS_g1(26)
510         lwz   22, FCS_h1(26)
511         lwz   23, FCS_h2(26)
512         stw   20, FCS_g1(26)
513         stw   23, FCS_h1(26)
514         stw   21, FCS_g2(26)
515         stw   22, FCS_h2(26)
516         // stats only
517         lis   24,     VG_(stats__n_xIndir_hits2_32)@ha
518         addi  24, 24, VG_(stats__n_xIndir_hits2_32)@l
519         lwz   25, 0(24)
520         addi  25, 25, 1
521         stw   25, 0(24)
522         // goto old .host2 a.k.a. new .host1
523         mtctr 23
524         bctr
525         /*NOTREACHED*/
527 3:      // try way 3
528         lwz   24, FCS_g3(26)
529         cmpw  24, 20   // cmp against .guest3
530         bne   4f
531         // hit at way 3; swap upwards
532         lwz   21, FCS_g2(26)
533         lwz   22, FCS_h2(26)
534         lwz   23, FCS_h3(26)
535         stw   20, FCS_g2(26)
536         stw   23, FCS_h2(26)
537         stw   21, FCS_g3(26)
538         stw   22, FCS_h3(26)
539         // stats only
540         lis   24,     VG_(stats__n_xIndir_hits3_32)@ha
541         addi  24, 24, VG_(stats__n_xIndir_hits3_32)@l
542         lwz   25, 0(24)
543         addi  25, 25, 1
544         stw   25, 0(24)
545         // goto old .host3 a.k.a. new .host2
546         mtctr 23
547         bctr
548         /*NOTREACHED*/
550 4:      // fast lookup failed:
551         /* stats only */
552         lis   24,     VG_(stats__n_xIndir_misses_32)@ha
553         addi  24, 24, VG_(stats__n_xIndir_misses_32)@l
554         lwz   25, 0(24)
555         addi  25, 25, 1
556         stw   25, 0(24)
558         li    6, VG_TRC_INNER_FASTMISS
559         li    7, 0
560         b     postamble
561         /*NOTREACHED*/
563 /* ------ Assisted jump ------ */
564 .global VG_(disp_cp_xassisted)
565 VG_(disp_cp_xassisted):
566         /* r31 contains the TRC */
567         mr      6,31
568         li      7,0
569         b       postamble
571 /* ------ Event check failed ------ */
572 .global VG_(disp_cp_evcheck_fail)
573 VG_(disp_cp_evcheck_fail):
574         li      6,VG_TRC_INNER_COUNTERZERO
575         li      7,0
576         b       postamble
578         
579 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
581 #endif // defined(VGP_ppc32_linux)
583 /* Let the linker know we don't need an executable stack */
584 MARK_STACK_NO_EXEC
586 /*--------------------------------------------------------------------*/
587 /*--- end                                                          ---*/
588 /*--------------------------------------------------------------------*/