[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-devel
Subject:    [PATCH 09/23] winebuild: Add PPC64 support
From:       André Hentschel <nerv () dawncrow ! de>
Date:       2021-01-31 17:34:19
Message-ID: 20210131173433.114385-10-nerv () dawncrow ! de
[Download RAW message or body]

Signed-off-by: André Hentschel <nerv@dawncrow.de>
---
 tools/winebuild/build.h  |   4 +-
 tools/winebuild/import.c | 271 +++++++++++++++++++++++++++++++++++++++
 tools/winebuild/main.c   |   2 +
 tools/winebuild/parser.c |   4 +-
 tools/winebuild/spec32.c |  37 +++---
 tools/winebuild/utils.c  |  39 +++---
 6 files changed, 321 insertions(+), 36 deletions(-)

diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 4fb6e23700e..dce415deca1 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -145,7 +145,7 @@ typedef struct
 
 enum target_cpu
 {
-    CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_LAST = CPU_ARM64
+    CPU_x86, CPU_x86_64, CPU_POWERPC, CPU_ARM, CPU_ARM64, CPU_POWERPC64, CPU_LAST = \
CPU_POWERPC64  };
 
 enum target_platform
@@ -193,7 +193,7 @@ struct strarray
 
 #define FLAG_CPU(cpu)  (0x10000 << (cpu))
 #define FLAG_CPU_MASK  (FLAG_CPU(CPU_LAST + 1) - FLAG_CPU(0))
-#define FLAG_CPU_WIN64 (FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM64))
+#define FLAG_CPU_WIN64 (FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM64) | \
FLAG_CPU(CPU_POWERPC64))  #define FLAG_CPU_WIN32 (FLAG_CPU_MASK & ~FLAG_CPU_WIN64)
 
 #define MAX_ORDINALS  65535
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index 827a875e5df..7ee75ad3575 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -3,6 +3,8 @@
  *
  * Copyright 2000, 2004 Alexandre Julliard
  * Copyright 2000 Eric Pouech
+ * Copyright 2009-2013, 2015, 2017, 2020 André Hentschel
+ * Copyright 2019 Timothy Pearson <tpearson@raptorengineering.com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -793,6 +795,20 @@ static void output_import_thunk( const char *name, const char \
*table, int pos )  output( "\tmr    %s, %s\n", ppc_reg(31), ppc_reg(0) );
         output( "\tbctr\n" );
         break;
+    case CPU_POWERPC64:
+        /*
+         * The ppc64 ABIv2 expects r12 to be set to ctr before bctr for PLT-like \
calls. +         * ABIv2-compatible functions attempt to rebuild the TOC pointer (r2) \
from r12 under this assumption. +         */
+        output( "\tlis %s, (%s+%d)@highest\n", ppc_reg(12), table, pos );
+        output( "\tori %s, %s, (%s+%d)@higher\n", ppc_reg(12), ppc_reg(12), table, \
pos ); +        output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) );
+        output( "\toris %s, %s, (%s+%d)@high\n", ppc_reg(12), ppc_reg(12), table, \
pos ); +        output( "\tori %s, %s, (%s+%d)@l\n", ppc_reg(12), ppc_reg(12), table, \
pos ); +        output( "\tld %s, 0(%s)\n", ppc_reg(12), ppc_reg(12) );
+        output( "\tmtctr %s\n", ppc_reg(12) );
+        output( "\tbctr\n" );
+        break;
     }
     output_cfi( ".cfi_endproc" );
     output_function_size( name );
