diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/sysdep.h')
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/sysdep.h | 111 |
1 files changed, 96 insertions, 15 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/sysdep.h b/sysdeps/unix/sysv/linux/powerpc/sysdep.h index 577809acb8..944793d56f 100644 --- a/sysdeps/unix/sysv/linux/powerpc/sysdep.h +++ b/sysdeps/unix/sysv/linux/powerpc/sysdep.h @@ -31,32 +31,113 @@ #ifdef ASSEMBLER -#define ENTRY(name) \ - .globl name; \ - .type name,@function; \ - .align 2; \ +/* This seems to always be the case on PPC. */ +#define ALIGNARG(log2) log2 +/* For ELF we need the `.type' directive to make shared libs work right. */ +#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; +#define ASM_SIZE_DIRECTIVE(name) .size name,.-name + +/* If compiled for profiling, call `_mcount' at the start of each function. */ +#ifdef PROF +/* The mcount code relies on a the return address being on the stack + to locate our caller and so it can restore it; so store one just + for its benefit. */ +#ifdef PIC +#define CALL_MCOUNT \ + .pushsection; \ + .section ".data"; \ + .align ALIGNARG(2); \ +0:.long 0; \ + .previous; \ + mflr %r0; \ + stw %r0,4(%r1); \ + bl _GLOBAL_OFFSET_TABLE_@local-4; \ + mflr %r11; \ + lwz %r0,0b@got(%r11); \ + bl JUMPTARGET(_mcount); +#else /* PIC */ +#define CALL_MCOUNT \ + .section ".data"; \ + .align ALIGNARG(2); \ +0:.long 0; \ + .previous; \ + mflr %r0; \ + lis %r11,0b@ha; \ + stw %r0,4(%r1); \ + addi %r0,%r11,0b@l; \ + bl JUMPTARGET(_mcount); +#endif /* PIC */ +#else /* PROF */ +#define CALL_MCOUNT /* Do nothing. */ +#endif /* PROF */ + +#define ENTRY(name) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + CALL_MCOUNT + +#define EALIGN_W_0 /* No words to insert. */ +#define EALIGN_W_1 nop +#define EALIGN_W_2 nop;nop +#define EALIGN_W_3 nop;nop;nop +#define EALIGN_W_4 EALIGN_W_3;nop +#define EALIGN_W_5 EALIGN_W_4;nop +#define EALIGN_W_6 EALIGN_W_5;nop +#define EALIGN_W_7 EALIGN_W_6;nop + +/* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes + past a 2^align boundary. */ +#ifdef PROF +#define EALIGN(name, alignt, words) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(2); \ + C_LABEL(name) \ + CALL_MCOUNT \ + b 0f; \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ + 0: +#else /* PROF */ +#define EALIGN(name, alignt, words) \ + ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ + ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ C_LABEL(name) +#endif + +#undef END +#define END(name) \ + ASM_SIZE_DIRECTIVE(name) #define DO_CALL(syscall) \ li 0,syscall; \ sc #ifdef PIC +#define JUMPTARGET(name) name##@plt +#else +#define JUMPTARGET(name) name +#endif + #define PSEUDO(name, syscall_name, args) \ .section ".text"; \ ENTRY (name) \ - DO_CALL (SYS_ify (syscall_name)); \ + DO_CALL (SYS_ify (syscall_name)); + +#define PSEUDO_RET \ bnslr; \ - b __syscall_error@plt -#else -#define PSEUDO(name, syscall_name, args) \ - .section ".text"; \ - ENTRY (name) \ - DO_CALL (SYS_ify (syscall_name)); \ - bnslr; \ - b __syscall_error -#endif + b JUMPTARGET(__syscall_error) +#define ret PSEUDO_RET + +#undef PSEUDO_END +#define PSEUDO_END(name) \ + END (name) -#define ret /* Nothing (should be 'blr', but never reached). */ +/* Local labels stripped out by the linker. */ +#define L(x) .L##x #endif /* ASSEMBLER */ |