Home | History | Annotate | Download | only in m_dispatch
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
      4 /*---                                        dispatch-ppc32-aix5.S ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8   This file is part of Valgrind, a dynamic binary instrumentation
      9   framework.
     10 
     11   Copyright (C) 2006-2010 OpenWorks LLP
     12      info (at) open-works.co.uk
     13 
     14   This program is free software; you can redistribute it and/or
     15   modify it under the terms of the GNU General Public License as
     16   published by the Free Software Foundation; either version 2 of the
     17   License, or (at your option) any later version.
     18 
     19   This program is distributed in the hope that it will be useful, but
     20   WITHOUT ANY WARRANTY; without even the implied warranty of
     21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22   General Public License for more details.
     23 
     24   You should have received a copy of the GNU General Public License
     25   along with this program; if not, write to the Free Software
     26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     27   02111-1307, USA.
     28 
     29   The GNU General Public License is contained in the file COPYING.
     30 
     31   Neither the names of the U.S. Department of Energy nor the
     32   University of California nor the names of its contributors may be
     33   used to endorse or promote products derived from this software
     34   without prior written permission.
     35 */
     36 
     37 #if defined(VGP_ppc32_aix5)
     38 
     39 #include "pub_core_basics_asm.h"
     40 #include "pub_core_dispatch_asm.h"
     41 #include "pub_core_transtab_asm.h"
     42 #include "libvex_guest_offsets.h"	/* for OFFSET_ppc32_CIA */
     43 
     44 
     45 /*------------------------------------------------------------*/
     46 /*---                                                      ---*/
     47 /*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
     48 /*--- run all translations except no-redir ones.           ---*/
     49 /*---                                                      ---*/
     50 /*------------------------------------------------------------*/
     51 
     52 /*----------------------------------------------------*/
     53 /*--- Incomprehensible TOC mumbo-jumbo nonsense.   ---*/
     54 /*----------------------------------------------------*/
     55 
     56 /* No, I don't have a clue either.  I just compiled a bit of
     57    C with gcc and copied the assembly code it produced. */
     58 
     59 /* Basically "lwz rd, tocent__foo(2)" gets &foo into rd. */
     60 
     61     .file       "dispatch-ppc32-aix5.S"
     62     .machine	"any"
     63     .toc
     64     .csect .text[PR]
     65     .toc
     66 tocent__vgPlain_dispatch_ctr:
     67     .tc vgPlain_dispatch_ctr[TC],vgPlain_dispatch_ctr[RW]
     68 tocent__vgPlain_machine_ppc32_has_VMX:
     69     .tc vgPlain_machine_ppc32_has_VMX[TC],vgPlain_machine_ppc32_has_VMX[RW]
     70 tocent__vgPlain_machine_ppc32_has_FP:
     71     .tc vgPlain_machine_ppc32_has_FP[TC],vgPlain_machine_ppc32_has_FP[RW]
     72 tocent__vgPlain_tt_fast:
     73     .tc vgPlain_tt_fast[TC],vgPlain_tt_fast[RW]
     74 tocent__vgPlain_tt_fastN:
     75     .tc vgPlain_tt_fast[TC],vgPlain_tt_fastN[RW]
     76     .csect .text[PR]
     77     .align 2
     78     .globl vgPlain_run_innerloop
     79     .globl .vgPlain_run_innerloop
     80     .csect vgPlain_run_innerloop[DS]
     81 vgPlain_run_innerloop:
     82     .long .vgPlain_run_innerloop, TOC[tc0], 0
     83     .csect .text[PR]
     84 
     85 /*----------------------------------------------------*/
     86 /*--- Preamble (set everything up)                 ---*/
     87 /*----------------------------------------------------*/
     88 
     89 /* signature:
     90 UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
     91 */
     92 .vgPlain_run_innerloop:
     93 	/* r3 holds guest_state */
     94 	/* r4 holds do_profiling */
     95 	/* Rather than attempt to make sense of the AIX ABI, just
     96            drop r1 by 256 (to get away from the caller's frame), then
     97 	   512 (to give ourselves a 512-byte save area), and then
     98 	   another 256 (to clear our save area).  In all, drop r1 by 1024
     99 	   and dump stuff on the stack at 256(1)..768(1).  */
    100 
    101         /* ----- entry point to VG_(run_innerloop) ----- */
    102         /* For AIX/ppc32 we do:	 LR-> +8(parent_sp), CR-> +4(parent_sp) */
    103 
    104         /* Save lr and cr*/
    105         mflr    0
    106         stw     0,8(1)
    107 	mfcr	0
    108 	stw	0,4(1)
    109 
    110         /* New stack frame */
    111         stwu    1,-1024(1)  /* sp should maintain 16-byte alignment */
    112 
    113         /* Save callee-saved registers... */
    114 	/* r3, r4 are live here, so use r5 */
    115         lwz     5,tocent__vgPlain_machine_ppc32_has_FP(2)
    116         lwz     5,0(5)
    117         cmplwi  5,0
    118         beq     LafterFP1
    119 
    120         /* Floating-point reg save area : 144 bytes at r1[256..399] */
    121         stfd    31,392(1)
    122         stfd    30,384(1)
    123         stfd    29,376(1)
    124         stfd    28,368(1)
    125         stfd    27,360(1)
    126         stfd    26,352(1)
    127         stfd    25,344(1)
    128         stfd    24,336(1)
    129         stfd    23,328(1)
    130         stfd    22,320(1)
    131         stfd    21,312(1)
    132         stfd    20,304(1)
    133         stfd    19,296(1)
    134         stfd    18,288(1)
    135         stfd    17,280(1)
    136         stfd    16,272(1)
    137         stfd    15,264(1)
    138         stfd    14,256(1)
    139 LafterFP1:
    140 
    141         /* General reg save area : 76 bytes at r1[400 .. 475] */
    142         stw     31,472(1)
    143         stw     30,468(1)
    144         stw     29,464(1)
    145         stw     28,460(1)
    146         stw     27,456(1)
    147         stw     26,452(1)
    148         stw     25,448(1)
    149         stw     24,444(1)
    150         stw     23,440(1)
    151         stw     22,436(1)
    152         stw     21,432(1)
    153         stw     20,428(1)
    154         stw     19,424(1)
    155         stw     18,420(1)
    156         stw     17,416(1)
    157         stw     16,412(1)
    158         stw     15,408(1)
    159         stw     14,404(1)
    160         /* Probably not necessary to save r13 (thread-specific ptr),
    161            as VEX stays clear of it... but what the hell. */
    162         stw     13,400(1)
    163 
    164         /* It's necessary to save/restore VRSAVE in the AIX / Darwin ABI.
    165            The Linux kernel might not actually use VRSAVE for its intended
    166            purpose, but it should be harmless to preserve anyway. */
    167 	/* r3, r4 are live here, so use r5 */
    168         lwz     5,tocent__vgPlain_machine_ppc32_has_VMX(2)
    169         lwz     5,0(5)
    170         cmplwi  5,0
    171         beq     LafterVMX1
    172 
    173 //	Sigh.  AIX 5.2 has no idea that Altivec exists.
    174 //        /* VRSAVE save word : 4 bytes at r1[476 .. 479] */
    175 //        mfspr   5,256        /* vrsave reg is spr number 256 */
    176 //        stw     5,476(1)
    177 //
    178 //        /* Vector reg save area (quadword aligned):
    179 //	   192 bytes at r1[480 .. 671] */
    180 //        li      5,656
    181 //        stvx    31,5,1
    182 //        li      5,640
    183 //        stvx    30,5,1
    184 //        li      5,624
    185 //        stvx    29,5,1
    186 //        li      5,608
    187 //        stvx    28,5,1
    188 //        li      5,592
    189 //        stvx    27,5,1
    190 //        li      5,576
    191 //        stvx    26,5,1
    192 //        li      5,560
    193 //        stvx    25,5,1
    194 //        li      5,544
    195 //        stvx    25,5,1
    196 //        li      5,528
    197 //        stvx    23,5,1
    198 //        li      5,512
    199 //        stvx    22,5,1
    200 //        li      5,496
    201 //        stvx    21,5,1
    202 //        li      5,480
    203 //        stvx    20,5,1
    204 LafterVMX1:
    205 
    206         /* Local variable space... */
    207 	/* Put the original guest state pointer at r1[128].  We
    208            will need to refer to it each time round the dispatch loop.
    209 	   Apart from that, we can use r1[0 .. 128] and r1[132 .. 255]
    210 	   as scratch space. */
    211 
    212         /* r3 holds guest_state */
    213         /* r4 holds do_profiling */
    214         mr      31,3      /* r31 (generated code gsp) = r3 */
    215         stw     3,128(1)  /* stash orig guest_state ptr */
    216 
    217         /* hold dispatch_ctr in r29 */
    218         lwz     5,tocent__vgPlain_dispatch_ctr(2)
    219         lwz     29,0(5)
    220 
    221         /* set host FPU control word to the default mode expected
    222            by VEX-generated code.  See comments in libvex.h for
    223            more info. */
    224         lwz     5,tocent__vgPlain_machine_ppc32_has_FP(2)
    225         lwz     5,0(5)
    226         cmplwi  5,0
    227         beq     LafterFP2
    228 
    229         /* get zero into f3 (tedious) */
    230         /* note: fsub 3,3,3 is not a reliable way to do this,
    231            since if f3 holds a NaN or similar then we don't necessarily
    232            wind up with zero. */
    233         li      5,0
    234         stw     5,64(1)	/* r1[64] is scratch */
    235         lfs     3,64(1)
    236         mtfsf   0xFF,3   /* fpscr = f3 */
    237 LafterFP2:
    238 
    239         /* set host AltiVec control word to the default mode expected
    240            by VEX-generated code. */
    241         lwz     5,tocent__vgPlain_machine_ppc32_has_VMX(2)
    242         lwz     5,0(5)
    243         cmplwi  5,0
    244         beq     LafterVMX2
    245 
    246 //	Sigh.  AIX 5.2 has no idea that Altivec exists.
    247 //        vspltisw 3,0x0  /* generate zero */
    248 //        mtvscr  3
    249 LafterVMX2:
    250 
    251         /* fetch %CIA into r3 */
    252         lwz     3,OFFSET_ppc32_CIA(31)
    253 
    254         /* fall into main loop (the right one) */
    255 	/* r4 = do_profiling.  It's probably trashed after here,
    256            but that's OK: we don't need it after here. */
    257 	cmplwi	4,0
    258 	beq	VG_(run_innerloop__dispatch_unprofiled)
    259 	b	VG_(run_innerloop__dispatch_profiled)
    260 	/*NOTREACHED*/
    261 
    262 /*----------------------------------------------------*/
    263 /*--- NO-PROFILING (standard) dispatcher           ---*/
    264 /*----------------------------------------------------*/
    265 
    266 .globl VG_(run_innerloop__dispatch_unprofiled)
    267 VG_(run_innerloop__dispatch_unprofiled):
    268 	/* At entry: Live regs:
    269 		r1  (=sp)
    270 		r3  (=CIA = next guest address)
    271 		r29 (=dispatch_ctr)
    272 		r31 (=guest_state)
    273 	   Stack state:
    274 		128(r1) (=orig guest_state)
    275 	*/
    276 
    277 	/* Has the guest state pointer been messed with?  If yes, exit.
    278 	   Also set up & VG_(tt_fast) early in an attempt at better
    279            scheduling. */
    280         lwz     5,128(1)         /* original guest_state ptr */
    281         cmpw    5,31
    282 	lwz	5,tocent__vgPlain_tt_fast(2)	/* r5 = &tt_fast */
    283         bne	gsp_changed
    284 
    285         /* save the jump address in the guest state */
    286         stw     3,OFFSET_ppc32_CIA(31)
    287 
    288         /* Are we out of timeslice?  If yes, defer to scheduler. */
    289 	addi	29,29,-1
    290 	cmplwi	29,0
    291         beq	counter_is_zero
    292 
    293         /* try a fast lookup in the translation cache */
    294         /* r4 = VG_TT_FAST_HASH(addr)           * sizeof(FastCacheEntry)
    295               = ((r3 >>u 2) & VG_TT_FAST_MASK)  << 3 */
    296         rlwinm  4,3,1, 29-VG_TT_FAST_BITS, 28   /* entry# * 8 */
    297 	add     5,5,4	 /* & VG_(tt_fast)[entry#] */
    298 	lwz     6,0(5)   /* .guest */
    299 	lwz     7,4(5)   /* .host */
    300         cmpw    3,6
    301         bne     fast_lookup_failed
    302 
    303         /* Found a match.  Call .host. */
    304         mtctr   7
    305         bctrl
    306 
    307         /* On return from guest code:
    308 	   r3  holds destination (original) address.
    309            r31 may be unchanged (guest_state), or may indicate further
    310            details of the control transfer requested to *r3.
    311         */
    312 	/* start over */
    313 	b	VG_(run_innerloop__dispatch_unprofiled)
    314 	/*NOTREACHED*/
    315 
    316 /*----------------------------------------------------*/
    317 /*--- PROFILING dispatcher (can be much slower)    ---*/
    318 /*----------------------------------------------------*/
    319 
    320 .globl VG_(run_innerloop__dispatch_profiled)
    321 VG_(run_innerloop__dispatch_profiled):
    322 	/* At entry: Live regs:
    323 		r1  (=sp)
    324 		r3  (=CIA = next guest address)
    325 		r29 (=dispatch_ctr)
    326 		r31 (=guest_state)
    327 	   Stack state:
    328 		128(r1) (=orig guest_state)
    329 	*/
    330 	/* Has the guest state pointer been messed with?  If yes, exit.
    331 	   Also set up & VG_(tt_fast) early in an attempt at better
    332            scheduling. */
    333         lwz     5,128(1)         /* original guest_state ptr */
    334         cmpw    5,31
    335 	lwz	5,tocent__vgPlain_tt_fast(2)	/* r5 = &tt_fast */
    336         bne	gsp_changed
    337 
    338         /* save the jump address in the guest state */
    339         stw     3,OFFSET_ppc32_CIA(31)
    340 
    341         /* Are we out of timeslice?  If yes, defer to scheduler. */
    342 	addi	29,29,-1
    343 	cmplwi	29,0
    344         beq	counter_is_zero
    345 
    346         /* try a fast lookup in the translation cache */
    347         /* r4 = VG_TT_FAST_HASH(addr)           * sizeof(FastCacheEntry)
    348               = ((r3 >>u 2) & VG_TT_FAST_MASK)  << 3 */
    349         rlwinm  4,3,1, 29-VG_TT_FAST_BITS, 28   /* entry# * 8 */
    350 	add     5,5,4	 /* & VG_(tt_fast)[entry#] */
    351 	lwz     6,0(5)   /* .guest */
    352 	lwz     7,4(5)   /* .host */
    353         cmpw    3,6
    354         bne     fast_lookup_failed
    355 
    356         /* increment bb profile counter */
    357 	srwi	4,4,1   /* entry# * sizeof(UInt*) */
    358 	lwz	9,tocent__vgPlain_tt_fastN(2)   /* r9 = &tt_fastN */
    359         lwzx    8,9,4   /* r7 = tt_fastN[r4] */
    360         lwz     10,0(8)
    361         addi    10,10,1
    362         stw     10,0(8)
    363 
    364         /* Found a match.  Call .host. */
    365         mtctr   7
    366         bctrl
    367 
    368         /* On return from guest code:
    369 	   r3  holds destination (original) address.
    370            r31 may be unchanged (guest_state), or may indicate further
    371            details of the control transfer requested to *r3.
    372         */
    373 	/* start over */
    374 	b	VG_(run_innerloop__dispatch_unprofiled)
    375 	/*NOTREACHED*/
    376 
    377 
    378 /*----------------------------------------------------*/
    379 /*--- exit points                                  ---*/
    380 /*----------------------------------------------------*/
    381 
    382 gsp_changed:
    383 	/* Someone messed with the gsp (in r31).  Have to
    384            defer to scheduler to resolve this.  dispatch ctr
    385 	   is not yet decremented, so no need to increment. */
    386 	/* %CIA is NOT up to date here.  First, need to write
    387 	   %r3 back to %CIA, but without trashing %r31 since
    388 	   that holds the value we want to return to the scheduler.
    389 	   Hence use %r5 transiently for the guest state pointer. */
    390         lwz     5,128(1)        /* original guest_state ptr */
    391         stw     3,OFFSET_ppc32_CIA(5)
    392 	mr	3,31		/* r3 = new gsp value */
    393 	b	run_innerloop_exit
    394 	/*NOTREACHED*/
    395 
    396 counter_is_zero:
    397 	/* %CIA is up to date */
    398 	/* back out decrement of the dispatch counter */
    399         addi    29,29,1
    400         li      3,VG_TRC_INNER_COUNTERZERO
    401         b       run_innerloop_exit
    402 
    403 fast_lookup_failed:
    404 	/* %CIA is up to date */
    405 	/* back out decrement of the dispatch counter */
    406         addi    29,29,1
    407         li      3,VG_TRC_INNER_FASTMISS
    408 	b       run_innerloop_exit
    409 
    410 
    411 
    412 /* All exits from the dispatcher go through here.
    413    r3 holds the return value.
    414 */
    415 run_innerloop_exit:
    416         /* We're leaving.  Check that nobody messed with
    417            VSCR or FPSCR. */
    418 
    419         /* Using r10 - value used again further on, so don't trash! */
    420         lwz     10,tocent__vgPlain_machine_ppc32_has_FP(2)
    421         lwz     10,0(10)
    422         cmplwi  10,0
    423         beq     LafterFP8
    424 
    425 	/* Set fpscr back to a known state, since vex-generated code
    426 	   may have messed with fpscr[rm]. */
    427         li      5,0
    428         stw     5,64(1)	 /* r1[64] is scratch */
    429         lfs     3,64(1)
    430         mtfsf   0xFF,3   /* fpscr = f3 */
    431 LafterFP8:
    432 
    433 	/* Using r11 - value used again further on, so don't trash! */
    434         lwz     11,tocent__vgPlain_machine_ppc32_has_VMX(2)
    435         lwz     11,0(11)
    436         cmplwi  11,0
    437         beq     LafterVMX8
    438 
    439 //	Sigh.  AIX 5.2 has no idea that Altivec exists.
    440 //        /* Check VSCR[NJ] == 1 */
    441 //        /* first generate 4x 0x00010000 */
    442 //        vspltisw  4,0x1                   /* 4x 0x00000001 */
    443 //        vspltisw  5,0x0                   /* zero */
    444 //        vsldoi    6,4,5,0x2               /* <<2*8 => 4x 0x00010000 */
    445 //        /* retrieve VSCR and mask wanted bits */
    446 //        mfvscr    7
    447 //        vand      7,7,6                   /* gives NJ flag */
    448 //        vspltw    7,7,0x3                 /* flags-word to all lanes */
    449 //        vcmpequw. 8,6,7                   /* CR[24] = 1 if v6 == v7 */
    450 //        bt        24,invariant_violation  /* branch if all_equal */
    451 LafterVMX8:
    452 
    453 	/* otherwise we're OK */
    454         b       run_innerloop_exit_REALLY
    455 
    456 
    457 invariant_violation:
    458         li      3,VG_TRC_INVARIANT_FAILED
    459         b       run_innerloop_exit_REALLY
    460 
    461 run_innerloop_exit_REALLY:
    462         /* r3 holds VG_TRC_* value to return */
    463 
    464         /* Write ctr to VG(dispatch_ctr) */
    465         lwz     5,tocent__vgPlain_dispatch_ctr(2)
    466         stw     29,0(5)
    467 
    468         /* Restore callee-saved registers... */
    469 
    470         /* r10 already holds VG_(machine_ppc32_has_FP) value */
    471         cmplwi  10,0
    472         beq     LafterFP9
    473 
    474         /* Floating-point regs */
    475         lfd     31,392(1)
    476         lfd     30,384(1)
    477         lfd     29,376(1)
    478         lfd     28,368(1)
    479         lfd     27,360(1)
    480         lfd     26,352(1)
    481         lfd     25,344(1)
    482         lfd     24,336(1)
    483         lfd     23,328(1)
    484         lfd     22,320(1)
    485         lfd     21,312(1)
    486         lfd     20,304(1)
    487         lfd     19,296(1)
    488         lfd     18,288(1)
    489         lfd     17,280(1)
    490         lfd     16,272(1)
    491         lfd     15,264(1)
    492         lfd     14,256(1)
    493 LafterFP9:
    494 
    495         /* General regs */
    496         lwz     31,472(1)
    497         lwz     30,468(1)
    498         lwz     29,464(1)
    499         lwz     28,460(1)
    500         lwz     27,456(1)
    501         lwz     26,452(1)
    502         lwz     25,448(1)
    503         lwz     24,444(1)
    504         lwz     23,440(1)
    505         lwz     22,436(1)
    506         lwz     21,432(1)
    507         lwz     20,428(1)
    508         lwz     19,424(1)
    509         lwz     18,420(1)
    510         lwz     17,416(1)
    511         lwz     16,412(1)
    512         lwz     15,408(1)
    513         lwz     14,404(1)
    514         lwz     13,400(1)
    515 
    516         /* r11 already holds VG_(machine_ppc32_has_VMX) value */
    517         cmplwi  11,0
    518         beq     LafterVMX9
    519 
    520 //       Sigh.  AIX 5.2 has no idea that Altivec exists.
    521 //        /* VRSAVE */
    522 //        lwz     4,476(1)
    523 //        mtspr   4,256         /* VRSAVE reg is spr number 256 */
    524 //
    525 //        /* Vector regs */
    526 //        li      4,656
    527 //        lvx     31,4,1
    528 //        li      4,640
    529 //        lvx     30,4,1
    530 //        li      4,624
    531 //        lvx     29,4,1
    532 //        li      4,608
    533 //        lvx     28,4,1
    534 //        li      4,592
    535 //        lvx     27,4,1
    536 //        li      4,576
    537 //        lvx     26,4,1
    538 //        li      4,560
    539 //        lvx     25,4,1
    540 //        li      4,544
    541 //        lvx     24,4,1
    542 //        li      4,528
    543 //        lvx     23,4,1
    544 //        li      4,512
    545 //        lvx     22,4,1
    546 //        li      4,496
    547 //        lvx     21,4,1
    548 //        li      4,480
    549 //        lvx     20,4,1
    550 LafterVMX9:
    551 
    552 	/* r3 is live here; don't trash it */
    553         /* restore lr,cr,sp */
    554 	addi	4,1,1024  /* r4 = old SP */
    555 	lwz	0,8(4)
    556 	mtlr	0
    557 	lwz	0,4(4)
    558 	mtcr	0
    559 	mr	1,4
    560 	blr
    561 
    562 LT..vgPlain_run_innerloop:
    563     .long 0
    564     .byte 0,0,32,64,0,0,2,0
    565     .long 0
    566     .long LT..vgPlain_run_innerloop-.vgPlain_run_innerloop
    567     .short 13
    568     .byte "vgPlain_run_innerloop"
    569     .align 2
    570 _section_.text:
    571     .csect .data[RW],3
    572     .long _section_.text
    573 
    574 /*------------------------------------------------------------*/
    575 /*---                                                      ---*/
    576 /*--- A special dispatcher, for running no-redir           ---*/
    577 /*--- translations.  Just runs the given translation once. ---*/
    578 /*---                                                      ---*/
    579 /*------------------------------------------------------------*/
    580 
    581 /* signature:
    582 void VG_(run_a_noredir_translation) ( UWord* argblock );
    583 */
    584 
    585 /* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
    586    and 2 to carry results:
    587       0: input:  ptr to translation
    588       1: input:  ptr to guest state
    589       2: output: next guest PC
    590       3: output: guest state pointer afterwards (== thread return code)
    591 */
    592 .csect .text[PR]
    593 .align 2
    594 .globl  .VG_(run_a_noredir_translation)
    595 .VG_(run_a_noredir_translation):
    596 
    597 	/* Rather than attempt to make sense of the AIX ABI, just
    598            drop r1 by 256 (to get away from the caller's frame), then
    599 	   512 (to give ourselves a 512-byte save area), and then
    600 	   another 256 (to clear our save area).  In all, drop r1 by 1024
    601 	   and dump stuff on the stack at 256(1)..768(1).  */
    602 	/* At entry, r3 points to argblock */
    603 
    604         /* ----- entry point to VG_(run_innerloop) ----- */
    605         /* For AIX/ppc32 we do:	 LR-> +8(parent_sp), CR-> +4(parent_sp) */
    606 
    607         /* Save lr and cr*/
    608         mflr    0
    609         stw     0,8(1)
    610 	mfcr	0
    611 	stw	0,4(1)
    612 
    613         /* New stack frame */
    614         stwu    1,-1024(1)  /* sp should maintain 16-byte alignment */
    615 
    616         /* General reg save area : 76 bytes at r1[400 .. 475] */
    617         stw     31,472(1)
    618         stw     30,468(1)
    619         stw     29,464(1)
    620         stw     28,460(1)
    621         stw     27,456(1)
    622         stw     26,452(1)
    623         stw     25,448(1)
    624         stw     24,444(1)
    625         stw     23,440(1)
    626         stw     22,436(1)
    627         stw     21,432(1)
    628         stw     20,428(1)
    629         stw     19,424(1)
    630         stw     18,420(1)
    631         stw     17,416(1)
    632         stw     16,412(1)
    633         stw     15,408(1)
    634         stw     14,404(1)
    635         stw     13,400(1)
    636 	stw	3,396(1)	/* will need it later */
    637 
    638         lwz     31,4(3)		/* rd argblock[1] */
    639         lwz     30,0(3)		/* rd argblock[0] */
    640         mtlr    30		/* run translation */
    641         blrl
    642 
    643         lwz     4,396(1)	/* &argblock */
    644         stw     3,  8(4)	/* wr argblock[2] */
    645         stw     31,12(4)	/* wr argblock[3] */
    646 
    647         /* General regs */
    648         lwz     31,472(1)
    649         lwz     30,468(1)
    650         lwz     29,464(1)
    651         lwz     28,460(1)
    652         lwz     27,456(1)
    653         lwz     26,452(1)
    654         lwz     25,448(1)
    655         lwz     24,444(1)
    656         lwz     23,440(1)
    657         lwz     22,436(1)
    658         lwz     21,432(1)
    659         lwz     20,428(1)
    660         lwz     19,424(1)
    661         lwz     18,420(1)
    662         lwz     17,416(1)
    663         lwz     16,412(1)
    664         lwz     15,408(1)
    665         lwz     14,404(1)
    666         lwz     13,400(1)
    667 
    668         /* restore lr,cr,sp */
    669 	addi	4,1,1024  /* r4 = old SP */
    670 	lwz	0,8(4)
    671 	mtlr	0
    672 	lwz	0,4(4)
    673 	mtcr	0
    674 	mr	1,4
    675 	blr
    676 
    677 #endif // defined(VGP_ppc32_aix5)
    678 
    679 /*--------------------------------------------------------------------*/
    680 /*--- end                                                          ---*/
    681 /*--------------------------------------------------------------------*/
    682