@@ -1144,6 +1160,54 @@ static void output_delayed_import_thunks( const DLLSPEC *spec \
)  output( "\tmtlr %s\n", ppc_reg(0));
         output( "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1),  \
48+extra_stack_storage);  
+        /* branch to ctr register. */
+        output( "\tbctr\n");
+        break;
+    case CPU_POWERPC64:
+        /* Save all callee saved registers into a stackframe. */
+        output( "\tstdu %s, -%d(%s)\n",ppc_reg(1), 176, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(2),  24, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(3),  48, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(4),  56, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(5),  64, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(6),  72, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(7),  80, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(8),  88, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(9),  96, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(10),104, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(11),112, ppc_reg(1));
+        output( "\tstd  %s, %d(%s)\n", ppc_reg(12),120, ppc_reg(1));
+        /* r0 -> r3 (arg1) */
+        output( "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
+        /* Call the __wine_delay_load function, arg1 is arg1. */
+        output( "\tlis %s, %s@highest\n", ppc_reg(12), \
asm_name("__wine_spec_delay_load") ); +        output( "\tori %s, %s, %s@higher\n", \
ppc_reg(12), ppc_reg(12), asm_name("__wine_spec_delay_load") ); +        output( \
"\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); +        output( "\toris %s, \
%s, %s@high\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_spec_delay_load") ); +     \
output( "\tori %s, %s, %s@l\n", ppc_reg(12), ppc_reg(12), \
asm_name("__wine_spec_delay_load") ); +        output( "\tmtctr %s\n", ppc_reg(12) );
+        output( "\tbctrl\n" );
+        output( "\tld %s, %d(%s)\n", ppc_reg(2),  24, ppc_reg(1));
+        /* r3 (return value) -> r12 (branch / ctr) */
+        output( "\tmr %s, %s\n", ppc_reg(12), ppc_reg(3));
+        /* Load return value from call into ctr register */
+        output( "\tmtctr %s\n", ppc_reg(12));
+        /* restore all saved registers and drop stackframe. */
+        output( "\tld %s, %d(%s)\n", ppc_reg(2),  24, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(3),  48, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(4),  56, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(5),  64, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(6),  72, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(7),  80, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(8),  88, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(9),  96, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(10),104, ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(11),112, ppc_reg(1));
+        /* don't restore r12!  restoring r12 here would corrupt the computed TOC \
post-bctr. */ +        /* Load return value from call into return register */
+        output( "\tld %s, 0(%s)\n", ppc_reg(1), ppc_reg(1));
+        output( "\tld %s, %d(%s)\n", ppc_reg(0), 16, ppc_reg(1));
+        output( "\tmtlr %s\n", ppc_reg(0));
         /* branch to ctr register. */
         output( "\tbctr\n");
         break;
@@ -1219,6 +1283,23 @@ static void output_delayed_import_thunks( const DLLSPEC *spec \
)  break;
                 }
                 break;
+            case CPU_POWERPC64:
+                output( "\tmflr %s\n", ppc_reg(0));
+                output( "\tstd  %s, %d(%s)\n", ppc_reg(0), 16, ppc_reg(1)); /* save \
return address */ +                output( "\tlis %s, %d@highest\n", ppc_reg(12), \
(idx << 16) | j ); +                output( "\tori %s, %s, %d@higher\n", ppc_reg(12), \
ppc_reg(12), (idx << 16) | j ); +                output( "\trldicr %s, %s, 32, 31\n", \
ppc_reg(12), ppc_reg(12) ); +                output( "\toris %s, %s, %d@high\n", \
ppc_reg(12), ppc_reg(12), (idx << 16) | j ); +                output( "\tori %s, %s, \
%d@l\n", ppc_reg(12), ppc_reg(12), (idx << 16) | j ); +                output( "\tmr \
%s, %s\n", ppc_reg(0), ppc_reg(12) ); +                output( "\tlis %s, \
%s@highest\n", ppc_reg(12), asm_name("__wine_delay_load_asm") ); +                \
output( "\tori %s, %s, %s@higher\n", ppc_reg(12), ppc_reg(12), \
asm_name("__wine_delay_load_asm") ); +                output( "\trldicr %s, %s, 32, \
31\n", ppc_reg(12), ppc_reg(12) ); +                output( "\toris %s, %s, \
%s@high\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_delay_load_asm") ); +          \
output( "\tori %s, %s, %s@l\n", ppc_reg(12), ppc_reg(12), \
asm_name("__wine_delay_load_asm") ); +                output( "\tmtctr %s\n", \
ppc_reg(12) ); +                output( "\tbctr\n" );
+                break;
             }
             output_cfi( ".cfi_endproc" );
         }
