changeset 7:7ca57dbefed4

- ppc64 update from Masanori
author cslag
date Sun, 19 Jul 2015 13:05:34 +0200
parents b8ea1d2a34a3
children d2a8d50a59b6 a996f29affdf
files ChangeLog README doc/manual/callconvs/callconv_ppc64.tex dyncall/dyncall.h dyncall/dyncall_call_ppc64.S dyncall/dyncall_callvm_ppc64.c dyncall/dyncall_value.h dyncallback/dyncall_callback_ppc64.S dyncallback/dyncall_thunk_ppc64.c dyncallback/dyncall_thunk_ppc64.h portasm/portasm-ppc64.S test/callback_plain/callback_plain.c test/callback_suite/handler.c
diffstat 13 files changed, 359 insertions(+), 233 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Thu Jul 09 20:51:11 2015 +0200
+++ b/ChangeLog	Sun Jul 19 13:05:34 2015 +0200
@@ -3,7 +3,7 @@
 Version 0.9 (upcoming)
 dyncall:
   o ARM64 support (AAPCS64 on Linux, Apple's derived version on iOS)
-  o PPC64 support (thanks Masanori!)
+  o PPC64 support, including syscalls (thanks Masanori!)
   o introduced dcArgF and dcVArgF for flexible/convenient argument binding (works like dcCallF/dcVCallF but without the function call)
   o added -fPIC by default for FreeBSD
   o PPC32 linux syscall support
--- a/README	Thu Jul 09 20:51:11 2015 +0200
+++ b/README	Sun Jul 19 13:05:34 2015 +0200
@@ -10,7 +10,7 @@
  - 'dynload' for loading code.
 
 The package provides abstractions to the Application Binary Interface 
-of various hardware platforms such as x86, AMD64, ARM32/64, PowerPCC32/64,
+of various hardware platforms such as x86, AMD64, ARM32/64, PowerPC32/64,
 MIPS32/64 and SPARC32/64.
 
 Our releases are thoroughly tested across all supported platforms using a
--- a/doc/manual/callconvs/callconv_ppc64.tex	Thu Jul 09 20:51:11 2015 +0200
+++ b/doc/manual/callconvs/callconv_ppc64.tex	Sun Jul 19 13:05:34 2015 +0200
@@ -34,7 +34,7 @@
 
 \paragraph{\product{dyncall} support}
 
-\product{Dyncall} supports PowerPC (64bit) Big Endian and Little Endian ELF ABIs on System V systems (Linux, etc.). Mac OS X is not supported.
+\product{Dyncall} supports PowerPC (64bit) Big Endian and Little Endian ELF ABIs on System V systems (Linux, etc.), including syscalls. Mac OS X is not supported.
 
 
 \subsubsection{PPC64 ELF ABI}
--- a/dyncall/dyncall.h	Thu Jul 09 20:51:11 2015 +0200
+++ b/dyncall/dyncall.h	Sun Jul 19 13:05:34 2015 +0200
@@ -29,6 +29,7 @@
   dyncall C API
 
   REVISION
+  2015/07/08 added SYS_PPC64 system call
   2015/01/16 added SYS_PPC32 system call
   2007/12/11 initial
   
@@ -83,6 +84,7 @@
 #define DC_CALL_SYS_X86_INT80H_LINUX  201
 #define DC_CALL_SYS_X86_INT80H_BSD    202
 #define DC_CALL_SYS_PPC32             210
+#define DC_CALL_SYS_PPC64             211
 
 /* Error codes. */
 
--- a/dyncall/dyncall_call_ppc64.S	Thu Jul 09 20:51:11 2015 +0200
+++ b/dyncall/dyncall_call_ppc64.S	Sun Jul 19 13:05:34 2015 +0200
@@ -23,7 +23,7 @@
 */
 
 
-#include "../portasm/portasm-ppc.S"
+#include "../portasm/portasm-ppc64.S"
 
 /*
   Call Kernel Implementations for PowerPC64.
@@ -37,6 +37,7 @@
      dcCall_ppc64(DCpointer target, struct DCRegData* pRegData, DCsize stacksize, DCptr stackdata);
    
   ChangeLog:
+  2015-07-08: Added support for system calls
   2014-08-07: Initial Support
 
 */
@@ -60,7 +61,6 @@
    - Parameter Area (min. v1:64 Bytes v2:0 Byte)
    - Frame Header Area (v1:48 Bytes v2:32 Bytes)
 
-
    Frame structure:
 
      on entry, parent frame layout:
@@ -92,25 +92,9 @@
 #endif
 
 .text
-	.global dcCall_ppc64
-	.type dcCall_ppc64, @function
-#if DC__ABI_PPC64_ELF_V != 2
-	.section .opd, "aw"
-	.align 3
-#endif
-
-dcCall_ppc64:
-#if DC__ABI_PPC64_ELF_V != 2
-	.quad .dcCall_ppc64, .TOC.@tocbase, 0
-	.previous
-	.global .dcCall_ppc64
-
-.dcCall_ppc64:
-#else
-0:	addis r2, r12,.TOC.-0b@ha
-	addi  r2, r2,.TOC.-0b@l
-	.localentry dcCall_ppc64,.-dcCall_ppc64
-#endif
+.align 2
+GLOBAL_C(dcCall_ppc64)
+ENTRY_C(dcCall_ppc64)
 	mflr r0                 /* r0 = return address */
 	std  r0,16(r1)          /* store r0 to link-area */
 	std  r31,-8(r1)
@@ -195,3 +179,32 @@
 	mtlr r0                 /* setup link register */
 	blr                     /* return */
 
+.align 2
+GLOBAL_C(dcCall_ppc64_syscall)
+ENTRY_C(dcCall_ppc64_syscall)
+	mflr r0                 /* r0 = return address */
+	std  r0,16(r1)          /* store r0 to link-area */
+	std  r31,-8(r1)
+	li   r0, -STACK_MIN
+	stdux r1,r1,r0          /* store r1 and decrement */
+
+	mr   r0, r3             /* r0 = syscall number ( passed as 'target function' ) */
+	mr   r11, r4            /* r11 = reg data */
+
+	/* load 5 integer registers */
+	ld  r3 , 0(r11)
+	ld  r4 , 8(r11)
+	ld  r5 ,16(r11)
+	ld  r6 ,24(r11)
+	ld  r7 ,32(r11)
+	
+	sc                    /* system call */
+
+	/* epilog */
+
+	ld   r2,TOC_SAVE(r1)
+	ld   r1, 0(r1)          /* restore stack */
+	ld   r31,-8(r1)
+	ld   r0,16(r1)          /* r0 = return address */
+	mtlr r0                 /* setup link register */
+	blr                     /* return */
--- a/dyncall/dyncall_callvm_ppc64.c	Thu Jul 09 20:51:11 2015 +0200
+++ b/dyncall/dyncall_callvm_ppc64.c	Sun Jul 19 13:05:34 2015 +0200
@@ -29,8 +29,10 @@
 
   SUPPORTED CALLING CONVENTIONS
   ppc64/linux
+  ppc64/syscall
 
   REVISION
+  2015/07/08 added syscall
   2014/08/07 initial support
 
 */
@@ -209,6 +211,12 @@
   dcCall_ppc64( target, &self->mRegData, dcVecSize(&self->mVecHead) , dcVecData(&self->mVecHead));
 }
 
