diff options
Diffstat (limited to 'libgcc/config/rs6000/tramp.S')
-rw-r--r-- | libgcc/config/rs6000/tramp.S | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/libgcc/config/rs6000/tramp.S b/libgcc/config/rs6000/tramp.S index 14cb18d..fe2a454 100644 --- a/libgcc/config/rs6000/tramp.S +++ b/libgcc/config/rs6000/tramp.S @@ -116,4 +116,70 @@ FUNC_END(__trampoline_setup) #endif +#elif _CALL_ELF == 2 + .type trampoline_initial,@object + .align 3 +trampoline_initial: + ld r11,.Lchain(r12) + ld r12,.Lfunc(r12) + mtctr r12 + bctr +.Lfunc = .-trampoline_initial + .quad 0 /* will be replaced with function address */ +.Lchain = .-trampoline_initial + .quad 0 /* will be replaced with static chain */ + +trampoline_size = .-trampoline_initial + .size trampoline_initial,trampoline_size + + +/* R3 = stack address to store trampoline */ +/* R4 = length of trampoline area */ +/* R5 = function address */ +/* R6 = static chain */ + + .pushsection ".toc","aw" +.LC0: + .quad trampoline_initial-8 + .popsection + +FUNC_START(__trampoline_setup) + addis 7,2,.LC0@toc@ha + ld 7,.LC0@toc@l(7) /* trampoline address -8 */ + + li r8,trampoline_size /* verify that the trampoline is big enough */ + cmpw cr1,r8,r4 + srwi r4,r4,3 /* # doublewords to move */ + addi r9,r3,-8 /* adjust pointer for stdu */ + mtctr r4 + blt cr1,.Labort + + /* Copy the instructions to the stack */ +.Lmove: + ldu r10,8(r7) + stdu r10,8(r9) + bdnz .Lmove + + /* Store correct function and static chain */ + std r5,.Lfunc(r3) + std r6,.Lchain(r3) + + /* Now flush both caches */ + mtctr r4 +.Lcache: + icbi 0,r3 + dcbf 0,r3 + addi r3,r3,8 + bdnz .Lcache + + /* Finally synchronize things & return */ + sync + isync + blr + +.Labort: + bl JUMP_TARGET(abort) + nop +FUNC_END(__trampoline_setup) + #endif |