@@ -1392,6 +1473,37 @@ void output_stubs( DLLSPEC *spec )
                 output( "\tmov x1, %u\n", odp->ordinal );
             output( "\tbl %s\n", asm_name("__wine_spec_unimplemented_stub") );
             break;
+        case CPU_POWERPC64:
+            /* Clobbers r3, r4, and r12 */
+            output( "\tlis %s, .L__wine_spec_file_name@highest\n", ppc_reg(3) );
+            output( "\tori %s, %s, .L__wine_spec_file_name@higher\n", ppc_reg(3), \
ppc_reg(3) ); +            output( "\trldicr %s, %s, 32, 31\n", ppc_reg(3), \
ppc_reg(3) ); +            output( "\toris %s, %s, .L__wine_spec_file_name@high\n", \
ppc_reg(3), ppc_reg(3) ); +            output( "\tori %s, %s, \
.L__wine_spec_file_name@l\n", ppc_reg(3), ppc_reg(3) ); +            if (exp_name)
+            {
+                output( "\tlis %s, .L%s_string@highest\n", ppc_reg(4), name );
+                output( "\tori %s, %s, .L%s_string@higher\n", ppc_reg(4), \
ppc_reg(4), name ); +                output( "\trldicr %s, %s, 32, 31\n", ppc_reg(4), \
ppc_reg(4) ); +                output( "\toris %s, %s, .L%s_string@high\n", \
ppc_reg(4), ppc_reg(4), name ); +                output( "\tori %s, %s, \
.L%s_string@l\n", ppc_reg(4), ppc_reg(4), name ); +            }
+            else
+            {
+                output( "\tlis %s, %u@highest\n", ppc_reg(4), odp->ordinal );
+                output( "\tori %s, %s, %u@higher\n", ppc_reg(4), ppc_reg(4), \
odp->ordinal ); +                output( "\trldicr %s, %s, 32, 31\n", ppc_reg(4), \
ppc_reg(4) ); +                output( "\toris %s, %s, %u@high\n", ppc_reg(4), \
ppc_reg(4), odp->ordinal ); +                output( "\tori %s, %s, %u@l\n", \
ppc_reg(4), ppc_reg(4), odp->ordinal ); +            }
+            output( "\tlis %s, __wine_spec_unimplemented_stub@highest\n", \
ppc_reg(12) ); +            output( "\tori %s, %s, \
__wine_spec_unimplemented_stub@higher\n", ppc_reg(12), ppc_reg(12) ); +            \
output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); +            output( \
"\toris %s, %s, __wine_spec_unimplemented_stub@high\n", ppc_reg(12), ppc_reg(12) ); + \
output( "\tori %s, %s, __wine_spec_unimplemented_stub@l\n", ppc_reg(12), ppc_reg(12) \
); +            output( "\tmtctr %s\n", ppc_reg(12) );
+            output( "\tbctr\n" );
+            break;
         default:
             assert(0);
         }
@@ -1684,6 +1796,136 @@ void output_syscalls( DLLSPEC *spec )
             output( "\tmovk x0, #0x%x\n", invalid_param & 0x0000ffff );
             output( "\tret\n" );
             break;
