Skip to content

Commit

Permalink
Support powerpc64le (gh-35).
Browse files Browse the repository at this point in the history
  • Loading branch information
yugr committed Mar 19, 2024
1 parent afa2f72 commit c07dac3
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 2 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,13 @@ jobs:
run: sudo apt-get update && sudo apt-get install qemu-user gcc-powerpc64-linux-gnu g++-powerpc64-linux-gnu binutils-powerpc64-linux-gnu libc6-ppc64-powerpc-cross libc6-dev-ppc64-powerpc-cross
- name: Run tests
run: scripts/travis.sh
powerpc64le:
runs-on: ubuntu-latest
env:
ARCH: powerpc64le-linux-gnu
steps:
- uses: actions/checkout@v3
- name: Install deps
run: sudo apt-get update && sudo apt-get install qemu-user gcc-powerpc64le-linux-gnu g++-powerpc64le-linux-gnu binutils-powerpc64le-linux-gnu libc6-ppc64el-cross libc6-dev-ppc64el-cross
- name: Run tests
run: scripts/travis.sh
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ where `TARGET` can be any of
* mipsel-linux-gnu
* mips64el-linux-gnuabi64
* e2k-linux-gnu
* powerpc64-linux-gnu (preliminary support)
* powerpc64-linux-gnu, powerpc64le-linux-gnu (preliminary support)

Script generates two files: `libxyz.so.tramp.S` and `libxyz.so.init.c` which need to be linked to your application (instead of `-lxyz`):

Expand Down
3 changes: 3 additions & 0 deletions arch/powerpc64le/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[Arch]
PointerSize = 8
SymbolReloc = R_PPC64_ADDR64
161 changes: 161 additions & 0 deletions arch/powerpc64le/table.S.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright 2024 Yury Gribov
*
* The MIT License (MIT)
*
* Use of this source code is governed by MIT license that can be
* found in the LICENSE.txt file.
*/

.machine power9
.abiversion 2

.section .note.GNU-stack,"",@progbits

.data

.globl _${lib_suffix}_tramp_table
.hidden _${lib_suffix}_tramp_table
.align 8
_${lib_suffix}_tramp_table:
.zero $table_size

.section ".toc","aw"
.align 3
.LC0:
.quad _${lib_suffix}_tramp_table

.section ".text"

.globl _${lib_suffix}_tramp_resolve
.hidden _${lib_suffix}_tramp_resolve

.globl _${lib_suffix}_save_regs_and_resolve
.hidden _${lib_suffix}_save_regs_and_resolve
.type _${lib_suffix}_save_regs_and_resolve, %function

_${lib_suffix}_save_regs_and_resolve:
.cfi_startproc
.LCF0:
addis 2, 12, .TOC. - .LCF0@ha
addi 2, 2, .TOC. - .LCF0@l
.localentry _${lib_suffix}_save_regs_and_resolve, . - _${lib_suffix}_save_regs_and_resolve

// Slow path which calls dlsym, taken only on first call.
// Registers are saved acc. to PPC64 ELF ABI
// For DWARF directives, read https://www.imperialviolet.org/2017/01/18/cfi.html.

mflr 0
std 0, 16(1)

ld 0, 48-8(1)

std 3, -8(1)
std 4, -16(1)
std 5, -24(1)
std 6, -32(1)
std 7, -40(1)
std 8, -48(1)
std 9, -56(1)
std 10, -64(1)

stfd 1, -72(1)
stfd 2, -80(1)
stfd 3, -88(1)
stfd 4, -96(1)
stfd 5, -104(1)
stfd 6, -112(1)
stfd 7, -120(1)
stfd 8, -128(1)
stfd 9, -136(1)
stfd 10, -144(1)
stfd 11, -152(1)
stfd 12, -160(1)
stfd 13, -168(1)

// TODO: also save Altivec registers

stdu 1, -256(1)

.cfi_def_cfa_offset 256
.cfi_offset r3, -8
.cfi_offset r4, -16
.cfi_offset r5, -24
.cfi_offset r6, -32
.cfi_offset r7, -40
.cfi_offset r8, -48
.cfi_offset r9, -56
.cfi_offset r10, -64
.cfi_offset f1, -72
.cfi_offset f2, -80
.cfi_offset f3, -88
.cfi_offset f4, -96
.cfi_offset f5, -104
.cfi_offset f6, -112
.cfi_offset f7, -120
.cfi_offset f8, -128
.cfi_offset f9, -136
.cfi_offset f10, -144
.cfi_offset f11, -152
.cfi_offset f12, -160
.cfi_offset f13, -168

mr 3, 0

bl _${lib_suffix}_tramp_resolve
nop

addi 1, 1, 256
.cfi_def_cfa_offset 0

ld 3, -8(1)
ld 4, -16(1)
ld 5, -24(1)
ld 6, -32(1)
ld 7, -40(1)
ld 8, -48(1)
ld 9, -56(1)
ld 10, -64(1)