+void dc_callvm_call_ppc64_syscall(DCCallVM* in_self, DCpointer target)
+{
+  DCCallVM_ppc64* self = (DCCallVM_ppc64*) in_self;
+  dcCall_ppc64_syscall( target, &self->mRegData, dcVecSize(&self->mVecHead) , dcVecData(&self->mVecHead));
+}
+
 void dc_callvm_mode_ppc64(DCCallVM* in_self, DCint mode);
 
 DCCallVM_vt gVT_ppc64 =
@@ -269,6 +277,34 @@
 };
 #endif
 
+DCCallVM_vt gVT_ppc64_syscall =
+{
+  &dc_callvm_free_ppc64
+, &dc_callvm_reset_ppc64
+, &dc_callvm_mode_ppc64
+, &dc_callvm_argBool_ppc64
+, &dc_callvm_argChar_ppc64
+, &dc_callvm_argShort_ppc64
+, &dc_callvm_argInt_ppc64
+, &dc_callvm_argLong_ppc64
+, &dc_callvm_argLongLong_ppc64
+, &dc_callvm_argFloat_ppc64
+, &dc_callvm_argDouble_ppc64
+, &dc_callvm_argPointer_ppc64
+, NULL /* argStruct */
+, (DCvoidvmfunc*)       &dc_callvm_call_ppc64_syscall
+, (DCboolvmfunc*)       &dc_callvm_call_ppc64_syscall
+, (DCcharvmfunc*)       &dc_callvm_call_ppc64_syscall
+, (DCshortvmfunc*)      &dc_callvm_call_ppc64_syscall
+, (DCintvmfunc*)        &dc_callvm_call_ppc64_syscall
+, (DClongvmfunc*)       &dc_callvm_call_ppc64_syscall
+, (DClonglongvmfunc*)   &dc_callvm_call_ppc64_syscall
+, (DCfloatvmfunc*)      &dc_callvm_call_ppc64_syscall
+, (DCdoublevmfunc*)     &dc_callvm_call_ppc64_syscall
+, (DCpointervmfunc*)    &dc_callvm_call_ppc64_syscall
+, NULL /* callStruct */
+};
+
 void dc_callvm_mode_ppc64(DCCallVM* in_self, DCint mode)
 {
   DCCallVM_ppc64* self = (DCCallVM_ppc64*) in_self;
@@ -290,6 +326,11 @@
       break;
 #endif
 
+    case DC_CALL_SYS_DEFAULT:
+    case DC_CALL_SYS_PPC64:
+      vt = &gVT_ppc64_syscall;
+      break;
+
     default: 
       self->mInterface.mError = DC_ERROR_UNSUPPORTED_MODE; 
       return;
--- a/dyncall/dyncall_value.h	Thu Jul 09 20:51:11 2015 +0200
+++ b/dyncall/dyncall_value.h	Sun Jul 19 13:05:34 2015 +0200
@@ -48,20 +48,31 @@
 
 union DCValue_
 {
+#if defined (DC__Arch_PPC32) && defined(DC__Endian_BIG)
   DCbool        B;
-#if defined (DC__Arch_PPC32) && defined(DC__Endian_BIG)
   struct { DCchar  c_pad[3]; DCchar  c; };
   struct { DCuchar C_pad[3]; DCuchar C; };
   struct { DCshort s_pad;    DCshort s; };
   struct { DCshort S_pad;    DCshort S; };
+  DCint         i;
+  DCuint        I;
+#elif defined (DC__Arch_PPC64) && defined(DC__Endian_BIG)
+  struct { DCbool  B_pad;    DCbool  B; };
+  struct { DCchar  c_pad[7]; DCchar  c; };
+  struct { DCuchar C_pad[7]; DCuchar C; };
+  struct { DCshort s_pad[3]; DCshort s; };
+  struct { DCshort S_pad[3]; DCshort S; };
+  struct { DCint   i_pad;    DCint   i; };
+  struct { DCint   I_pad;    DCuint  I; };
 #else
+  DCbool        B;
   DCchar        c;
   DCuchar       C;
   DCshort       s;
   DCushort      S;
-#endif
   DCint         i;
   DCuint        I;
+#endif
   DClong        j;
   DCulong       J;
   DClonglong    l;
--- a/dyncallback/dyncall_callback_ppc64.S	Thu Jul 09 20:51:11 2015 +0200
+++ b/dyncallback/dyncall_callback_ppc64.S	Sun Jul 19 13:05:34 2015 +0200
@@ -22,150 +22,121 @@
 
 */
 
-#include "../portasm/portasm-ppc.S"
-
-/* Callback Thunk Entry code for PowerPC 64-bit. */
-
-/* Stack Frame Layout: 
-
-	296 DCValue ( 8 )
-	112 DCArgs ( 64+104+8+4+4 = 184 )
-	 48 Parameter area ( 8*8 = 64 )
-	  0 Linkage area   ( 48 )
-
-
-*/
-
-/* Constants. */
-INT_REGS    = 8
-FLOAT_REGS  = 13
-SIZEOF_GPR  = 8
-SIZEOF_FPR  = 8
+#include "../portasm/portasm-ppc64.S"
 
-/* Linkage area. */
-LINK_SP     = 0
-LINK_CR     = 8
-LINK_LR     = 16
-LINK_OFFSET = 0
-#if DC__ABI_PPC64_ELF_V == 2
-LINK_TOC    = 24
-LINK_SIZE   = 32
-#else
-LINK_TOC    = 40
-LINK_SIZE   = 48
-#endif
-/* Parameter area. */
-PAR_OFFSET = LINK_SIZE
-#if DC__ABI_PPC64_ELF_V == 2
-PAR_SIZE = 0
-#else
-PAR_SIZE = 64
-#endif 
-/* local struct DCArgs */
-ARGS_OFFSET = (PAR_OFFSET+PAR_SIZE)
-ARGS_SIZE   = (SIZEOF_GPR*INT_REGS)+(SIZEOF_FPR*FLOAT_REGS) + 8 + 4 * 4 
-/* local struct DCValue */
-RESULT_OFFSET = (ARGS_OFFSET+ARGS_SIZE)
-RESULT_SIZE   = 8
-/* additional locals (reg 30/31) */
-LOCALS_OFFSET = (RESULT_OFFSET+RESULT_SIZE)
-LOCALS_SIZE   = 2*SIZEOF_GPR
-/* total */
-FRAME_SIZE = ( (LOCALS_OFFSET+LOCALS_SIZE)+15 & (-16) )
+.text
+.align 2
 
 /* struct DCCallback */
-#if DC__ABI_PPC64_ELF_V == 2
-DCB_THUNK      = 0
+
+#if DC__ABI_PPC64_ELF_V != 2
+DCB_THUNK      = 0    /* v1 */
+DCB_HANDLER    = 64
+DCB_STACKCLEAN = 72
+DCB_USERDATA   = 80
+#else
+DCB_THUNK      = 0    /* v2 */
 DCB_HANDLER    = 48
 DCB_STACKCLEAN = 56
 DCB_USERDATA   = 64
-#else
-DCB_THUNK      = 0
-DCB_HANDLER    = 64
-DCB_STACKCLEAN = 72
-DCB_USERDATA   = 80
 #endif
 
 /* struct DCArgs */
-DCA_IARRAY = 0
-DCA_FARRAY = SIZEOF_GPR*INT_REGS
-DCA_SP     = DCA_FARRAY + SIZEOF_FPR*FLOAT_REGS
-DCA_ICOUNT = DCA_SP + 8
-DCA_FCOUNT = DCA_ICOUNT + 4
+
+ARGS_IREGS     = 0
+ARGS_FREGS     = ARGS_IREGS + 8*8
+ARGS_SP        = ARGS_FREGS + 8*13
+ARGS_ICNT      = ARGS_SP    + 8
+ARGS_FCNT      = ARGS_ICNT  + 4
+ARGS_SIZE      = ARGS_FCNT  + 4
 
 /* struct DCValue */
-DCV_INT   = 0
-DCV_FLOAT = 0
-DCV_SIZE  = 8
+
+RESULT_SIZE    = 8
+
+/* Stack Offsets */
 
-iregfile = ARGS_OFFSET+DCA_IARRAY
-fregfile = ARGS_OFFSET+DCA_FARRAY
-save_sp  = ARGS_OFFSET+DCA_SP
-icount   = ARGS_OFFSET+DCA_ICOUNT
-fcount   = ARGS_OFFSET+DCA_FCOUNT
+SP_PREV        = 0
+SP_CR          = SP_PREV + 8
+SP_LR          = SP_CR   + 8
+#if DC__ABI_PPC64_ELF_V != 2
+SP_TOC         = 40
+SP_PAR         = 48
+PAR_SZ         = 64
+#else
+SP_TOC         = 24
+SP_PAR         = 32
+PAR_SZ         = 0
+#endif
+SP_ARGS        = SP_PAR    + PAR_SZ
+SP_IREGS       = SP_ARGS   + ARGS_IREGS
+SP_FREGS       = SP_ARGS   + ARGS_FREGS
+SP_SP          = SP_ARGS   + ARGS_SP
+SP_ICNT        = SP_ARGS   + ARGS_ICNT
+SP_FCNT        = SP_ARGS   + ARGS_FCNT
+SP_RESULT      = SP_ARGS   + ARGS_SIZE
+SP_LOCAL       = SP_RESULT + RESULT_SIZE  /* additional locals (reg 30/31) */ 
+SP_SIZE        = SP_LOCAL  + 2*8
 
-/* 
-  Thunk entry:
-  R2 = DCCallback*
+#define ALIGN(M,X) ( M+(X-1) & (-X) )
+
+FRAMESIZE = ALIGN(SP_SIZE,16)
+
+GLOBAL_C(dcCallbackThunkEntry)
+ENTRY_C(dcCallbackThunkEntry)
+
+/* --------------------------------------------------------------------------
+
+Input:
+        r1      Stack Pointer            
+        r3-r10  Integer Arguments        
+        f1-f8   Floating-point Arguments 
+        r11     Thunk Pointer            
+
 */
-.text
-	.global dcCallbackThunkEntry
-	.type dcCallbackThunkEntry, @function
-#if DC__ABI_PPC64_ELF_V != 2
-	.section .opd, "aw"
-	.align 3
-#endif
 
-dcCallbackThunkEntry:
-#if DC__ABI_PPC64_ELF_V != 2
-	.quad .dcCallbackThunkEntry, .TOC.@tocbase, 0
-	.previous
-	.global .dcCallbackThunkEntry
-
-.dcCallbackThunkEntry:
-#endif
 	mflr    r0
-	std     r0,  16(r1)           /* store return address */
-	std     r31, -8(r1)           /* store preserved registers (r31) */
-	addi    r12, r1, PAR_OFFSET   /* temporary r12 = parameter area on callers stack frame */
-	stdu    r1, -FRAME_SIZE(r1)   /* save callers stack pointer and make new stack frame. */
+	std     r0,  SP_LR(r1)         /* store return address */
+	std     r31, -8(r1)            /* store preserved registers (r31) */
+	addi    r12, r1, SP_PAR        /* temporary r12 = parameter area on callers stack frame */
+	stdu    r1, -FRAMESIZE(r1)     /* save callers stack pointer and make new stack frame. */
 
-	std     r3, iregfile+0*8(r1)  /* spill 8 integer parameter registers */
-	std     r4, iregfile+1*8(r1)
-	std     r5, iregfile+2*8(r1)
-	std     r6, iregfile+3*8(r1)
-	std     r7, iregfile+4*8(r1)
-	std     r8, iregfile+5*8(r1)
-	std     r9, iregfile+6*8(r1)
-	std     r10,iregfile+7*8(r1)
-	stfd    f1, fregfile+ 0*8(r1) /* spill 13 float parameter registers */
-	stfd    f2, fregfile+ 1*8(r1)
-	stfd    f3, fregfile+ 2*8(r1)
-	stfd    f4, fregfile+ 3*8(r1)
-	stfd    f5, fregfile+ 4*8(r1)
-	stfd    f6, fregfile+ 5*8(r1)
-	stfd    f7, fregfile+ 6*8(r1)
-	stfd    f8, fregfile+ 7*8(r1)
-	stfd    f9, fregfile+ 8*8(r1)
-	stfd    f10,fregfile+ 9*8(r1)
-	stfd    f11,fregfile+10*8(r1)
-	stfd    f12,fregfile+11*8(r1)
-	stfd    f13,fregfile+12*8(r1)
+	std     r3, SP_IREGS + 0*8(r1) /* spill 8 integer parameter registers */
+	std     r4, SP_IREGS + 1*8(r1)
+	std     r5, SP_IREGS + 2*8(r1)
+	std     r6, SP_IREGS + 3*8(r1)
+	std     r7, SP_IREGS + 4*8(r1)
+	std     r8, SP_IREGS + 5*8(r1)
+	std     r9, SP_IREGS + 6*8(r1)
+	std     r10,SP_IREGS + 7*8(r1)
+	stfd    f1, SP_FREGS + 0*8(r1) /* spill 13 float parameter registers */
+	stfd    f2, SP_FREGS + 1*8(r1)
+	stfd    f3, SP_FREGS + 2*8(r1)
+	stfd    f4, SP_FREGS + 3*8(r1)
+	stfd    f5, SP_FREGS + 4*8(r1)
+	stfd    f6, SP_FREGS + 5*8(r1)
+	stfd    f7, SP_FREGS + 6*8(r1)
+	stfd    f8, SP_FREGS + 7*8(r1)
+	stfd    f9, SP_FREGS + 8*8(r1)
+	stfd    f10,SP_FREGS + 9*8(r1)
+	stfd    f11,SP_FREGS +10*8(r1)
+	stfd    f12,SP_FREGS +11*8(r1)
+	stfd    f13,SP_FREGS +12*8(r1)
 	                        /* initialize struct DCCallback */
-	std     r12,save_sp(r1) /* init stack pointer */
+	std     r12,SP_SP(r1)   /* init stack pointer */
 	xor     r0, r0, r0      /* init register counters */
-	std     r0, icount(r1)
-	std     r0, fcount(r1)
-	std     r0, RESULT_OFFSET(r1)
+	std     r0, SP_ICNT(r1)
+	std     r0, SP_FCNT(r1)
+	std     r0, SP_RESULT(r1)      /* init result object */ 
 	                               /* invoke callback handler */
-	mr      r3, r11                /* arg 1: DCCallback* pcb  */
-	addi    r4, r1, ARGS_OFFSET    /* arg 2: DCArgs* args     */
-	addi    r5, r1, RESULT_OFFSET  /* arg 3: DCValue* result  */
+	mr      r3, r11                /* arg 1: DCCallback* pcb (r11 is thunk pointer) */
+	addi    r4, r1, SP_ARGS        /* arg 2: DCArgs* args     */
+	addi    r5, r1, SP_RESULT      /* arg 3: DCValue* result  */
 	ld      r6, DCB_USERDATA(r11)  /* arg 4: void* userdata   */
 
 	/* branch-and-link to DCCallback.handler */
 	ld      r12,  DCB_HANDLER(r11)
-	std     r2, LINK_TOC(r1)
+	std     r2, SP_TOC(r1)
 #if DC__ABI_PPC64_ELF_V != 2
 	ld      r2, 8(r12)
 	ld      r0, 0(r12)
@@ -175,41 +146,25 @@
 #endif
 	bctrl
 
-	addi    r0, r1, RESULT_OFFSET /* r0 = DCValue* */
-	                              /* switch on base result type */
-	cmpi    cr0, r3, 'B
-	beq     .i64
-	cmpi    cr0, r3, 'i
-	beq     .i64
-	cmpi    cr0, r3, 'c
-	beq     .i64
-	cmpi    cr0, r3, 's
-	beq     .i64
-	cmpi    cr0, r3, 'l
-	beq     .i64
+	/* check result type */
 	cmpi    cr0, r3, 'f
 	beq     .f32
 	cmpi    cr0, r3, 'd
 	beq     .f64
-	cmpi    cr0, r3, 'p
-	beq     .i64
-.void: /* ignore result (void call) */
-	b       .end
-.i64:  /* result is 64-bit long long result */
-	ld       r3, RESULT_OFFSET + DCV_INT(r1)
-	b       .end
-.f32:  /* result is C float result */
-	lfs       f1, RESULT_OFFSET + DCV_FLOAT(r1)
-	b       .end
-.f64:  /* result is C double result */
-	lfd       f1, RESULT_OFFSET + DCV_FLOAT(r1)
+.i64:
+	ld      r3, SP_RESULT(r1)
 	b       .end
 .end:
 
-	ld     r2,  LINK_TOC(r1)
-	ld     r1,  0(r1)  /* restore stack pointer */
-	ld     r31, -8(r1) /* restore preserved registers */
-	ld     r0,  16(r1) /* load link register with return address */
+	ld     r2,  SP_TOC(r1)
+	ld     r1,  SP_PREV(r1)  /* restore stack pointer */
+	ld     r31, -8(r1)       /* restore preserved registers */
+	ld     r0,  SP_LR(r1)    /* load link register with return address */
 	mtlr   r0
-	blr                /* branch back to link register */
- 
+	blr                      /* branch back to link register */
+.f32:
+	lfs       f1, SP_RESULT(r1)
+	b       .end
+.f64:
+	lfd       f1, SP_RESULT(r1)
+	b       .end
--- a/dyncallback/dyncall_thunk_ppc64.c	Thu Jul 09 20:51:11 2015 +0200
+++ b/dyncallback/dyncall_thunk_ppc64.c	Sun Jul 19 13:05:34 2015 +0200
@@ -31,9 +31,34 @@
 
 void dcbInitThunk(DCThunk* p, void (*entry)())
 {
-#if DC__ABI_PPC64_ELF_V == 2
+#if DC__ABI_PPC64_ELF_V != 2
   /*
-    ppc64 thunk code:
+    ppc64 thunk code:                (v1)
+      oris   r11, r2, HI16(p)
+      ori    r11,r11, LO16(p)
+      ld     r12,48(r11)
+      ld     r2,56(r11)
+      mtctr r12
+      bctr
+  */
+
+  p->thunk_entry  = (void *)&(p->code_load_hi);
+  p->toc_thunk    = ((long)(p->thunk_entry) & 0xffffffff00000000UL);
+
+  p->code_load_hi = 0x644bU;     /* oris  r11, r2, HI16(p) */
+  p->addr_self_hi = HI16(p);
+  p->code_load_lo = 0x616bU; 	 /* ori   r11,r11, LO16(p) */
+  p->addr_self_lo = LO16(p);
+  p->code_jump[0] = 0xe98b0030U; /* ld    r12,48(r11) */
+  p->code_jump[1] = 0xe84b0038U; /* ld    r2,56(r11) */
+  p->code_jump[2] = 0x7d8903a6U; /* mtclr r12 */
+  p->code_jump[3] = 0x4e800420U; /* bctr */
+  p->addr_entry   = (void *)*((long *)entry);
+  p->toc_entry    = *((long *)(entry + 8));
+
+#else
+  /*
+    ppc64 thunk code:                (v2)
       lis    r11, HIST16(p)
       ori    r11,r11, HIER16(p)
       rldicr r11,r11,32,31
@@ -57,31 +82,6 @@
   p->code_jump[1]   = 0x7d8903a6U; /* mtclr  r12 */
   p->code_jump[2]   = 0x4e800420U; /* bctr */
   p->addr_entry     = (void *)(entry);
-
-#else
-  /*
-    ppc64 thunk code:
-      oris   r11, r2, HI16(p)
-      ori    r11,r11, LO16(p)
-      ld     r12,48(r11)
-      ld     r2,56(r11)
-      mtctr r12
-      bctr
-  */
-
-  p->thunk_entry  = (void *)&(p->code_load_hi);
-  p->toc_thunk    = ((long)(p->thunk_entry) & 0xffffffff00000000UL);
-
-  p->code_load_hi = 0x644bU;     /* oris  r11, r2, HI16(p) */
-  p->addr_self_hi = HI16(p);
-  p->code_load_lo = 0x616bU; 	 /* ori   r11,r11, LO16(p) */
-  p->addr_self_lo = LO16(p);
-  p->code_jump[0] = 0xe98b0030U; /* ld    r12,48(r11) */
-  p->code_jump[1] = 0xe84b0038U; /* ld    r2,56(r11) */
-  p->code_jump[2] = 0x7d8903a6U; /* mtclr r12 */
-  p->code_jump[3] = 0x4e800420U; /* bctr */
-  p->addr_entry   = (void *)*((long *)entry);
-  p->toc_entry    = *((long *)(entry + 8));
 #endif
 }
 
--- a/dyncallback/dyncall_thunk_ppc64.h	Thu Jul 09 20:51:11 2015 +0200
+++ b/dyncallback/dyncall_thunk_ppc64.h	Sun Jul 19 13:05:34 2015 +0200
@@ -25,8 +25,20 @@
 #ifndef DYNCALL_THUNK_PPC64_H
 #define DYNCALL_THUNK_PPC64_H
 
-#if DC__ABI_PPC64_ELF_V == 2
-struct DCThunk_
+#if DC__ABI_PPC64_ELF_V != 2
+struct DCThunk_              /* v1 */
+{
+  void          (*thunk_entry)();                 /* offset:  0 */
+  long           toc_thunk;                       /* offset:  8 */
+  unsigned short code_load_hi, addr_self_hi;      /* offset: 16 */
+  unsigned short code_load_lo, addr_self_lo;      /* offset: 20 */
+  unsigned int   code_jump[6];                    /* offset: 24 */
+  void          (*addr_entry)();                  /* offset: 48 */
+  long           toc_entry;                       /* offset: 56 */
+};
+#define DCTHUNK_SIZE_PPC64 64
+#else
+struct DCThunk_              /* v2 */
 {
   unsigned short addr_self_hist, code_load_hist;  /* offset:  0 */
   unsigned short addr_self_hier, code_load_hier;  /* offset:  4 */
@@ -37,18 +49,6 @@
   void          (*addr_entry)();                  /* offset: 40 */
 };
 #define DCTHUNK_SIZE_PPC64 48
-#else
-struct DCThunk_
-{
-  void          (*thunk_entry)();                 /* offset:  0 */
-  long           toc_thunk;                       /* offset:  8 */
-  unsigned short code_load_hi, addr_self_hi;      /* offset: 16 */
-  unsigned short code_load_lo, addr_self_lo;      /* offset: 20 */
-  unsigned int   code_jump[6];                    /* offset: 24 */
-  void          (*addr_entry)();                  /* offset: 48 */
-  long           toc_entry;                       /* offset: 56 */
-};
-#define DCTHUNK_SIZE_PPC64 64
 #endif
 
 #endif /* DYNCALL_THUNK_PPC64_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/portasm/portasm-ppc64.S	Sun Jul 19 13:05:34 2015 +0200
@@ -0,0 +1,119 @@
+/*
+
+ Package: dyncall
+ Library: portasm
+ File: portasm/portasm-ppc64.S
+ Description: Portable Assembler Macros for ppc64
+ License:
+
+   Copyright (c) 2014-2015 Masanori Mitsugi <mitsugi@linux.vnet.ibm.com>
+
+   Permission to use, copy, modify, and distribute this software for any
+   purpose with or without fee is hereby granted, provided that the above
+   copyright notice and this permission notice appear in all copies.
+
+   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+
+#include "../autovar/autovar_OS.h"
+
+#if DC__ABI_PPC64_ELF_V != 2  /* v1 */
+#define GLOBAL_C(X) \
+.global X; \
+.type X, @function; \
+.section .opd, "aw"; \
+.align 3;
+#else                         /* v2 */
+#define GLOBAL_C(X) \
+.global X; \
+.type X, @function;
+#endif
+
+#if DC__ABI_PPC64_ELF_V != 2  /* v1 */
+#define ENTRY_C(X) \
+X: \
+.quad .X, .TOC.@tocbase, 0; \
+.previous; \
+.global .X; \
+.X:
+#else                         /* v2 */
+#define ENTRY_C(X) \
+X: \
+0: \
+addis r2, r12,.TOC.-0b@ha; \
+addi  r2, r2,.TOC.-0b@l; \
+.localentry X,.-X;
+#endif
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
+#define f0 0
+#define f1 1
+#define f2 2
+#define f3 3
+#define f4 4
+#define f5 5
+#define f6 6
+#define f7 7
+#define f8 8
+#define f9 9
+#define f10 10
+#define f11 11
+#define f12 12
+#define f13 13
+#define f14 14
+#define f15 15
+#define f16 16
+#define f17 17
+#define f18 18
+#define f19 19
+#define f20 20
+#define f21 21
+#define f22 22
+#define f23 23
+#define f24 24
+#define f25 25
+#define f26 26
+#define f27 27
+#define f28 28
+#define f29 29
+#define f30 30
+#define f31 31
--- a/test/callback_plain/callback_plain.c	Thu Jul 09 20:51:11 2015 +0200
+++ b/test/callback_plain/callback_plain.c	Sun Jul 19 13:05:34 2015 +0200
@@ -52,6 +52,7 @@
   if(arg3 ==    3) ++*ud;
   if(arg4 == 1.82) ++*ud;
   if(arg5 == 9909) ++*ud;
+
   result->s = 1234;
   return 's';
 }
--- a/test/callback_suite/handler.c	Thu Jul 09 20:51:11 2015 +0200
+++ b/test/callback_suite/handler.c	Sun Jul 19 13:05:34 2015 +0200
@@ -65,22 +65,6 @@
   /* currently, no void result is supported by the suite */
   GetReferenceResult(output, ch);
 
-#if defined(DC__Arch_PPC64) && defined(DC__Endian_BIG)
-  switch (ch) {
-    case DC_SIGCHAR_BOOL:     output->l = ((long long)output->B); break;
-    case DC_SIGCHAR_CHAR:     output->l = ((long long)output->c); break;
-    case DC_SIGCHAR_UCHAR:    output->l = ((long long)output->C); break;
-    case DC_SIGCHAR_SHORT:    output->l = ((long long)output->s); break;
-    case DC_SIGCHAR_USHORT:   output->l = ((long long)output->S); break;
-    case DC_SIGCHAR_INT:      output->l = ((long long)output->i); break;
-    case DC_SIGCHAR_UINT:     output->l = ((long long)output->I); break;
-    case DC_SIGCHAR_LONG:     output->l = ((long long)output->j); break;
-    case DC_SIGCHAR_ULONG:    output->l = ((long long)output->J); break;
-    case DC_SIGCHAR_ULONGLONG:output->l = ((long long)output->L); break;
-    case DC_SIGCHAR_FLOAT:    output->d = ((double)output->f); break;
-  }
-#endif
-
   switch(ch) {
     case DC_SIGCHAR_BOOL:     return 'B';
     case DC_SIGCHAR_CHAR:     return 'c';