+        case CPU_POWERPC64:
+            output( "\tlis %s, %u@highest\n", ppc_reg(12), count );
+            output( "\tori %s, %s, %u@higher\n", ppc_reg(12), ppc_reg(12), count );
+            output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) );
+            output( "\toris %s, %s, %u@high\n", ppc_reg(12), ppc_reg(12), count );
+            output( "\tori %s, %s, %u@l\n", ppc_reg(12), ppc_reg(12), count );
+            output( "\tcmpw cr7, %s, %s\n", ppc_reg(11), ppc_reg(12) );
+            output( "\tbgt cr7, 3f\n" );
+            /* save return address (thunk_addr) */
+            output( "\tmflr %s\n", ppc_reg(0) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(0), 16, ppc_reg(1) );
+            /* Save all callee saved registers into the syscall_frame. */
+            output( "\tstdu %s, -%d(%s)\n",ppc_reg(1),  240, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(2),   24, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(3),   32, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(4),   40, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(5),   48, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(6),   56, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(7),   64, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(8),   72, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(9),   80, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(10),  88, ppc_reg(1) );
+            /* Save all nonvolatile registers into the syscall_frame. */
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(14),  96, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(15), 104, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(16), 112, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(17), 120, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(18), 128, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(19), 136, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(20), 144, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(21), 152, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(22), 160, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(23), 168, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(24), 176, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(25), 184, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(26), 192, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(27), 200, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(28), 208, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(29), 216, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(30), 224, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(31), 232, ppc_reg(1) );
+            output( "\tmr %s, %s\n", ppc_reg(15), ppc_reg(11) );
+            output( "\tmr %s, %s\n", ppc_reg(18), ppc_reg(1) );
+            output( "\tld  %s, %d(%s)\n", ppc_reg(11),  240 + 40, ppc_reg(1) );
+            output( "\tlis %s, %s@highest\n", ppc_reg(12), asm_name("NtCurrentTeb") \
); +            output( "\tori %s, %s, %s@higher\n", ppc_reg(12), ppc_reg(12), \
asm_name("NtCurrentTeb") ); +            output( "\trldicr %s, %s, 32, 31\n", \
ppc_reg(12), ppc_reg(12) ); +            output( "\toris %s, %s, %s@high\n", \
ppc_reg(12), ppc_reg(12), asm_name("NtCurrentTeb") ); +            output( "\tori %s, \
%s, %s@l\n", ppc_reg(12), ppc_reg(12), asm_name("NtCurrentTeb") ); +            \
output( "\tmtctr %s\n", ppc_reg(12) ); +            output( "\tbctrl\n" );
+            /* ppc64_thread_data()->syscall_frame */
+            output( "\taddi %s, %s, 0x200\n", ppc_reg(3),  ppc_reg(3) );
+            output( "\taddi %s, %s, 0x0f0\n", ppc_reg(3),  ppc_reg(3) );
+            output( "\taddi %s, %s, 0x008\n", ppc_reg(19), ppc_reg(3) );
+            output( "\tstd %s, 0(%s)\n", ppc_reg(1), ppc_reg(19) );  /* syscall \
frame */ +            output( "\tld %s, %d(%s)\n", ppc_reg(3),  32, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(4),  40, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(5),  48, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(6),  56, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(7),  64, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(8),  72, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(9),  80, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(10), 88, ppc_reg(1) );
+            output( "\tlis %s, %s@highest\n", ppc_reg(12), \
asm_name(".Lsyscall_args") ); +            output( "\tori %s, %s, %s@higher\n", \
ppc_reg(12), ppc_reg(12), asm_name(".Lsyscall_args") ); +            output( \
"\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); +            output( "\toris \
%s, %s, %s@high\n", ppc_reg(12), ppc_reg(12), asm_name(".Lsyscall_args") ); +         \
output( "\tori %s, %s, %s@l\n", ppc_reg(12), ppc_reg(12), asm_name(".Lsyscall_args") \
); +            output( "\tadd %s, %s, %s\n", ppc_reg(12), ppc_reg(12), ppc_reg(15) \
); +            output( "\tlbz %s, 0(%s)\n", ppc_reg(16), ppc_reg(12) );
+            output( "\taddi %s, %s, -64\n", ppc_reg(16), ppc_reg(16) );
+            output( "\tcmpwi cr7, %s, 0\n", ppc_reg(16) );
+            output( "\textsw %s, %s\n", ppc_reg(16), ppc_reg(16) );
+            output( "\tble cr7, 2f\n" );
+            output( "\taddi %s, %s, %d\n", ppc_reg(17), ppc_reg(1), 240 + 64 + 96); \
/* this function + prev function (thunk) + parameter save area */ +            \
output( "\tsub %s, %s, %s\n", ppc_reg(1), ppc_reg(1), ppc_reg(16) ); +            \
output( "\taddi %s, %s, -%d\n", ppc_reg(1), ppc_reg(1), 96 ); +            output( \
"\trldicr %s, %s, 0, 59\n", ppc_reg(1), ppc_reg(1) ); /* align sp */ +            \
output( "\tstd %s, %d(%s)\n", ppc_reg(18),  0, ppc_reg(1) ); +            output( \
"\tstd  %s, %d(%s)\n", ppc_reg(2), 24, ppc_reg(1) ); +            output( "\taddi %s, \
%s, %d\n", ppc_reg(20), ppc_reg(1), 96 ); /* new parameter save area */ +            \
output( "1:\taddi %s, %s, -%d\n", ppc_reg(16), ppc_reg(16), 8 ); +            output( \
"\tldx  %s, %s, %s\n", ppc_reg(0), ppc_reg(17), ppc_reg(16) ); +            output( \
"\tstdx %s, %s, %s\n", ppc_reg(0), ppc_reg(20), ppc_reg(16) ); +            output( \
"\tcmpwi cr7, %s, 0\n", ppc_reg(16) ); +            output( "\tbne cr7, 1b\n" );
+            output( "2:\tlis %s, %s@highest\n", ppc_reg(12), \
asm_name(".Lsyscall_table") ); +            output( "\tori %s, %s, %s@higher\n", \
ppc_reg(12), ppc_reg(12), asm_name(".Lsyscall_table") ); +            output( \
"\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); +            output( "\toris \
%s, %s, %s@high\n", ppc_reg(12), ppc_reg(12), asm_name(".Lsyscall_table") ); +        \
output( "\tori %s, %s, %s@l\n", ppc_reg(12), ppc_reg(12), asm_name(".Lsyscall_table") \
); +            output( "\trldicr %s, %s, 3, 60\n", ppc_reg(17), ppc_reg(15) );
+            output( "\tadd %s, %s, %s\n", ppc_reg(17), ppc_reg(17), ppc_reg(12) );
+            output( "\tld %s, 0(%s)\n", ppc_reg(12), ppc_reg(17) );
+            output( "\tmtctr %s\n", ppc_reg(12) );
+            output( "\tbctrl\n" );
+            output( "\tmr %s, %s\n", ppc_reg(1), ppc_reg(18) );
+            output( "\tli %s, 0\n", ppc_reg(0) );
+            output( "\tstd %s, 0(%s)\n", ppc_reg(0), ppc_reg(19) );
+            output( "\tld  %s, %d(%s)\n", ppc_reg(2),  24, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(14),  96, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(15), 104, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(16), 112, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(17), 120, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(18), 128, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(19), 136, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(20), 144, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(21), 152, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(22), 160, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(23), 168, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(24), 176, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(25), 184, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(26), 192, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(27), 200, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(28), 208, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(29), 216, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(30), 224, ppc_reg(1) );
+            output( "\tld %s, %d(%s)\n", ppc_reg(31), 232, ppc_reg(1) );
+            output( "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1), 240 ); /* restore \
sp */ +            output( "\tld %s, %d(%s)\n", ppc_reg(0), 16, ppc_reg(1) );
+            output( "\tmtlr %s\n", ppc_reg(0) );
+            output( "\tblr\n" );
+            output( "3:\tlis %s, %u@highest\n", ppc_reg(3), invalid_param );
+            output( "\tori %s, %s, %u@higher\n", ppc_reg(3), ppc_reg(3), \
invalid_param ); +            output( "\trldicr %s, %s, 32, 31\n", ppc_reg(3), \
ppc_reg(3) ); +            output( "\toris %s, %s, %u@high\n", ppc_reg(3), \
ppc_reg(3), invalid_param ); +            output( "\tori %s, %s, %u@l\n", ppc_reg(3), \
ppc_reg(3), invalid_param ); +            output( "\tblr\n" );
+            break;
         default:
             assert(0);
         }
@@ -1778,6 +2020,35 @@ void output_syscalls( DLLSPEC *spec )
             output( "\tldp x29, x30, [sp], #16\n" );
             output( "\tret\n" );
             break;
+        case CPU_POWERPC64:
+            output( "\tmflr %s\n", ppc_reg(0) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(0), 16, ppc_reg(1) ); /* save lr \
*/ +            output( "\tstdu %s, -%d(%s)\n",ppc_reg(1),  64, ppc_reg(1) );
+            output( "\tstd  %s, %d(%s)\n", ppc_reg(2),  24, ppc_reg(1) ); /* save r2 \
*/ +            output( "\tstd  %s, %d(%s)\n", ppc_reg(0),  32, ppc_reg(1) ); /* save \
lr again */ +            output( "\tstd  %s, %d(%s)\n", ppc_reg(11), 40, ppc_reg(1) \
); /* save r11 */ +            output( "\tstd  %s, %d(%s)\n", ppc_reg(12), 48, \
ppc_reg(1) ); /* save r12 */ +            output( "\tlis %s, %s@highest\n", \
ppc_reg(12), asm_name("__wine_syscall_dispatcher") ); +            output( "\tori %s, \
%s, %s@higher\n", ppc_reg(12), ppc_reg(12), asm_name("__wine_syscall_dispatcher") ); \
+            output( "\trldicr %s, %s, 32, 31\n", ppc_reg(12), ppc_reg(12) ); +       \
output( "\toris %s, %s, %s@high\n", ppc_reg(12), ppc_reg(12), \
asm_name("__wine_syscall_dispatcher") ); +            output( "\tori %s, %s, %s@l\n", \
ppc_reg(12), ppc_reg(12), asm_name("__wine_syscall_dispatcher") ); +            \
output( "\tld %s, 0(%s)\n", ppc_reg(12), ppc_reg(12) ); +            output( "\tlis \
%s, %u@highest\n", ppc_reg(11), i ); +            output( "\tori %s, %s, \
%u@higher\n", ppc_reg(11), ppc_reg(11), i ); +            output( "\trldicr %s, %s, \
32, 31\n", ppc_reg(11), ppc_reg(11) ); +            output( "\toris %s, %s, \
%u@high\n", ppc_reg(11), ppc_reg(11), i ); +            output( "\tori %s, %s, \
%u@l\n", ppc_reg(11), ppc_reg(11), i ); +            output( "\tmtctr %s\n", \
ppc_reg(12) ); +            output( "\tbctrl\n" );
+            output( "\tld %s, %d(%s)\n", ppc_reg(12), 48, ppc_reg(1) ); /* restore \
r12 */ +            output( "\tld %s, %d(%s)\n", ppc_reg(11), 40, ppc_reg(1) ); /* \
restore r11 */ +            output( "\tld %s, %d(%s)\n", ppc_reg(2),  24, ppc_reg(1) \
); /* restore r2 */ +            output( "\taddi %s, %s, %d\n", ppc_reg(1), \
ppc_reg(1), 64 ); /* restore sp */ +            output( "\tld %s, %d(%s)\n", \
ppc_reg(0), 16, ppc_reg(1) ); /* restore lr */ +            output( "\tmtlr %s\n", \
ppc_reg(0) ); +            output( "\tblr\n" );
+            break;
         default:
             assert(0);
         }
diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c
index 1477df7f259..2420225ffaf 100644
--- a/tools/winebuild/main.c
+++ b/tools/winebuild/main.c
@@ -54,6 +54,8 @@ int safe_seh = 0;
 enum target_cpu target_cpu = CPU_x86;
 #elif defined(__x86_64__)
 enum target_cpu target_cpu = CPU_x86_64;
+#elif defined(__powerpc64__)
+enum target_cpu target_cpu = CPU_POWERPC64;
 #elif defined(__powerpc__)
 enum target_cpu target_cpu = CPU_POWERPC;
 #elif defined(__arm__)
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index 2e6424fe76a..edcacadf801 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -432,9 +432,9 @@ static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
     odp->link_name = xstrdup("");
     /* don't bother generating stubs for Winelib */
     if (odp->flags & FLAG_CPU_MASK)
-        odp->flags &= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM) | \
FLAG_CPU(CPU_ARM64); +        odp->flags &= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) \
| FLAG_CPU(CPU_ARM) | FLAG_CPU(CPU_ARM64) | FLAG_CPU(CPU_POWERPC64);  else
-        odp->flags |= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) | FLAG_CPU(CPU_ARM) | \
FLAG_CPU(CPU_ARM64); +        odp->flags |= FLAG_CPU(CPU_x86) | FLAG_CPU(CPU_x86_64) \
| FLAG_CPU(CPU_ARM) | FLAG_CPU(CPU_ARM64) | FLAG_CPU(CPU_POWERPC64);  
     return parse_spec_arguments( odp, spec, 1 );
 }
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 678f104c555..21df41329cd 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -32,12 +32,13 @@
 
 #include "build.h"
 