lfd 1, -72(1)
lfd 2, -80(1)
lfd 3, -88(1)
lfd 4, -96(1)
lfd 5, -104(1)
lfd 6, -112(1)
lfd 7, -120(1)
lfd 8, -128(1)
lfd 9, -136(1)
lfd 10, -144(1)
lfd 11, -152(1)
lfd 12, -160(1)
lfd 13, -168(1)

ld 0, 16(1)
mtlr 0

.cfi_restore r3
.cfi_restore r4
.cfi_restore r5
.cfi_restore r6
.cfi_restore r7
.cfi_restore r8
.cfi_restore r9
.cfi_restore r10
.cfi_restore f1
.cfi_restore f2
.cfi_restore f3
.cfi_restore f4
.cfi_restore f5
.cfi_restore f6
.cfi_restore f7
.cfi_restore f8
.cfi_restore f9
.cfi_restore f10
.cfi_restore f11
.cfi_restore f12
.cfi_restore f13

blr

.cfi_endproc
79 changes: 79 additions & 0 deletions arch/powerpc64le/trampoline.S.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright 2024 Yury Gribov
*
* The MIT License (MIT)
*
* Use of this source code is governed by MIT license that can be
* found in the LICENSE.txt file.
*/

.globl $sym
.p2align 4
.type $sym, %function
#ifndef IMPLIB_EXPORT_SHIMS
.hidden $sym
#endif

$sym:
.cfi_startproc
.$sym.LCF0:
addis 2, 12, .TOC. - .$sym.LCF0@ha
addi 2, 2, .TOC. - .$sym.LCF0@l
.localentry $sym, . - $sym

1:
// Load address
addis 12, 2, .LC0@toc@ha
ld 12, .LC0@toc@l(12)
ld 12, $offset(12)

cmpdi 12, 0
beq 3f

2: // "Fast" path
// TODO: can we get rid of prologue/epilogue here?

mflr 0
std 0, 16(1)
stdu 1, -112(1)
.cfi_def_cfa_offset 112
.cfi_offset lr, 16

std 2, 24(1)

mtctr 12
bctrl

ld 2, 24(1)
addi 1, 1, 112
.cfi_def_cfa_offset 0
ld 0, 16(1)
mtlr 0
.cfi_restore lr
blr

3: // Slow path

mflr 0
std 0, 16(1)

li 0, $number
std 0, -8(1)

stdu 1, -48(1)
.cfi_def_cfa_offset 48
.cfi_offset lr, 16

bl _${lib_suffix}_save_regs_and_resolve
nop

addi 1, 1, 48
.cfi_def_cfa_offset 0

ld 0, 16(1)
mtlr 0
.cfi_restore lr

b 1b

.cfi_endproc
5 changes: 4 additions & 1 deletion implib-gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ def collect_syms(f):
syms_set = set()
for line in out.splitlines():
line = line.strip()
line = re.sub(r'\[<localentry>: [0-9]+\]', '', line) # Strip out strange markers in powerpc64le ELFs
if not line:
# Next symtab
toc = None
Expand Down Expand Up @@ -374,7 +375,7 @@ def main():
parser.add_argument('--target',
help="Target platform triple e.g. x86_64-unknown-linux-gnu or arm-none-eabi "
"(atm x86_64, i[0-9]86, arm/armhf/armeabi, aarch64/armv8, "
"mips/mipsel, mips64/mip64el, e2k and powerpc64 are supported)",
"mips/mipsel, mips64/mip64el, e2k, powerpc64/powerpc64le are supported)",
default=os.uname()[-1])
parser.add_argument('--symbol-list',
help="Path to file with symbols that should be present in wrapper "
Expand Down Expand Up @@ -406,6 +407,8 @@ def main():
target = 'mips64' # Handle mips64-..., mips64el-..., mips64le-...
elif args.target.startswith('mips'):
target = 'mips' # Handle mips-..., mipsel-..., mipsle-...
elif args.target.startswith('ppc64le'):
target = 'powerpc64le'
elif args.target.startswith('ppc64'):
target = 'powerpc64'
else:
Expand Down
5 changes: 5 additions & 0 deletions tests/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ else
PREFIX=powerpc64-linux-gnu-
INTERP="qemu-ppc64 -L /usr/powerpc64-linux-gnu -E LD_LIBRARY_PATH=.${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
;;
ppc64le | powerpc64le | powerpc64le-*)
TARGET=powerpc64le
PREFIX=powerpc64le-linux-gnu-
INTERP="qemu-ppc64le -L /usr/powerpc64le-linux-gnu -E LD_LIBRARY_PATH=.${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
;;
*)
echo >&2 "Unsupported target: $ARCH"
exit 1
Expand Down

0 comments on commit c07dac3

Please sign in to comment.