This is the mail archive of the
frysk@sources.redhat.com
mailing list for the frysk project.
Re: one frysk-core patch to add PPC64 testcases.
- From: Yong Zheng <zhengyo at cn dot ibm dot com>
- To: frysk at sourceware dot org
- Date: Fri, 18 Aug 2006 20:07:04 +0800
- Subject: Re: one frysk-core patch to add PPC64 testcases.
- References: <1155884638.7779.25.camel@YZ_X86_64>
hi,
here is the latest patch.
2006-08-18 Yong Zheng <zhengyo@cn.ibm.com>
* frysk/proc/TestPPC64Regs.java: New file for PPC64 test.
* frysk/proc/TestPPC64Modify.java: Ditto.
* frysk/pkglibexecdir/funit-ppc64-regs.S: Ditto.
* frysk/pkglibexecdir/funit-ppc64-modify.S: Ditto.
* frysk/Makefile.am: Add PPC64Regs/PPC64Modify tests.
* frysk/proc/IsaPPC64.java (getWordSize): Edit return value
from 4 to 8.
Rebuild frysk on X86-64/PPC64 based on the cvs head(08-18) and tested.
Please review it.
Best regards
Yong Zheng
On Fri, 2006-08-18 at 15:03 +0800, Yong Zheng wrote:
> hi,
>
> There's no any case for us to test register and memory modification in
> PPC64 in frysk. So we write two cases for above purpose. During the
> test, we found the PPC64's worksize(got from IsaPPC64.java) should be
> 8bytes but not 4 bytes. Here is the patch to add PPC64 tests.
>
> 2006-08-18 Yong Zheng <zhengyo@cn.ibm.com>
>
> * frysk/proc/TestPPC64Regs.java: New file for PPC64 test
> * frysk/proc/TestPPC64Modify.java: New file for PPC64 test
> * frysk/pkglibexecdir/funit-ppc64-regs.S: New file for PPC64
> * frysk/pkglibexecdir/funit-ppc64-modify.S: Ditto
> * frysk/Makefile.am: Add PPC64Regs/PPC64Modify tests
>
> * frysk/proc/IsaPPC64.java (getWordSize): Edit return value
> from 4 to 8
>
> Rebuild frysk on X86-64/PPC64 based on the cvs head(08-18) and tested.
>
> Best regards
> Yong Zheng
>
Index: frysk-core/Makefile.am
===================================================================
RCS file: /cvs/frysk/frysk-core/Makefile.am,v
retrieving revision 1.61
diff -u -r1.61 Makefile.am
--- frysk-core/Makefile.am 17 Aug 2006 01:54:27 -0000 1.61
+++ frysk-core/Makefile.am 18 Aug 2006 08:04:30 -0000
@@ -102,6 +102,11 @@
frysk_pkglibexecdir_funit_x8664_modify_SOURCES = frysk/pkglibexecdir/funit-x8664-modify.S
pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-x8664-modify
+frysk_pkglibexecdir_funit_ppc64_regs_SOURCES = frysk/pkglibexecdir/funit-ppc64-regs.S
+pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-ppc64-regs
+frysk_pkglibexecdir_funit_ppc64_modify_SOURCES = frysk/pkglibexecdir/funit-ppc64-modify.S
+pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-ppc64-modify
+
# For TestExec.java
pkglibexec_PROGRAMS += frysk/pkglibexecdir/funit-child-alias
frysk_pkglibexecdir_funit_child_alias_SOURCES =
Index: frysk-core/frysk/proc/IsaPPC64.java
===================================================================
RCS file: /cvs/frysk/frysk-core/frysk/proc/IsaPPC64.java,v
retrieving revision 1.1
diff -u -r1.1 IsaPPC64.java
--- frysk-core/frysk/proc/IsaPPC64.java 4 Aug 2006 09:07:42 -0000 1.1
+++ frysk-core/frysk/proc/IsaPPC64.java 18 Aug 2006 08:05:25 -0000
@@ -84,7 +84,7 @@
public int getWordSize ()
{
- return 4;
+ return 8;
}
public ByteOrder getByteOrder ()
--- /dev/null 2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/proc/TestPPC64Modify.java 2006-08-18 15:59:14.000000000 +0800
@@ -0,0 +1,251 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2006, IBM Corp.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+package frysk.proc;
+
+import java.util.Observer;
+import java.util.Observable;
+
+import frysk.sys.SyscallNum;
+
+/**
+ * Check that registers and memory can be modified for PPC64.
+ *
+ * This test case runs an assembler program that will terminate successfully
+ * if left to run untouched. The test adds a syscall observer and modifies
+ * a register which is used as a jump location when the test returns. This causes
+ * an alternate code path which issues an exit syscall. The test also modifies
+ * other registers as well as a data word in the program being run. The alternate
+ * code path in the program being run will verify the new register values and
+ * will not issue the exit syscall unless everything is correct.
+ *
+ * You can read this testsuite and the assembler program.
+ */
+public class TestPPC64Modify
+ extends TestLib
+{
+ class TestPPC64ModifyInternals
+ {
+ volatile int stoppedTaskEventCount;
+ volatile int syscallTaskEventCount;
+ volatile int syscallState;
+ volatile boolean exited;
+ volatile int exitedTaskEventStatus;
+
+ long gpr0;
+ long gpr3;
+
+ // Test the following registers' value
+ long gpr4;
+ long gpr5;
+
+ long gpr6;
+ long gpr7;
+ long gpr8;
+
+ int syscallNum;
+ boolean isPPC64Isa;
+ boolean exitSyscall;
+
+ // Need to add task observers to the process the moment it is
+ // created, otherwize the creation of the very first task is
+ // missed (giving a mismatch of task created and deleted
+ // notifications.)
+
+ class TaskEventObserver
+ extends TaskObserverBase
+ implements TaskObserver.Syscall, TaskObserver.Signaled
+ {
+ public Action updateSyscallEnter (Task task)
+ {
+ syscallState = 1;
+ SyscallEventInfo syscall;
+ LinuxPPC64 isa;
+
+ try
+ {
+ syscall = task.getSyscallEventInfo();
+ isa = (LinuxPPC64)task.getIsa();
+ }
+ catch (TaskException e)
+ {
+ fail("Got task exception " + e);
+ return Action.CONTINUE; // not reached
+ }
+
+ // The low-level assembler code performs an exit syscall
+ // and sets up the registers with simple values. We want
+ // to verify that all the registers are as expected.
+ syscallNum = syscall.number (task);
+ if (syscallNum == SyscallNum.SYSgetpid)
+ {
+ // In the assembler program, we store 21 to gpr3, 22 to gpr4
+ // and 23 to gpr5 before syscalling
+ gpr3 = isa.getRegisterByName ("gpr3").get (task);
+ assertEquals ("gpr3 register", 21, gpr3);
+
+ gpr4 = isa.getRegisterByName ("gpr4").get (task);
+ assertEquals ("rsi register", 22, gpr4);
+
+ gpr5 = isa.getRegisterByName ("gpr5").get (task);
+ assertEquals ("rdx register", 23, gpr5);
+
+ gpr6 = isa.getRegisterByName ("gpr6").get (task);
+ int mem = task.memory.getInt (gpr6);
+
+ // gpr6 store the value 3 first and then we will modify it to 8
+ assertEquals ("old mem value", 3, mem);
+ task.memory.putInt (gpr6, 8);
+ mem = task.memory.getInt (gpr6);
+ assertEquals ("new mem value", 8, mem);
+
+ gpr7 = isa.getRegisterByName ("gpr7").get (task);
+ isa.getRegisterByName ("gpr8").put (task, gpr7);
+
+ // Set a number of the registers as expected.
+ // Then check them in assembly
+ isa.getRegisterByName ("gpr3").put (task, 3);
+ isa.getRegisterByName ("gpr4").put (task, 4);
+ isa.getRegisterByName ("gpr5").put (task, 5);
+ isa.getRegisterByName ("gpr7").put (task, 7);
+
+ // After this, the assembler program will be executed.
+ // If all is ok, it will call 'exit' syscall to exit.
+ }
+ else if (syscallNum == SyscallNum.SYSexit)
+ {
+ gpr3 = isa.getRegisterByName ("gpr3").get (task);
+ assertEquals ("exit code", 3, gpr3);
+ exitSyscall = true;
+ }
+ return Action.CONTINUE;
+ }
+
+ public Action updateSyscallExit (Task task)
+ {
+ syscallState = 0;
+ return Action.CONTINUE;
+ }
+
+ public Action updateSignaled (Task task, int sig)
+ {
+ //fail ("unexpected signal " + sig);
+ return Action.CONTINUE; // not reached
+ }
+ }
+
+ TaskEventObserver taskEventObserver = new TaskEventObserver ();
+
+ class ProcRemovedObserver
+ implements Observer
+ {
+ volatile int count;
+
+ public void update (Observable o, Object obj)
+ {
+ Proc process = (Proc) obj;
+ if (isChildOfMine (process))
+ {
+ syscallState ^= 1; // we won't return from exit syscall
+ exited = true;
+ Manager.eventLoop.requestStop ();
+ }
+ }
+ }
+
+ TestPPC64ModifyInternals ()
+ {
+ host.observableTaskAddedXXX.addObserver (new Observer ()
+ {
+ public void update (Observable o, Object obj)
+ {
+ Task task = (Task) obj;
+ if (!isChildOfMine (task.proc))
+ return;
+ killDuringTearDown (task.getTid ());
+
+ Isa isa;
+ try
+ {
+ isa = task.getIsa();
+ }
+ catch (TaskException e)
+ {
+ isa = null;
+ }
+
+ if (isa instanceof LinuxPPC64)
+ {
+ isPPC64Isa = true;
+ task.requestAddSyscallObserver (taskEventObserver);
+ task.requestAddSignaledObserver (taskEventObserver);
+ }
+ else
+ {
+ //If not PPC64, stop immediately
+ isPPC64Isa = false;
+ Manager.eventLoop.requestStop ();
+ }
+ }
+ });
+
+ host.observableProcRemovedXXX.addObserver(new ProcRemovedObserver ());
+ }
+ }
+
+ public void testPPC64Modify ()
+ {
+ if (MachineType.getMachineType() != MachineType.PPC64)
+ return;
+ TestPPC64ModifyInternals t = new TestPPC64ModifyInternals ();
+
+ // Call assembler program making syscalls
+ new AttachedDaemonProcess (new String[]
+ {
+ getExecPrefix () + "funit-ppc64-modify"
+ }).resume ();
+ assertRunUntilStop ("run \"ppc64modify\" to exit");
+
+ if (t.isPPC64Isa)
+ {
+ assertTrue ("proc exited", t.exited);
+ assertTrue ("exit syscall found", t.exitSyscall);
+ }
+ }
+}
--- /dev/null 2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/proc/TestPPC64Regs.java 2006-08-18 15:58:54.000000000 +0800
@@ -0,0 +1,177 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2006, IBM Corp.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+package frysk.proc;
+
+import java.util.Observable;
+
+import frysk.sys.SyscallNum;
+
+/**
+ * Check that PPC64 registers can be accessed.
+ */
+public class TestPPC64Regs
+ extends SyscallExaminer
+{
+ class TestPPC64RegsInternals extends SyscallExaminer.Tester
+ {
+ long gpr0;
+ long gpr3;
+ long gpr4;
+ long gpr5;
+
+ int syscallNum;
+ boolean isPPC64Isa;
+
+ // Need to add task observers to the process the moment it is
+ // created, otherwize the creation of the very first task is
+ // missed (giving a mismatch of task created and deleted
+ // notifications.)
+
+ class TaskEventObserver
+ extends SyscallExaminer.Tester.TaskEventObserver
+ {
+ public Action updateSyscallEnter (Task task)
+ {
+ LinuxPPC64 isaPPC64;
+ SyscallEventInfo syscall;
+
+ super.updateSyscallEnter(task);
+
+ try
+ {
+ syscall = task.getSyscallEventInfo ();
+ isaPPC64 = (LinuxPPC64)task.getIsa ();
+ }
+ catch (TaskException e)
+ {
+ fail("got task exception " + e);
+ return Action.CONTINUE; // not reached
+ }
+
+ // The low-level assembler code performs an exit syscall
+ // and sets up the registers with simple values. We want
+ // to verify that all the registers are as expected.
+ syscallNum = syscall.number (task);
+
+ if (syscallNum == SyscallNum.SYSexit)
+ {
+ gpr0 = isaPPC64.getRegisterByName ("gpr0").get (task);
+ gpr3 = isaPPC64.getRegisterByName ("gpr3").get (task);
+ gpr4 = isaPPC64.getRegisterByName ("gpr4").get (task);
+ gpr5 = isaPPC64.getRegisterByName ("gpr5").get (task);
+ }
+
+ return Action.CONTINUE;
+ }
+ }
+
+ class RegsTestObserver
+ extends SyscallExaminer.TaskAddedObserver
+ {
+ public void update(Observable o, Object obj)
+ {
+ super.update(o, obj);
+ Task task = (Task)obj;
+
+ if (!isChildOfMine(task.proc))
+ return;
+
+ Isa isa;
+ TaskEventObserver taskEventObserver = new TaskEventObserver();
+
+ try
+ {
+ isa = task.getIsa();
+ }
+ catch (TaskException e)
+ {
+ isa = null;
+ }
+
+ if (isa instanceof LinuxPPC64)
+ {
+ isPPC64Isa = true;
+ task.requestAddSyscallObserver(taskEventObserver);
+ task.requestAddSignaledObserver(taskEventObserver);
+ }
+ else
+ {
+ //If not PPC64, stop immediately
+ isPPC64Isa = false;
+ Manager.eventLoop.requestStop();
+ }
+ }
+ }
+
+ TestPPC64RegsInternals ()
+ {
+ super();
+ addTaskAddedObserver(new RegsTestObserver());
+ }
+ }
+
+ public void testPPC64Regs ()
+ {
+ if (MachineType.getMachineType() != MachineType.PPC64)
+ return;
+
+ TestPPC64RegsInternals t = new TestPPC64RegsInternals();
+ // Create program making an exit syscall");
+ AttachedDaemonProcess child = new AttachedDaemonProcess (new String[]
+ {
+ getExecPrefix () + "funit-ppc64-regs"
+ });
+ logger.finest("About to resume funit-ppc64-regs");
+ child.resume();
+ assertRunUntilStop ("run \"ppc64regs\" until exit");
+
+ if (t.isPPC64Isa)
+ {
+ assertEquals ("syscall", 1, t.syscallNum);
+ assertEquals ("gpr0 register", 1, t.gpr0);
+ assertEquals ("gpr3 register", 1, t.gpr3);
+ assertEquals ("gpr4 register", 4, t.gpr4);
+ // Left shift 36bits from 0x1
+ assertEquals ("gpr5 register", 0x1000000000L, t.gpr5);
+
+ assertTrue ("exited", t.exited);
+ }
+ }
+}
--- /dev/null 2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/pkglibexecdir/funit-ppc64-modify.S 2006-08-18 15:57:11.000000000 +0800
@@ -0,0 +1,142 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2006 IBM Corp.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+.text # section declaration - begin code
+
+ .global main
+#ifdef __powerpc64__
+ .section ".opd","aw"
+ .align 3
+#endif
+
+main:
+
+#ifdef __powerpc64__
+ .quad ._main,.TOC.@tocbase,0
+ .previous
+
+ .global ._main
+._main:
+
+ mflr 0 # move the value of LR to gpr0
+ std 31,-8(1)
+ std 0,16(1) # store the LR to 16(1)
+ stdu 1,-144(1) # store the stack frame pointer value to -144(1)
+ mr 31,1 # copy the value gpr1 to gpr31
+
+ li 0,20 # syscall number(sys_write)
+ li 3,21 # values for TestPPC64Modify.java to inspect. gpr3=21
+ li 4,22 # gpr4=22
+ li 5,23 # gpr5=23
+
+ # load the data's address
+ lis 6,data_value@highest
+ ori 6,6,data_value@higher # load data bits 32-47 into gpr6 bits 0-15
+
+ rldicr 6,6,32,31 # rotate gpr6's low word(0-31)into 32-63
+
+ oris 6,6,data_value@h
+ ori 6,6,data_value@l
+
+ #load the .L0's address
+ lis 7,.L0@highest
+ ori 7,7,.L0@higher # load data bits 32-47 into gpr6 bits 0-15
+
+ rldicr 7,7,32,31 # rotate gpr6's low word(0-31)into 32-63
+
+ oris 7,7,.L0@h
+ ori 7,7,.L0@l
+
+ # load the .L1's address
+ lis 8,.L1@highest
+ ori 8,8,.L1@higher # load data bits 32-47 into gpr6 bits 0-15
+
+ rldicr 8,8,32,31 # rotate gpr6's low word(0-31)into 32-63
+
+ oris 8,8,.L1@h
+ ori 8,8,.L1@l
+
+ sc
+ #mtctr 8
+ #bctr
+.L0:
+ # Check the value of variables is right or not
+ cmpdi cr7,4,4
+ bne cr7,.L2
+ cmpdi cr7,5,5
+ bne cr7,.L2
+
+ # check the value of gpr6
+ # load the variable's value
+ lis 6,data_value@highest # load data bits 48-63 into gpr6 bits 16-31
+ ori 6,6,data_value@higher # load data bits 32-47 into gpr6 bits 0-15
+
+ rldicr 6,6,32,31 # rotate gpr6's low word(0-31)into 32-63
+
+ oris 6,6,data_value@h
+ ori 6,6,data_value@l
+
+ lwa 10,0(6)
+ cmpdi cr7,10,8
+ bne cr7,.L2
+ cmpwi cr7,7,7
+ bne cr7,.L2
+
+ li 0,1
+ li 3,3
+ sc
+ b .L1
+
+.L2: b .L1 # failure
+.L1:
+ ld 1,0(1) # restore the stack frame pointer value
+ # restore the LR register
+ ld 0,16(1)
+ mtlr 0
+
+ ld 31,-8(1)
+ blr # Not really supposed to get here
+
+ .data
+data_value: .long 3
+
+#endif
+
+.section .note.GNU-stack,"",@progbits
+
--- /dev/null 2006-08-17 19:07:50.484771500 +0800
+++ frysk-core/frysk/pkglibexecdir/funit-ppc64-regs.S 2006-08-18 15:54:27.000000000 +0800
@@ -0,0 +1,70 @@
+// This file is part of the program FRYSK.
+//
+// Copyright 2006 IBM Corp.
+//
+// FRYSK is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// FRYSK is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FRYSK; if not, write to the Free Software Foundation,
+// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// In addition, as a special exception, Red Hat, Inc. gives You the
+// additional right to link the code of FRYSK with code not covered
+// under the GNU General Public License ("Non-GPL Code") and to
+// distribute linked combinations including the two, subject to the
+// limitations in this paragraph. Non-GPL Code permitted under this
+// exception must only link to the code of FRYSK through those well
+// defined interfaces identified in the file named EXCEPTION found in
+// the source code files (the "Approved Interfaces"). The files of
+// Non-GPL Code may instantiate templates or use macros or inline
+// functions from the Approved Interfaces without causing the
+// resulting work to be covered by the GNU General Public
+// License. Only Red Hat, Inc. may make changes or additions to the
+// list of Approved Interfaces. You must obey the GNU General Public
+// License in all respects for all of the FRYSK code and other code
+// used in conjunction with FRYSK except the Non-GPL Code covered by
+// this exception. If you modify this file, you may extend this
+// exception to your version of the file, but you are not obligated to
+// do so. If you do not wish to provide this exception without
+// modification, you must delete this exception statement from your
+// version and license this file solely under the GPL without
+// exception.
+
+.text # section declaration - begin code
+
+ .global main
+#ifdef __powerpc64__
+ .section ".opd","aw"
+ .align 3
+#endif
+
+main:
+
+#ifdef __powerpc64__
+ .quad ._main,.TOC.@tocbase,0
+ .previous
+
+ .global ._main
+._main:
+
+ li 0,1 # syscall number (sys_exit)
+ li 3,1 # first argument: exit code
+ li 4,4 # gpr4=4
+
+ # shift left 36-bits for the value: 0x1
+ # test whether the low 32-bits and high 32-bits can be accessed right
+ li 5,1 # gpr5=1
+ sldi 5,5,36
+ sc # call kernel
+
+#endif
+
+.section .note.GNU-stack,"",@progbits
+