-#define IMAGE_FILE_MACHINE_UNKNOWN 0
-#define IMAGE_FILE_MACHINE_I386    0x014c
-#define IMAGE_FILE_MACHINE_POWERPC 0x01f0
-#define IMAGE_FILE_MACHINE_AMD64   0x8664
-#define IMAGE_FILE_MACHINE_ARMNT   0x01C4
-#define IMAGE_FILE_MACHINE_ARM64   0xaa64
+#define IMAGE_FILE_MACHINE_UNKNOWN   0
+#define IMAGE_FILE_MACHINE_I386      0x014c
+#define IMAGE_FILE_MACHINE_POWERPC   0x01f0
+#define IMAGE_FILE_MACHINE_POWERPC64 0x01f2
+#define IMAGE_FILE_MACHINE_AMD64     0x8664
+#define IMAGE_FILE_MACHINE_ARMNT     0x01C4
+#define IMAGE_FILE_MACHINE_ARM64     0xaa64
 
 #define IMAGE_SIZEOF_NT_OPTIONAL32_HEADER 224
 #define IMAGE_SIZEOF_NT_OPTIONAL64_HEADER 240
@@ -610,7 +611,6 @@ void output_exports( DLLSPEC *spec )
     }
 }
 
-
 /*******************************************************************
  *         output_module
  *
@@ -655,6 +655,7 @@ void output_module( DLLSPEC *spec )
             break;
         case CPU_ARM64:
         case CPU_POWERPC:
+        case CPU_POWERPC64:
             output( "\n\t.section \".init\",\"ax\"\n" );
             output( "\tb 1f\n" );
             break;
@@ -676,11 +677,12 @@ void output_module( DLLSPEC *spec )
     output( "\t.long 0x4550\n" );         /* Signature */
     switch(target_cpu)
     {
-    case CPU_x86:     machine = IMAGE_FILE_MACHINE_I386; break;
-    case CPU_x86_64:  machine = IMAGE_FILE_MACHINE_AMD64; break;
-    case CPU_POWERPC: machine = IMAGE_FILE_MACHINE_POWERPC; break;
-    case CPU_ARM:     machine = IMAGE_FILE_MACHINE_ARMNT; break;
-    case CPU_ARM64:   machine = IMAGE_FILE_MACHINE_ARM64; break;
+    case CPU_x86:       machine = IMAGE_FILE_MACHINE_I386; break;
+    case CPU_x86_64:    machine = IMAGE_FILE_MACHINE_AMD64; break;
+    case CPU_POWERPC:   machine = IMAGE_FILE_MACHINE_POWERPC; break;
+    case CPU_POWERPC64: machine = IMAGE_FILE_MACHINE_POWERPC64; break;
+    case CPU_ARM:       machine = IMAGE_FILE_MACHINE_ARMNT; break;
+    case CPU_ARM64:     machine = IMAGE_FILE_MACHINE_ARM64; break;
     }
     output( "\t.short 0x%04x\n",          /* Machine */
              machine );
