xen: refactor the various "version not supported" messages into a single helper
[valgrind.git] / coregrind / m_dispatch / dispatch-ppc32-linux.S
blob770a05882f77ed39d6d0fd7cc28268709e9f2cee
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-2013 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, write to the Free Software
25   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26   02111-1307, USA.
28   The GNU General Public License is contained in the file COPYING.
31 #if defined(VGP_ppc32_linux)
33 #include "config.h"
34 #include "pub_core_basics_asm.h"
35 #include "pub_core_dispatch_asm.h"
36 #include "pub_core_transtab_asm.h"
37 #include "libvex_guest_offsets.h"       /* for OFFSET_ppc32_CIA */
40 /*------------------------------------------------------------*/
41 /*---                                                      ---*/
42 /*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
43 /*--- used to run all translations,                        ---*/
44 /*--- including no-redir ones.                             ---*/
45 /*---                                                      ---*/
46 /*------------------------------------------------------------*/
48 /*----------------------------------------------------*/
49 /*--- Entry and preamble (set everything up)       ---*/
50 /*----------------------------------------------------*/
52 /* signature:
53 void VG_(disp_run_translations)( UWord* two_words,
54                                  void*  guest_state,
55                                  Addr   host_addr );
57 .text
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 */
65         /* ----- entry point to VG_(disp_run_translations) ----- */
66         /* For Linux/ppc32 we need the SysV ABI, which uses
67            LR->4(parent_sp), CR->anywhere.
68            (The AIX ABI, used on Darwin,
69            uses LR->8(prt_sp), CR->4(prt_sp))
70         */
72         /* Save lr */
73         mflr    6
74         stw     6,4(1)
76         /* New stack frame */
77         stwu    1,-496(1)  /* sp should maintain 16-byte alignment */
79         /* Save callee-saved registers... */
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
84         beq     LafterFP1
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)
105 LafterFP1:
107         /* General reg save area : 76 bytes */
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)
126         stw     13,276(1)
127         stw     3,272(1)  /* save two_words for later */
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. */
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
136         beq     LafterVMX1
138 #ifdef HAS_ALTIVEC
139         /* VRSAVE save word : 32 bytes */
140         mfspr   6,256         /* vrsave reg is spr number 256 */
141         stw     6,244(1)
143         /* Alignment padding : 4 bytes */
145         /* Vector reg save area (quadword aligned) : 192 bytes */
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
161         stvx    25,6,1
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
170 #endif
171         
172 LafterVMX1:
174         /* Save cr */
175         mfcr    6
176         stw     6,44(1)
178         /* Local variable space... */
180         /* 32(sp) used later to check FPSCR[RM] */
182         /* r3 holds two_words */
183         /* r4 holds guest_state */
184         /* r5 holds host_addr */
186         /* 24(sp) used later to stop ctr reg being clobbered */
187         /* 20(sp) used later to load fpscr with zero */
188         /* 8:16(sp) free */
189         
190         /* Linkage Area (reserved)
191            4(sp)  : LR
192            0(sp)  : back-chain
193         */
195         /* set host FPU control word to the default mode expected 
196            by VEX-generated code.  See comments in libvex.h for
197            more info. */
198         lis     6,VG_(machine_ppc32_has_FP)@ha
199         lwz     6,VG_(machine_ppc32_has_FP)@l(6)
200         cmplwi  6,0
201         beq     LafterFP2
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. */
207         li      6,0
208         stw     6,20(1)
209         lfs     3,20(1)
210         mtfsf   0xFF,3   /* fpscr = f3 */
211 LafterFP2:
213         /* set host AltiVec control word to the default mode expected 
214            by VEX-generated code. */
215         lis     6,VG_(machine_ppc32_has_VMX)@ha
216         lwz     6,VG_(machine_ppc32_has_VMX)@l(6)
217         cmplwi  6,0
218         beq     LafterVMX2
220 #ifdef HAS_ALTIVEC
221         vspltisw 3,0x0  /* generate zero */
222         mtvscr  3
223 #endif
224         
225 LafterVMX2:
227         /* make a stack frame for the code we are calling */
228         stwu    1,-16(1)
230         /* Set up the guest state ptr */
231         mr      31,4      /* r31 (generated code gsp) = r4 */
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
240         /*NOTREACHED*/
242 /*----------------------------------------------------*/
243 /*--- Postamble and exit.                          ---*/
244 /*----------------------------------------------------*/
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.) */
253         /* We're leaving.  Check that nobody messed with
254            VSCR or FPSCR in ways we don't expect. */
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)
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)
263         cmplwi  10,0    /* Do we have FP ? */
264         beq     LafterFP8
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 */
274 LafterFP8:
276         cmplwi  11,0    /* Do we have altivec? */
277         beq     LafterVMX8
279 #ifdef HAS_ALTIVEC
280         /* Check VSCR[NJ] == 1 */
281         /* first generate 4x 0x00010000 */
282         vspltisw  4,0x1                   /* 4x 0x00000001 */
283         vspltisw  5,0x0                   /* zero */
284         vsldoi    6,4,5,0x2               /* <<2*8 => 4x 0x00010000 */
285         /* retrieve VSCR and mask wanted bits */
286         mfvscr    7
287         vand      7,7,6                   /* gives NJ flag */
288         vspltw    7,7,0x3                 /* flags-word to all lanes */
289         vcmpequw. 8,6,7                   /* CR[24] = 1 if v6 == v7 */
290         bt        24,invariant_violation  /* branch if all_equal */
291 #endif
293 LafterVMX8:
294         /* otherwise we're OK */
295         b       remove_frame
297 invariant_violation:
298         li      6,VG_TRC_INVARIANT_FAILED
299         li      7,0
300         /* fall through */
302 remove_frame:
303         /* Restore FP regs */
304         /* r10 already holds VG_(machine_ppc32_has_FP) value */
305         cmplwi  10,0
306         beq     LafterFP9
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)
327 LafterFP9:
329         /* r11 already holds VG_(machine_ppc32_has_VMX) value */
330         cmplwi  11,0
331         beq     LafterVMX9
333         /* Restore Altivec regs */
334 #ifdef HAS_ALTIVEC
335         /* VRSAVE */
336         lwz     4,244(1)
337         mfspr   4,256         /* VRSAVE reg is spr number 256 */
339         /* Vector regs */
340         li      4,224
341         lvx     31,4,1
342         li      4,208
343         lvx     30,4,1
344         li      4,192
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
364 #endif
365 LafterVMX9:
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)
393         /* restore lr & sp, and leave */
394         lwz     0,500(1)  /* stack_size + 4 */
395         mtlr    0
396         addi    1,1,496   /* stack_size */
397         blr
400 /*----------------------------------------------------*/
401 /*--- Continuation points                          ---*/
402 /*----------------------------------------------------*/
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
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
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)
442         /* stats only */
443         lis     5,VG_(stats__n_xindirs_32)@ha
444         addi    5,5,VG_(stats__n_xindirs_32)@l
445         lwz     6,0(5)
446         addi    6,6,1
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) */
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
463         /* Found a match.  Jump to .host. */
464         mtctr   7
465         bctr
467 fast_lookup_failed:
468         /* stats only */
469         lis     5,VG_(stats__n_xindir_misses_32)@ha
470         addi    5,5,VG_(stats__n_xindir_misses_32)@l
471         lwz     6,0(5)
472         addi    6,6,1
473         stw     6,0(5)
475         li      6,VG_TRC_INNER_FASTMISS
476         li      7,0
477         b       postamble
478         /*NOTREACHED*/
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
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
495         
496 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
498 /* Let the linker know we don't need an executable stack */
499 .section .note.GNU-stack,"",@progbits
501 #endif // defined(VGP_ppc32_linux)
503 /*--------------------------------------------------------------------*/
504 /*--- end                                                          ---*/
505 /*--------------------------------------------------------------------*/