@@ -833,11 +835,12 @@ void output_fake_module( DLLSPEC *spec )
     put_dword( 0x4550 );                             /* Signature */
     switch(target_cpu)
     {
-    case CPU_x86:     put_word( IMAGE_FILE_MACHINE_I386 ); break;
-    case CPU_x86_64:  put_word( IMAGE_FILE_MACHINE_AMD64 ); break;
-    case CPU_POWERPC: put_word( IMAGE_FILE_MACHINE_POWERPC ); break;
-    case CPU_ARM:     put_word( IMAGE_FILE_MACHINE_ARMNT ); break;
-    case CPU_ARM64:   put_word( IMAGE_FILE_MACHINE_ARM64 ); break;
+    case CPU_x86:       put_word( IMAGE_FILE_MACHINE_I386 ); break;
+    case CPU_x86_64:    put_word( IMAGE_FILE_MACHINE_AMD64 ); break;
+    case CPU_POWERPC:   put_word( IMAGE_FILE_MACHINE_POWERPC ); break;
+    case CPU_POWERPC64: put_word( IMAGE_FILE_MACHINE_POWERPC64 ); break;
+    case CPU_ARM:       put_word( IMAGE_FILE_MACHINE_ARMNT ); break;
+    case CPU_ARM64:     put_word( IMAGE_FILE_MACHINE_ARM64 ); break;
     }
     put_word( nb_sections );                         /* NumberOfSections */
     put_dword( hash_filename(spec->file_name) );     /* TimeDateStamp */
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 928a2460aa1..5389c1ba32c 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -52,21 +52,23 @@ static const struct
     enum target_cpu cpu;
 } cpu_names[] =
 {
-    { "i386",    CPU_x86 },
-    { "i486",    CPU_x86 },
-    { "i586",    CPU_x86 },
-    { "i686",    CPU_x86 },
-    { "i786",    CPU_x86 },
-    { "amd64",   CPU_x86_64 },
-    { "x86_64",  CPU_x86_64 },
-    { "powerpc", CPU_POWERPC },
-    { "arm",     CPU_ARM },
-    { "armv5",   CPU_ARM },
-    { "armv6",   CPU_ARM },
-    { "armv7",   CPU_ARM },
-    { "armv7a",  CPU_ARM },
-    { "arm64",   CPU_ARM64 },
-    { "aarch64", CPU_ARM64 },
+    { "i386",           CPU_x86 },
+    { "i486",           CPU_x86 },
+    { "i586",           CPU_x86 },
+    { "i686",           CPU_x86 },
+    { "i786",           CPU_x86 },
+    { "amd64",          CPU_x86_64 },
+    { "x86_64",         CPU_x86_64 },
+    { "powerpc",        CPU_POWERPC },
+    { "powerpc64",      CPU_POWERPC64 },
+    { "powerpc64le",    CPU_POWERPC64 },
+    { "arm",            CPU_ARM },
+    { "armv5",          CPU_ARM },
+    { "armv6",          CPU_ARM },
+    { "armv7",          CPU_ARM },
+    { "armv7a",         CPU_ARM },
+    { "arm64",          CPU_ARM64 },
+    { "aarch64",        CPU_ARM64 },
 };
 
 /* atexit handler to clean tmp files */
@@ -425,6 +427,7 @@ struct strarray get_as_command(void)
             switch(target_cpu)
             {
             case CPU_POWERPC:
+            case CPU_POWERPC64:
                 strarray_add_one( &args, (force_pointer_size == 8) ? "-a64" : "-a32" \
);  break;
             default:
@@ -472,6 +475,10 @@ struct strarray get_ld_command(void)
             case CPU_POWERPC:
                 strarray_add( &args, "-m", (force_pointer_size == 8) ? "elf64ppc" : \
"elf32ppc", NULL );  break;
+            case CPU_POWERPC64:
+                /* We only respect the little endian version for now */
+                strarray_add( &args, "-m", (force_pointer_size == 8) ? "elf64lppc" : \
"elf32lppc", NULL ); +                break;
             default:
                 strarray_add( &args, "-m", (force_pointer_size == 8) ? "elf_x86_64" \
: "elf_i386", NULL );  break;
@@ -1029,6 +1036,7 @@ unsigned int get_alignment(unsigned int align)
         if (target_platform != PLATFORM_APPLE) return align;
         /* fall through */
     case CPU_POWERPC:
+    case CPU_POWERPC64:
     case CPU_ARM:
     case CPU_ARM64:
         n = 0;
@@ -1056,6 +1064,7 @@ unsigned int get_ptr_size(void)
     case CPU_ARM:
         return 4;
     case CPU_x86_64:
+    case CPU_POWERPC64:
     case CPU_ARM64:
         return 8;
     }
-- 
2.25.1


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic