summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/ppe/pk/ppe42
diff options
context:
space:
mode:
authorShakeeb <shakeebbk@in.ibm.com>2016-09-01 06:24:44 -0500
committerAMIT J. TENDOLKAR <amit.tendolkar@in.ibm.com>2016-09-01 07:48:28 -0400
commit5e83bcb5cf9d400739cfb2beaab1a3173e8cafb2 (patch)
treeb3d6cd12b5eb0c92404ae5ac0352bb360b38fa95 /src/import/chips/p9/procedures/ppe/pk/ppe42
parent1008ef70a71fcfdec398ff30923d5025991c85f4 (diff)
downloadtalos-sbe-5e83bcb5cf9d400739cfb2beaab1a3173e8cafb2.tar.gz
talos-sbe-5e83bcb5cf9d400739cfb2beaab1a3173e8cafb2.zip
SBE move import`
Change-Id: I726951318cdb19fd445af2f7910e0d6872eff18c Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/29086 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Sachin Gupta <sgupta2m@in.ibm.com> Reviewed-by: AMIT J. TENDOLKAR <amit.tendolkar@in.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/ppe/pk/ppe42')
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/Makefile50
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/div64.S272
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/eabi.c46
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/endian.h48
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/math.c206
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/pk_panic_codes.h340
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/pk_port_types.h65
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/pkppe42files.mk72
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42.h813
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_asm.h634
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_boot.S193
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_cache.h126
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_context.h228
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_core.c157
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_exceptions.S525
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.c369
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.h98
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_init.c102
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq.h244
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq_core.c71
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_msr.h112
-rwxr-xr-xsrc/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.c103
-rwxr-xr-xsrc/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.h158
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_spr.h205
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.c351
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.h73
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_thread_init.S134
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_timebase.S140
-rw-r--r--src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42math.h84
29 files changed, 6019 insertions, 0 deletions
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/Makefile b/src/import/chips/p9/procedures/ppe/pk/ppe42/Makefile
new file mode 100644
index 00000000..60f8d7f8
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/Makefile
@@ -0,0 +1,50 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: import/chips/p9/procedures/ppe/pk/ppe42/Makefile $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2016
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+# This Makefile is designed to be invoked with the -I argument set to
+# the location of the "pk.mk" for the build
+
+include img_defs.mk
+include pkppe42files.mk
+
+ifeq "$(PK_TIMER_SUPPORT)" "1"
+PPE42_OBJECTS += ${PPE42-TIMER-C-SOURCES:.c=.o} ${PPE42-TIMER-S-SOURCES:.S=.o}
+endif
+
+ifeq "$(PK_THREAD_SUPPORT)" "1"
+PPE42_OBJECTS += ${PPE42-THREAD-C-SOURCES:.c=.o} ${PPE42-THREAD-S-SOURCES:.S=.o}
+endif
+
+OBJS := $(addprefix $(OBJDIR)/, $(PPE42_OBJECTS))
+
+all: $(OBJS)
+
+$(OBJS) $(OBJS:.o=.d): | $(OBJDIR)
+
+$(OBJDIR):
+ mkdir -p $(OBJDIR)
+
+ifneq ($(MAKECMDGOALS),clean)
+include $(OBJS:.o=.d)
+endif
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/div64.S b/src/import/chips/p9/procedures/ppe/pk/ppe42/div64.S
new file mode 100644
index 00000000..cf19fa6e
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/div64.S
@@ -0,0 +1,272 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/div64.S $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file div64.S
+/// \brief Unsigned 64/64 bit division
+///
+/// This is IBM code, originally part of OS Open. The code has been slightly
+/// modified from its original form, both to be compatible with PK and to
+/// change the function prototype slightly.
+///
+/// The code was provided by Matt Tyrlik in Raleigh.
+
+/* @#START#@
+**
+** PSCN (Power Service and Control Network)
+** Cage Controller OS Open Code
+**
+** (C) Copyright International Business Machines Corporation 2002
+** All Rights Reserved
+** Licensed Material - Program Property of I B M
+** Refer to copyright instructions: Form G120-2083
+**
+** Module:
+** div64.s
+**
+** Description:
+** Divide 64 bit unsigned values on 32 bit CPU
+** div64(uint64_t dividen, uint64_t divisor,
+** uint64_t *quotient, uint64_t *remainder)
+**
+** Original source from:
+** "The PowerPC Compiler Writer's Guide", pp62-65 by
+** Steve Hoxey, Faraydon Karim, Bill Hay, Hank Warray,
+** published by Warthman Associates, 240 Hamilton Avenue,
+** Palo Alto, CA 94301, USA, 1996 for IBM.
+** ISBN 0-9649654-0-2.
+**
+** This version checks for divisor equal to zero.
+**
+** Environment:
+** OS Open (XCOFF)
+**
+** Linkage:
+** AIX 4.3.3
+**
+** @author
+** Thomas Richter
+**
+** History:
+** Date Author Description
+** -----------------------------------------------------------------------------
+** 23-Sep-02 Richter Created
+**
+** @#END#@*/
+
+ .nolist
+#include "pk.h"
+ .list
+
+ .global_function __ppe42_udiv64
+
+ /*
+ ** Code comment notation:
+ ** msw = most-significant (high-order) word, i.e. bits 0..31
+ ** lsw = least-significant (low-order) word, i.e. bits 32..63
+ ** LZ = Leading Zeroes
+ ** SD = Significant Digits
+ **
+ ** R3:R4 = Input parameter, dividend.
+ ** R5:R6 = Input parameter, divisor.
+ ** R7 = Output parameter, pointer to quotient.
+ ** R8 = Output parameter, pointer to remainder.
+ **
+ ** Pointer arguments point to a uint64_t.
+ **
+ ** Division is achieved using a shift/rotate/substract algorithsm
+ ** described above.
+ ** The registers are used as follows:
+ ** R3:R4 = dividend (upper 32bits:lower 32bits)
+ ** R5:R6 = divisor (upper 32bits:lower 32bits)
+ **
+ ** R7:R8 = temporary 64 bit register (upper 32bits:lower 32bits)
+ ** count the number of leading 0s in the dividend
+ **
+ ** Here is the description from the book. The dividend is placed
+ ** in the low order part of a 4 (32bit) register sequence named
+ ** tmp-high:tmp-low:dividend-high:dividend:low or tmp:dvd for short.
+ **
+ ** Each iteration includes the following steps:
+ ** 1. Shift tmp:dvd by one bit to the left.
+ ** 2. Subtract the divisor from tmp. This is a 64 bit operation.
+ ** 3. If result is greater than or equal, place result in tmp and
+ ** set the low order bit of dividend
+ ** 4. If result is negative, do not modify tmp and
+ ** clear the low order bit of dividend
+ ** 5. If the number of iterations is less than the width of the
+ ** dividend, goto step 1.
+ **
+ ** Now the algorithm can be improved by reducing the number of
+ ** iterations to be executed.
+ ** 1. Calculate the leading zeroes of the dividend.
+ ** 2. Calculate the leading zeroes of the divisor.
+ ** 3. Calculate the significant ones of the dividend.
+ ** 4. Calculate the significant ones of the divisor.
+ **
+ ** Initial tmp := dvd >> (dvd.SD - dvs.SD)
+ ** Initial dvd := dvd << (dvd.LZ + dvs.SD)
+ ** Loops: dvd.SD - dvs.SD.
+ **
+ ** Warning: Special care must be taken if dvd.LZ == dvs.LZ. The code
+ ** below does so by reducing the number of dvs.SD by one. This leads
+ ** to the loop being executed 1 more time than really necessary,
+ ** but avoids to check for the case when dvd.LZ == dvs.LZ.
+ ** This case (dvd.LZ == dvs.LZ) only checks for the number of leading
+ ** zeroes, but does not check if dividend is really greater than the
+ ** divisor.
+ ** Consider 16/17, both have an LZ value of 59. The code sets dvs.LZ
+ ** 60. This resutls in dvs.SD to 4, thus one iteration after which
+ ** tmp is the remainder 16.
+ */
+
+__ppe42_udiv64: // PK
+
+ /* push R30 & R31 onto the stack */
+ stwu r1, -16(r1)
+ stvd r30, 8(r1)
+
+ /* Save result pointers on volatile spare registers */
+ ori r31, r8, 0 /* Save remainder address */
+ ori r30, r7, 0 /* Save quotient address */
+
+ /* count the number of leading 0s in the dividend */
+ cmpwi cr0, r3, 0 /* dvd.msw == 0? */
+ cntlzw r0, r3 /* R0 = dvd.msw.LZ */
+ cntlzw r9, r4 /* R9 = dvd.lsw.LZ */
+ bne cr0, lab1 /* if(dvd.msw == 0) dvd.LZ = dvd.msw.LZ */
+ addi r0, r9, 32 /* dvd.LZ = dvd.lsw.LZ + 32 */
+lab1:
+ /* count the number of leading 0s in the divisor */
+ cmpwi cr0, r5, 0 /* dvd.msw == 0? */
+ cntlzw r9, r5 /* R9 = dvs.msw.LZ */
+ cntlzw r10, r6 /* R10 = dvs.lsw.LZ */
+ bne cr0, lab2 /* if(dvs.msw == 0) dvs.LZ = dvs.msw.LZ */
+ cmpwi cr0, r6, 0 /* dvd.lsw == 0? */
+ beq cr0, lab10 /* dvs.msw == 0 */
+ addi r9, r10, 32 /* dvs.LZ = dvs.lsw.LZ + 32 */
+
+lab2:
+ /* Determine shift amounts to minimize the number of iterations */
+ cmpw cr0, r0, r9 /* Compare dvd.LZ to dvs.LZ */
+ subfic r10, r0, 64 /* R10 = dvd.SD */
+ bgt cr0, lab9 /* if(dvs > dvd) quotient = 0 */
+ addi r9, r9, 1 /* See comment above. ++dvs.LZ (or --dvs.SD) */
+ subfic r9, r9, 64 /* R9 = dvs.SD */
+ add r0, r0, r9 /* (dvd.LZ + dvs.SD) = left shift of dvd for */
+ /* initial dvd */
+ subf r9, r9, r10 /* (dvd.SD - dvs.SD) = right shift of dvd for */
+ /* initial tmp */
+ mtctr r9 /* Number of iterations = dvd.SD - dvs.SD */
+
+ /* R7:R8 = R3:R4 >> R9 */
+ cmpwi cr0, r9, 32 /* compare R9 to 32 */
+ addi r7, r9, -32
+ blt cr0, lab3 /* if(R9 < 32) jump to lab3 */
+ srw r8, r3, r7 /* tmp.lsw = dvd.msw >> (R9 - 32) */
+ addi r7, r0, 0 /* tmp.msw = 0 */
+ b lab4
+
+lab3:
+ srw r8, r4, r9 /* R8 = dvd.lsw >> R9 */
+ subfic r7, r9, 32
+ slw r7,r3,r7 /* R7 = dvd.msw << 32 - R9 */
+ or r8, r8,r7 /* tmp.lsw = R8 | R7 */
+ srw r7,r3,r9 /* tmp.msw = dvd.msw >> R9 */
+lab4:
+ /* R3:R4 = R3:R4 << R0 */
+ cmpwi cr0, r0, 32 /* Compare R0 to 32 */
+ addic r9, r0, -32
+ blt cr0, lab5 /* if(R0 < 32) jump to lab5 */
+ slw r3, r4, r9 /* dvd.msw = dvd.lsw << R9 */
+ addi r4, r0, 0 /* dvd.lsw = 0 */
+ b lab6
+
+lab5:
+ slw r3, r3, r0 /* r3 = dvd.msw << r0 */
+ subfic r9, r0, 32
+ srw r9, r4, r9 /* r9 = dvd.lsw >> 32 - r0 */
+ or r3, r3, r9 /* dvd.msw = r3 | r9 */
+ slw r4, r4, r0 /* dvd.lsw = dvd.lsw << r0 */
+lab6:
+ /* Restoring division shift and subtract loop */
+ addi r10, r0, -1 /* r10 = -1 */
+ addic r7, r7, 0 /* Clear carry bit before loop starts */
+lab7:
+ /*
+ ** tmp:dvd is considered one large register
+ ** each portion is shifted left 1 bit by adding it to itself
+ ** adde sums the carry from the previous and creates a new carry
+ */
+ adde r4, r4, r4 /* Shift dvd.lsw left 1 bit */
+ adde r3, r3, r3 /* Shift dvd.msw to left 1 bit */
+ adde r8, r8, r8 /* Shift tmp.lsw to left 1 bit */
+ adde r7, r7, r7 /* Shift tmp.msw to left 1 bit */
+ subfc r0, r6, r8 /* tmp.lsw - dvs.lsw */
+ subfe. r9, r5, r7 /* tmp.msw - dvs.msw */
+ blt cr0, lab8 /* if(result < 0) clear carry bit */
+ or r8, r0, r0 /* Move lsw */
+ or r7, r9, r9 /* Move msw */
+ addic r0, r10, 1 /* Set carry bit */
+
+lab8:
+ bdnz lab7
+
+ /* Write quotient and remainder */
+ adde r4, r4, r4 /* quo.lsw (lsb = CA) */
+ adde r3, r3, r3 /* quo.msw (lsb from lsw) */
+ stw r4, 4(r30)
+ stw r3, 0(r30)
+ stw r8, 4(r31) /* rem.lsw */
+ stw r7, 0(r31) /* rem.msw */
+ b lab11
+
+lab9:
+ /* Qoutient is 0, divisor > dividend */
+ addi r0, r0, 0
+ stw r3, 0(r31) /* Store remainder */
+ stw r4, 4(r31)
+ stw r0, 0(r30) /* Set quotient to zero */
+ stw r0, 4(r30)
+ b lab11
+
+lab10:
+ /* Divisor is 0 */
+ addi r0, r0, -1
+ stw r0, 0(r31) /* Set remainder to zero */
+ stw r0, 4(r31)
+ stw r0, 0(r30) /* Set quotient to zero */
+ stw r0, 4(r30)
+
+lab11:
+ //pop r30 & r31 from stack
+ lvd r30, 8(r1)
+ lwz r1, 0(r1)
+ blr
+ .epilogue __ppe42_udiv64
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/eabi.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/eabi.c
new file mode 100644
index 00000000..140cc2be
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/eabi.c
@@ -0,0 +1,46 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/eabi.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+// assuming link script instructs the c++ compiler to put
+// ctor_start_address and ctor_end_address in .rodata
+
+//extern void (*ctor_start_address)() __attribute__ ((section (".rodata")));
+//extern void (*ctor_end_address)() __attribute__((section(".rodata")));
+#ifdef __cplusplus
+ extern "C"
+#endif
+__attribute__((weak)) void __eabi()
+{
+ // This is the default eabi and can be overridden.
+ // eabi environment is already set up by the PK kernel
+ // Call static C++ constructors if you use C++ global/static objects
+
+ //void(**ctors)() = &ctor_start_address;
+ //while(ctors != &ctor_end_address)
+ //{
+ // (*ctors)();
+ // ctors++;
+ //}
+}
+
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/endian.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/endian.h
new file mode 100644
index 00000000..dade05cf
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/endian.h
@@ -0,0 +1,48 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/endian.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __ENDIAN_H__
+#define __ENDIAN_H__
+
+#ifndef __PPE42__
+ #include_next <endian.h>
+#else
+ // Currently not provided with PPE42 native compiler as PPE42
+ // is compiled with no clib support.
+ // endian.h provides:
+ // htobe16,
+ // htole16,
+ // be16toh,
+ // le16toh,
+ // htobe32,
+ // htole32,
+ // be32toh,
+ // le32toh,
+ // htobe64,
+ // htole64,
+ // be64toh,
+ // le64toh
+#endif
+
+#endif
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/math.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/math.c
new file mode 100644
index 00000000..1cddc624
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/math.c
@@ -0,0 +1,206 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/math.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include "ppe42math.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+unsigned long
+udivmodsi4(unsigned long num, unsigned long den, int modwanted)
+{
+ unsigned long bit = 1;
+ unsigned long res = 0;
+
+ while (den < num && bit && !(den & (1L << 31)))
+ {
+ den <<= 1;
+ bit <<= 1;
+ }
+
+ while (bit)
+ {
+ if (num >= den)
+ {
+ num -= den;
+ res |= bit;
+ }
+
+ bit >>= 1;
+ den >>= 1;
+ }
+
+ if (modwanted)
+ {
+ return num;
+ }
+
+ return res;
+}
+
+// 64 bit divide. Note: TBD add when needed
+//unsigned long long __udivdi3(unsigned long long a, unsigned long long b)
+//{
+// unsigned long long c = 0;
+// return c;
+//}
+
+// 32 bit unsigned integer divide
+unsigned long __udivsi3(unsigned long a, unsigned long b)
+{
+ return udivmodsi4(a, b, 0);
+}
+
+// 32 bit modulus
+unsigned long __umodsi3(unsigned long a, unsigned long b)
+{
+ return udivmodsi4(a, b, 1);
+}
+
+// 32 bit signed divide
+int __divsi3(int _a, int _b)
+{
+ register unsigned long neg = 0;
+
+ if(_a & 0x80000000)
+ {
+ neg = !neg;
+ _a = (~_a) + 1;
+ }
+
+ if(_b & 0x80000000)
+ {
+ _b = (~_b) + 1;
+ neg = !neg;
+ }
+
+ int c = __udivsi3((unsigned long)_a, (unsigned long)_b);
+
+ if(neg)
+ {
+ c = (~c) + 1;
+ }
+
+ return c;
+}
+
+// 32 bit unsigned mutiply
+unsigned long __umulsi3(unsigned long _a, unsigned long _b)
+{
+ register unsigned long a = _a;
+ register unsigned long b = _b;
+ register unsigned long c;
+ register unsigned long d;
+ asm volatile("mullhwu %0, %1, %2" : "=r"(c) : "r"(a), "r"(b));
+ d = c;
+ c = a >> 16;
+ asm volatile("mullhwu %0, %1, %2" : "=r"(c) : "r"(c), "r"(b));
+ d += (c << 16);
+ c = b >> 16;
+ asm volatile("mullhwu %0, %1, %2" : "=r"(c) : "r"(c), "r"(a));
+ d += (c << 16);
+ return d;
+}
+
+// 32 bit signed multiply
+unsigned int __mulsi3(unsigned int _a, unsigned int _b)
+{
+ register unsigned long neg = 0;
+ register unsigned long a = _a;
+ register unsigned long b = _b;
+ register unsigned long c;
+ register unsigned long d;
+
+ if(a & 0x80000000)
+ {
+ a = (~a) + 1;
+ neg = !neg;
+ }
+
+ if(b & 0x80000000)
+ {
+ b = (~b) + 1;
+ neg = !neg;
+ }
+
+ asm volatile("mullhwu %0, %1, %2" : "=r"(c) : "r"(a), "r"(b));
+ d = c;
+ c = a >> 16;
+ asm volatile("mullhwu %0, %1, %2" : "=r"(c) : "r"(c), "r"(b));
+ d += (c << 16);
+ c = b >> 16;
+ asm volatile("mullhwu %0, %1, %2" : "=r"(c) : "r"(c), "r"(a));
+ d += (c << 16);
+
+ if(neg)
+ {
+ d = (~d) + 1;
+ }
+
+ return d;
+}
+
+// 64 bit signed multiply
+unsigned long long __muldi3(unsigned long long _a, unsigned long long _b)
+{
+ unsigned long long sum = 0;
+
+ while(_a)
+ {
+ if(_a & 1)
+ {
+ sum += _b;
+ }
+
+ _a >>= 1;
+ _b <<= 1;
+ }
+
+ return sum;
+}
+
+//float __mulsf3(float _a , float _b)
+//{
+// // floating point math
+// return 0.0;
+//}
+
+//float __subsf3(float _a, float _b)
+//{
+// // floating point sub
+// return 0.0;
+//}
+
+//unsigned long __fixsfsi (float _a)
+//{
+// // float to int
+// return 0;
+//}
+
+#ifdef __cplusplus
+};
+#endif
+
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/pk_panic_codes.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/pk_panic_codes.h
new file mode 100644
index 00000000..0e079657
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/pk_panic_codes.h
@@ -0,0 +1,340 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/pk_panic_codes.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PK_PANIC_CODES_H__
+#define __PK_PANIC_CODES_H__
+
+// On PPE42, PANIC codes are stored as part of the trap word instruction.
+// tw 31, RA, RB Where RA and RB would used to encode the trap code.
+// There are 16 valid gprs on PP42, so this gives 256 possible trap codes.
+// The trap code is defined as a two byte code defined as 0xYYZZ where YY
+// is encoded into the RA field and ZZ is incoded into the RB field
+// YY and ZZ are limited to the values:
+// 00,01,02,03,04,05,06,07,08,09,0a,0d,1c,1d,1e,1f (valid gpr ids)
+//
+// To add a new panic code, select an unused values and rename it.
+// This enum contains all the valid values that can be used. Using a
+// panic code not in this list will result in a compiler/assembler error.
+#ifndef __ASSEMBLER__
+
+typedef enum
+{
+ PPE42_MACHINE_CHECK_PANIC = 0x0001,
+ PPE42_DATA_STORAGE_PANIC = 0x0002,
+ PPE42_INSTRUCTION_STORAGE_PANIC = 0x0003,
+ PPE42_DATA_ALIGNMENT_PANIC = 0x0004,
+ PK_BOOT_VECTORS_NOT_ALIGNED = 0x0005,
+ PK_DEFAULT_IRQ_HANDLER = 0x0006,
+ PK_DEFAULT_SPECIAL_HANDLER = 0x0007,
+ PPE42_PHANTOM_INTERRUPT = 0x0008,
+ PPE42_ILLEGAL_INSTRUCTION = 0x0009,
+ PK_UNUSED_000a = 0x000a,
+ PK_UNUSED_000d = 0x000d,
+ PK_UNUSED_001c = 0x001c,
+ PK_UNUSED_001d = 0x001d,
+ PK_UNUSED_001e = 0x001e,
+ PK_UNUSED_001f = 0x001f,
+
+ // API return codes
+ PK_ILLEGAL_CONTEXT_THREAD_CONTEXT = 0x0100,
+ PK_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT = 0x0101,
+ PK_ILLEGAL_CONTEXT_THREAD = 0x0102,
+ PK_ILLEGAL_CONTEXT_TIMER = 0x0103,
+ PK_INVALID_THREAD_AT_RESUME1 = 0x0104,
+ PK_INVALID_THREAD_AT_RESUME2 = 0x0105,
+ PK_INVALID_THREAD_AT_SUSPEND1 = 0x0106,
+ PK_INVALID_THREAD_AT_SUSPEND2 = 0x0107,
+ PK_INVALID_THREAD_AT_DELETE = 0x0108,
+ PK_INVALID_THREAD_AT_INFO = 0x0109,
+ PK_INVALID_THREAD_AT_CHANGE = 0x010a,
+ PK_INVALID_THREAD_AT_SWAP1 = 0x010d,
+ PK_INVALID_THREAD_AT_SWAP2 = 0x011c,
+ PK_INVALID_THREAD_AT_CREATE = 0x011d,
+ PK_INVALID_SEMAPHORE_AT_POST = 0x011e,
+ PK_INVALID_SEMAPHORE_AT_PEND = 0x011f,
+ PK_INVALID_SEMAPHORE_AT_RELEASE = 0x0200,
+ PK_INVALID_SEMAPHORE_AT_INFO = 0x0201,
+ PK_INVALID_SEMAPHORE_AT_CREATE = 0x0202,
+ PK_INVALID_TIMER_AT_SCHEDULE = 0x0203,
+ PK_INVALID_TIMER_AT_CANCEL = 0x0204,
+ PK_INVALID_TIMER_AT_INFO = 0x0205,
+ PK_INVALID_TIMER_AT_CREATE = 0x0206,
+ PK_INVALID_ARGUMENT_IRQ_SETUP = 0x0207,
+ PK_INVALID_ARGUMENT_IRQ_HANDLER = 0x0208,
+ PK_INVALID_ARGUMENT_INTERRUPT = 0x0209,
+ PK_INVALID_ARGUMENT_CONTEXT_SET = 0x020a,
+ PK_INVALID_ARGUMENT_CONTEXT_GET = 0x020d,
+ PK_INVALID_ARGUMENT_FIT = 0x021c,
+ PK_INVALID_ARGUMENT_WATCHDOG = 0x021d,
+ PK_INVALID_ARGUMENT_INIT = 0x021e,
+ PK_INVALID_ARGUMENT_SEMAPHORE = 0x021f,
+ PK_INVALID_ARGUMENT_THREAD_CHANGE = 0x0300,
+ PK_INVALID_ARGUMENT_THREAD_PRIORITY = 0x0301,
+ PK_INVALID_ARGUMENT_THREAD1 = 0x0302,
+ PK_INVALID_ARGUMENT_THREAD2 = 0x0303,
+ PK_INVALID_ARGUMENT_THREAD3 = 0x0304,
+ PK_STACK_OVERFLOW = 0x0305,
+ PK_TIMER_ACTIVE = 0x0306,
+ PK_TIMER_NOT_ACTIVE = 0x0307,
+ PK_PRIORITY_IN_USE_AT_RESUME = 0x0308,
+ PK_PRIORITY_IN_USE_AT_CHANGE = 0x0309,
+ PK_PRIORITY_IN_USE_AT_SWAP = 0x030a,
+ PK_SEMAPHORE_OVERFLOW = 0x030d,
+ PK_SEMAPHORE_PEND_NO_WAIT = 0x031c,
+ PK_SEMAPHORE_PEND_TIMED_OUT = 0x031d,
+ PK_SEMAPHORE_PEND_WOULD_BLOCK = 0x031e,
+ PK_INVALID_DEQUE_SENTINEL = 0x031f,
+ PK_INVALID_DEQUE_ELEMENT = 0x0400,
+ PK_INVALID_OBJECT = 0x0401,
+
+ // PK Kernel panics
+ PK_NO_TIMER_SUPPORT = 0x0402,
+ PK_START_THREADS_RETURNED = 0x0403,
+ PK_UNIMPLEMENTED = 0x0404,
+ PK_SCHEDULING_INVARIANT = 0x0405,
+ PK_TIMER_HANDLER_INVARIANT = 0x0406,
+ PK_THREAD_TIMEOUT_STATE = 0x0407,
+
+ // PK
+ PK_UNUSED_0408 = 0x0408,
+ PK_UNUSED_0409 = 0x0409,
+ PK_UNUSED_040a = 0x040a,
+ PK_UNUSED_040d = 0x040d,
+ PK_UNUSED_041c = 0x041c,
+ PK_UNUSED_041d = 0x041d,
+ PK_UNUSED_041e = 0x041e,
+ PK_UNUSED_041f = 0x041f,
+
+ // Sync panic codes
+ SYNC_INVALID_OBJECT = 0x0500,
+ SYNC_INVALID_ARGUMENT = 0x0501,
+ SYNC_BARRIER_PEND_TIMED_OUT = 0x0502,
+ SYNC_BARRIER_OVERFLOW = 0x0503,
+ SYNC_BARRIER_UNDERFLOW = 0x0504,
+ SYNC_BARRIER_INVARIANT = 0x0505,
+ SYNC_SHARED_UNDERFLOW = 0x0506,
+
+ OCCHW_INSTANCE_MISMATCH = 0x0507,
+ OCCHW_IRQ_ROUTING_ERROR = 0x0508,
+ OCCHW_XIR_INVALID_POINTER = 0x0509,
+ OCCHW_XIR_INVALID_GPE = 0x050a,
+
+ PK_UNUSED_050d = 0x050d,
+ PK_UNUSED_051c = 0x051c,
+ PK_UNUSED_051d = 0x051d,
+ PK_UNUSED_051e = 0x051e,
+ PK_UNUSED_051f = 0x051f,
+
+ PK_UNUSED_0600 = 0x0600,
+ PK_UNUSED_0601 = 0x0601,
+ PK_UNUSED_0602 = 0x0602,
+ PK_UNUSED_0603 = 0x0603,
+ PK_UNUSED_0604 = 0x0604,
+ PK_UNUSED_0605 = 0x0605,
+ PK_UNUSED_0606 = 0x0606,
+ PK_UNUSED_0607 = 0x0607,
+ PK_UNUSED_0608 = 0x0608,
+ PK_UNUSED_0609 = 0x0609,
+ PK_UNUSED_060a = 0x060a,
+ PK_UNUSED_060d = 0x060d,
+ PK_UNUSED_061c = 0x061c,
+ PK_UNUSED_061d = 0x061d,
+ PK_UNUSED_061e = 0x061e,
+ PK_UNUSED_061f = 0x061f,
+
+ PK_UNUSED_0700 = 0x0700,
+ PK_UNUSED_0701 = 0x0701,
+ PK_UNUSED_0702 = 0x0702,
+ PK_UNUSED_0703 = 0x0703,
+ PK_UNUSED_0704 = 0x0704,
+ PK_UNUSED_0705 = 0x0705,
+ PK_UNUSED_0706 = 0x0706,
+ PK_UNUSED_0707 = 0x0707,
+ PK_UNUSED_0708 = 0x0708,
+ PK_UNUSED_0709 = 0x0709,
+ PK_UNUSED_070a = 0x070a,
+ PK_UNUSED_070d = 0x070d,
+ PK_UNUSED_071c = 0x071c,
+ PK_UNUSED_071d = 0x071d,
+ PK_UNUSED_071e = 0x071e,
+ PK_UNUSED_071f = 0x071f,
+
+ PK_UNUSED_0800 = 0x0800,
+ PK_UNUSED_0801 = 0x0801,
+ PK_UNUSED_0802 = 0x0802,
+ PK_UNUSED_0803 = 0x0803,
+ PK_UNUSED_0804 = 0x0804,
+ PK_UNUSED_0805 = 0x0805,
+ PK_UNUSED_0806 = 0x0806,
+ PK_UNUSED_0807 = 0x0807,
+ PK_UNUSED_0808 = 0x0808,
+ PK_UNUSED_0809 = 0x0809,
+ PK_UNUSED_080a = 0x080a,
+ PK_UNUSED_080d = 0x080d,
+ PK_UNUSED_081c = 0x081c,
+ PK_UNUSED_081d = 0x081d,
+ PK_UNUSED_081e = 0x081e,
+ PK_UNUSED_081f = 0x081f,
+
+ PK_UNUSED_0900 = 0x0900,
+ PK_UNUSED_0901 = 0x0901,
+ PK_UNUSED_0902 = 0x0902,
+ PK_UNUSED_0903 = 0x0903,
+ PK_UNUSED_0904 = 0x0904,
+ PK_UNUSED_0905 = 0x0905,
+ PK_UNUSED_0906 = 0x0906,
+ PK_UNUSED_0907 = 0x0907,
+ PK_UNUSED_0908 = 0x0908,
+ PK_UNUSED_0909 = 0x0909,
+ PK_UNUSED_090a = 0x090a,
+ PK_UNUSED_090d = 0x090d,
+ PK_UNUSED_091c = 0x091c,
+ PK_UNUSED_091d = 0x091d,
+ PK_UNUSED_091e = 0x091e,
+ PK_UNUSED_091f = 0x091f,
+
+ PK_UNUSED_0a00 = 0x0a00,
+ PK_UNUSED_0a01 = 0x0a01,
+ PK_UNUSED_0a02 = 0x0a02,
+ PK_UNUSED_0a03 = 0x0a03,
+ PK_UNUSED_0a04 = 0x0a04,
+ PK_UNUSED_0a05 = 0x0a05,
+ PK_UNUSED_0a06 = 0x0a06,
+ PK_UNUSED_0a07 = 0x0a07,
+ PK_UNUSED_0a08 = 0x0a08,
+ PK_UNUSED_0a09 = 0x0a09,
+ PK_UNUSED_0a0a = 0x0a0a,
+ PK_UNUSED_0a0d = 0x0a0d,
+ PK_UNUSED_0a1c = 0x0a1c,
+ PK_UNUSED_0a1d = 0x0a1d,
+ PK_UNUSED_0a1e = 0x0a1e,
+ PK_UNUSED_0a1f = 0x0a1f,
+
+ PK_UNUSED_0d00 = 0x0d00,
+ PK_UNUSED_0d01 = 0x0d01,
+ PK_UNUSED_0d02 = 0x0d02,
+ PK_UNUSED_0d03 = 0x0d03,
+ PK_UNUSED_0d04 = 0x0d04,
+ PK_UNUSED_0d05 = 0x0d05,
+ PK_UNUSED_0d06 = 0x0d06,
+ PK_UNUSED_0d07 = 0x0d07,
+ PK_UNUSED_0d08 = 0x0d08,
+ PK_UNUSED_0d09 = 0x0d09,
+ PK_UNUSED_0d0a = 0x0d0a,
+ PK_UNUSED_0d0d = 0x0d0d,
+ PK_UNUSED_0d1c = 0x0d1c,
+ PK_UNUSED_0d1d = 0x0d1d,
+ PK_UNUSED_0d1e = 0x0d1e,
+ PK_UNUSED_0d1f = 0x0d1f,
+
+ // The following are reserved for instance specific use.
+ // Each engine must define its own XXX_panic_codes.h
+ // Where XXX = SBE, CME, GPE0, GPE1, PGPE, SGPE
+ // They are listed here to show the valid trap values that
+ // can be used.
+
+ //_UNUSED_1c00 = 0x1c00,
+ //_UNUSED_1c01 = 0x1c01,
+ //_UNUSED_1c02 = 0x1c02,
+ //_UNUSED_1c03 = 0x1c03,
+ //_UNUSED_1c04 = 0x1c04,
+ //_UNUSED_1c05 = 0x1c05,
+ //_UNUSED_1c06 = 0x1c06,
+ //_UNUSED_1c07 = 0x1c07,
+ //_UNUSED_1c08 = 0x1c08,
+ //_UNUSED_1c09 = 0x1c09,
+ //_UNUSED_1c0a = 0x1c0a,
+ //_UNUSED_1c0d = 0x1c0d,
+ //_UNUSED_1c1c = 0x1c1c,
+ //_UNUSED_1c1d = 0x1c1d,
+ //_UNUSED_1c1e = 0x1c1e,
+ //_UNUSED_1c1f = 0x1c1f,
+
+ //_UNUSED_1d00 = 0x1d00,
+ //_UNUSED_1d01 = 0x1d01,
+ //_UNUSED_1d02 = 0x1d02,
+ //_UNUSED_1d03 = 0x1d03,
+ //_UNUSED_1d04 = 0x1d04,
+ //_UNUSED_1d05 = 0x1d05,
+ //_UNUSED_1d06 = 0x1d06,
+ //_UNUSED_1d07 = 0x1d07,
+ //_UNUSED_1d08 = 0x1d08,
+ //_UNUSED_1d09 = 0x1d09,
+ //_UNUSED_1d0a = 0x1d0a,
+ //_UNUSED_1d0d = 0x1d0d,
+ //_UNUSED_1d1c = 0x1d1c,
+ //_UNUSED_1d1d = 0x1d1d,
+ //_UNUSED_1d1e = 0x1d1e,
+ //_UNUSED_1d1f = 0x1d1f,
+
+ //_UNUSED_1e00 = 0x1e00,
+ //_UNUSED_1e01 = 0x1e01,
+ //_UNUSED_1e02 = 0x1e02,
+ //_UNUSED_1e03 = 0x1e03,
+ //_UNUSED_1e04 = 0x1e04,
+ //_UNUSED_1e05 = 0x1e05,
+ //_UNUSED_1e06 = 0x1e06,
+ //_UNUSED_1e07 = 0x1e07,
+ //_UNUSED_1e08 = 0x1e08,
+ //_UNUSED_1e09 = 0x1e09,
+ //_UNUSED_1e0a = 0x1e0a,
+ //_UNUSED_1e0d = 0x1e0d,
+ //_UNUSED_1e1c = 0x1e1c,
+ //_UNUSED_1e1d = 0x1e1d,
+ //_UNUSED_1e1e = 0x1e1e,
+ //_UNUSED_1e1f = 0x1e1f,
+
+ //_UNUSED_1f00 = 0x1f00,
+ //_UNUSED_1f01 = 0x1f01,
+ //_UNUSED_1f02 = 0x1f02,
+ //_UNUSED_1f03 = 0x1f03,
+ //_UNUSED_1f04 = 0x1f04,
+ //_UNUSED_1f05 = 0x1f05,
+ //_UNUSED_1f06 = 0x1f06,
+ //_UNUSED_1f07 = 0x1f07,
+ //_UNUSED_1f08 = 0x1f08,
+ //_UNUSED_1f09 = 0x1f09,
+ //_UNUSED_1f0a = 0x1f0a,
+ //_UNUSED_1f0d = 0x1f0d,
+ //_UNUSED_1f1c = 0x1f1c,
+ //_UNUSED_1f1d = 0x1f1d,
+ //_UNUSED_1f1e = 0x1f1e,
+ //_UNUSED_1f1f = 0x1f1f
+} pkPanicCode_t;
+
+#else
+
+/// Assembler specific panic codes
+#define PPE42_MACHINE_CHECK_PANIC 0x0001
+#define PPE42_DATA_STORAGE_PANIC 0x0002
+#define PPE42_INSTRUCTION_STORAGE_PANIC 0x0003
+#define PPE42_DATA_ALIGNMENT_PANIC 0x0004
+
+#define PK_BOOT_VECTORS_NOT_ALIGNED 0x0005
+#define PPE42_ILLEGAL_INSTRUCTION 0x001c
+
+
+
+#endif // __ASSEMBLER__
+#endif
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/pk_port_types.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/pk_port_types.h
new file mode 100644
index 00000000..7a368d4e
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/pk_port_types.h
@@ -0,0 +1,65 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/pk_port_types.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PK_PORT_TYPES_H__
+#define __PK_PORT_TYPES_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file pk_port_types.h
+/// \brief Type definitions required by the PK port.
+///
+/// \todo GCC provides a portable version of cntlzw called __builtin_clz().
+/// We should make the PK priority queues portable by using this facility.
+///
+/// \todo I think that if more of the port-dependent types were moved here, we
+/// could break the circular dependencies in some of the header inclusion and
+/// simplify the way the PK/port/chip headers are included.
+
+/// An PkIrqId is an integer in the range of valid interrupts defined by the
+/// interrupt controller.
+
+typedef uint8_t PkIrqId;
+
+/// PK requires the port to define the type PkThreadQueue, which is a
+/// priority queue (where 0 is the highest priority). This queue must be able
+/// to handle PK_THREADS + 1 priorities (the last for the idle thread). The
+/// port must also define methods for clearing, insertion, deletion and min
+/// (with assumed legal priorities). The min operation returns PK_THREADS if
+/// the queue is empty. (Or a queue could be initialized with the PK_THREADS
+/// entry always present - PK code never tries to delete the idle thread from
+/// a thread queue).
+///
+/// These queues are used both for the run queue and the pending queue
+/// associated with every semaphore.
+///
+/// On PPE42 with 32 threads (implied), this is a job for a uint32_t and
+/// cntlzw().
+
+typedef uint32_t PkThreadQueue;
+
+#endif /* __PK_PORT_TYPES_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/pkppe42files.mk b/src/import/chips/p9/procedures/ppe/pk/ppe42/pkppe42files.mk
new file mode 100644
index 00000000..accca3f4
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/pkppe42files.mk
@@ -0,0 +1,72 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: import/chips/p9/procedures/ppe/pk/ppe42/pkppe42files.mk $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2016
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+# @file pkppe42files.mk
+#
+# @brief mk for including ppe42 object files
+#
+# @page ChangeLogs Change Logs
+# @section pkppe42files.mk
+# @verbatim
+#
+#
+# Change Log ******************************************************************
+# Flag Defect/Feature User Date Description
+# ------ -------------- ---------- ------------ -----------
+#
+# @endverbatim
+#
+##########################################################################
+# Include Files
+##########################################################################
+
+
+
+##########################################################################
+# Object Files
+##########################################################################
+PPE42-C-SOURCES = ppe42_core.c \
+ ppe42_init.c \
+ ppe42_irq_core.c\
+ ppe42_gcc.c\
+ ppe42_scom.c\
+ eabi.c\
+ math.c\
+ ppe42_string.c
+
+PPE42-S-SOURCES = ppe42_boot.S \
+ ppe42_exceptions.S\
+ div64.S\
+ ppe42_timebase.S
+
+PPE42-TIMER-C-SOURCES =
+PPE42-TIMER-S-SOURCES =
+
+PPE42-THREAD-C-SOURCES =
+PPE42-THREAD-S-SOURCES = ppe42_thread_init.S
+
+PPE42_THREAD_OBJECTS= $(PPE42-THREAD-S-SOURCES:.S=.o)
+PPE42_OBJECTS = $(PPE42-C-SOURCES:.c=.o)
+PPE42_OBJECTS += $(PPE42-S-SOURCES:.S=.o)
+
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42.h
new file mode 100644
index 00000000..6857ce10
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42.h
@@ -0,0 +1,813 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_H__
+#define __PPE42_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42.h
+/// \brief PPE42 port header for PK
+
+// Macros to define where declared code is actually compiled
+
+#ifdef __PPE42_CORE_C__
+ #define IF__PPE42_CORE_C__(x) x
+ #define UNLESS__PPE42_CORE_C__(x)
+#else
+ #define IF__PPE42_CORE_C__(x)
+ #define UNLESS__PPE42_CORE_C__(x) x
+#endif
+
+#ifdef __PPE42_IRQ_CORE_C__
+ #define IF__PPE42_IRQ_CORE_C__(x) x
+ #define UNLESS__PPE42_IRQ_CORE_C__(x)
+#else
+ #define IF__PPE42_IRQ_CORE_C__(x)
+ #define UNLESS__PPE42_IRQ_CORE_C__(x) x
+#endif
+
+#ifdef HWMACRO_GPE
+ #include "gpe.h"
+#elif defined(HWMACRO_STD)
+ #include "std.h"
+#elif defined(HWMACRO_PPE)
+ #include "ppe.h"
+#else
+ #error "Macro Type not specified. Are you building from the correct directory?"
+#endif
+
+
+#include "ppe42_asm.h"
+#include "ppe42_gcc.h"
+#include "ppe42_spr.h"
+#include "ppe42_msr.h"
+
+
+///start
+
+/// The synchronization macros defined here all create a compiler
+/// memory barrier that will cause GCC to flush/invalidate all memory data
+/// held in registers before the macro. This is consistent with other systems,
+/// e.g., the PowerPC Linux kernel, and is the safest way to define these
+/// macros.
+
+
+// Condition register fields
+
+#define CR_LT(n) (0x80000000u >> (4 * (n)))
+#define CR_GT(n) (0x40000000u >> (4 * (n)))
+#define CR_EQ(n) (0x20000000u >> (4 * (n)))
+#define CR_SO(n) (0x10000000u >> (4 * (n)))
+
+
+#ifndef __ASSEMBLER__
+
+#include "stdint.h"
+
+/// ssize_t is defined explictly rather than bringing in all of <unistd.h>
+#ifndef __ssize_t_defined
+ #define __ssize_t_defined
+ typedef int ssize_t;
+#endif
+
+/// A memory barrier
+#define barrier() asm volatile ("" : : : "memory")
+
+/// Ensure In-order Execution of Input/Output
+#define eieio() asm volatile ("sync" : : : "memory")
+
+/// Memory barrier
+#define sync() asm volatile ("sync" : : : "memory")
+
+/// Instruction barrier
+#define isync() asm volatile ("sync" : : : "memory")
+
+/// CouNT Leading Zeros Word
+#define cntlzw(x) \
+ ({uint32_t __x = (x); \
+ uint32_t __lzw; \
+ asm volatile ("cntlzw %0, %1" : "=r" (__lzw) : "r" (__x)); \
+ __lzw;})
+
+/// CouNT Leading Zeros : uint32_t
+static inline int
+cntlz32(uint32_t x)
+{
+ return cntlzw(x);
+}
+
+/// CouNT Leading Zeros : uint64_t
+static inline int
+cntlz64(uint64_t x)
+{
+ if (x > 0xffffffff)
+ {
+ return cntlz32(x >> 32);
+ }
+ else
+ {
+ return 32 + cntlz32(x);
+ }
+}
+
+
+/// 32-bit population count
+static inline int
+popcount32(uint32_t x)
+{
+ return __builtin_popcount(x);
+}
+
+
+/// 64-bit population count
+static inline int
+popcount64(uint64_t x)
+{
+ return __builtin_popcountll(x);
+}
+
+
+// NB: Normally we wouldn't like to force coercion inside a macro because it
+// can mask programming errors, but for the MMIO macros the addresses are
+// typically manifest constants or 32-bit unsigned integer expressions so we
+// embed the coercion to avoid warnings.
+
+/// 8-bit MMIO Write
+#define out8(addr, data) \
+ do {*(volatile uint8_t *)(addr) = (data);} while(0)
+
+/// 8-bit MMIO Read
+#define in8(addr) \
+ ({uint8_t __data = *(volatile uint8_t *)(addr); __data;})
+
+/// 16-bit MMIO Write
+#define out16(addr, data) \
+ do {*(volatile uint16_t *)(addr) = (data);} while(0)
+
+/// 16-bit MMIO Read
+#define in16(addr) \
+ ({uint16_t __data = *(volatile uint16_t *)(addr); __data;})
+
+/// 32-bit MMIO Write
+#define out32(addr, data) \
+ do {*(volatile uint32_t *)(addr) = (data);} while(0)
+
+/// 32-bit MMIO Read
+#define in32(addr) \
+ ({uint32_t __data = *(volatile uint32_t *)(addr); __data;})
+
+#ifdef HWMACRO_GPE
+
+/// 64-bit MMIO Write
+#define out64(addr, data) \
+ do { \
+ uint64_t __data = (data); \
+ volatile uint32_t *__addr_hi = (uint32_t *)(addr); \
+ volatile uint32_t *__addr_lo = __addr_hi + 1; \
+ *__addr_hi = (__data >> 32); \
+ *__addr_lo = (__data & 0xffffffff); \
+ } while(0)
+
+#else /* standard PPE's require a 64 bit write */
+
+/// 64-bit MMIO Write
+#define out64(addr, data) \
+ {\
+ uint64_t __d = (data); \
+ uint32_t* __a = (uint32_t*)(addr); \
+ asm volatile \
+ (\
+ "stvd %1, %0 \n" \
+ : "=o"(*__a) \
+ : "r"(__d) \
+ ); \
+ }
+
+#endif /* HWMACRO_GPE */
+
+#ifdef HWMACRO_GPE
+/// 64-bit MMIO Read
+#define in64(addr) \
+ ({ \
+ uint64_t __data; \
+ volatile uint32_t *__addr_hi = (uint32_t *)(addr); \
+ volatile uint32_t *__addr_lo = __addr_hi + 1; \
+ __data = *__addr_hi; \
+ __data = (__data << 32) | *__addr_lo; \
+ __data;})
+
+#else /* Standard PPE's require a 64 bit read */
+
+#define in64(addr) \
+ ({\
+ uint64_t __d; \
+ uint32_t* __a = (uint32_t*)(addr); \
+ asm volatile \
+ (\
+ "lvd %0, %1 \n" \
+ :"=r"(__d) \
+ :"o"(*__a) \
+ ); \
+ __d; \
+ })
+
+#endif /* HWMACRO_GPE */
+
+#endif /* __ASSEMBLER__ */
+
+#include "ppe42_irq.h"
+
+#ifndef __ASSEMBLER__
+
+/// Store revision information as a (global) string constant
+#define REVISION_STRING(symbol, rev) const char* symbol = rev;
+
+#else // __ASSEMBLER__
+// *INDENT-OFF*
+
+/// Store revision information as a global string constant
+ .macro .revision_string, symbol:req, rev:req
+ .pushsection .rodata
+ .balign 4
+ .global \symbol
+\symbol\():
+ .asciz "\rev"
+ .balign 4
+ .popsection
+ .endm
+
+// *INDENT-ON*
+#endif // __ASSEMBLER__
+
+
+
+#include "ppe42_context.h"
+#include "pk_panic_codes.h"
+
+// PPE42 stack characteristics for PK. The pre-pattern pattern is selected
+// to be easily recognizable yet be an illegal instruction.
+
+#define PK_STACK_DIRECTION -1
+#define PK_STACK_PRE_DECREMENT 1
+#define PK_STACK_ALIGNMENT 8
+#define PK_STACK_TYPE unsigned int
+#define PK_STACK_PATTERN 0x03abcdef
+
+// Kernel data structure offsets for assembler code
+
+#define PK_THREAD_OFFSET_SAVED_STACK_POINTER 0
+#define PK_THREAD_OFFSET_STACK_LIMIT 4
+#define PK_THREAD_OFFSET_STACK_BASE 8
+
+
+// Application-overrideable definitions
+
+/// The default thread machine context has MSR[CE], MSR[EE] and MSR[ME] set,
+/// and all other MSR bits cleared.
+///
+/// The default definition allows external and machine check exceptions. This
+/// definition can be overriden by the application.
+
+#ifndef PK_THREAD_MACHINE_CONTEXT_DEFAULT
+#define PK_THREAD_MACHINE_CONTEXT_DEFAULT \
+ (MSR_UIE | MSR_EE | MSR_ME)
+
+#endif
+
+
+#ifndef __ASSEMBLER__
+
+/// The PK kernel default panic sequence for C code is to issue a trap
+/// instruction with DBCR[TRAP] set, which causes XSR[TRAP] <- 1
+/// and causes the PPE to halt.
+///
+///
+/// The Simics environment does not model Debug events correctly. It executes
+/// the TRAP as an illegal instruction and branches to the Program Interrupt
+/// handler, destroying the contents of SRR0 and SRR1. Therefore we always
+/// insert a special Simics magic breakpoint (which is an effective NOP)
+/// before the hardware trap. The special-form magic instruction is
+/// recognized by our Simics support scripts which decode the kernel state and
+/// try to help the user interpret what happened based on the TRAP code.
+/// NOTE! SIMICS does not seem to recognize the "magic breakpoint" on PPE!
+
+
+#ifndef PK_PANIC
+
+#if SIMICS_ENVIRONMENT
+#define PK_PANIC(code) \
+ do { \
+ asm volatile ("stw %r3, __pk_panic_save_r3@sda21(0)"); \
+ asm volatile ("lwz %r3, __pk_panic_dbcr@sda21(0)"); \
+ asm volatile ("mtdbcr %r3"); \
+ asm volatile (".long %0" : : "i" (code)); \
+ } while(0)
+#else
+#define PK_PANIC(code) \
+ do { \
+ asm volatile ("tw 31, %0, %1" : : "i" (code/256) , "i" (code%256)); \
+ } while (0)
+#endif
+#endif // SIMICS_ENVIRONMENT
+
+// These variables are used by the PK_PANIC() definition above to save and
+// restore state. __pk_panic_dbcr is the value loaded into DBCR to force
+// traps to halt the PPE and freeze the timers.
+
+#if SIMICS_ENVIRONMENT
+#ifdef __PPE42_CORE_C__
+uint32_t __pk_panic_save_r3;
+uint32_t __pk_panic_dbcr = DBCR_RST_HALT;
+#define __PK_PANIC_DEFS__
+#else
+#define __PK_PANIC_DEFS__ \
+ extern uint32_t __pk_panic_save_r3; \
+ extern uint32_t __pk_panic_dbcr;
+#endif //SIMICS_ENVIRONMENT
+
+#endif // PK_PANIC
+
+/// This is the Simics 'magic breakpoint' instruction.
+///
+/// Note that this form does not include a memory barrier, as doing so might
+/// change the semantics of the program. There is an alternative form
+/// SIMICS_MAGIC_BREAKPOINT_BARRIER that does include a barrier.
+
+//#define SIMICS_MAGIC_BREAKPOINT asm volatile ("rlwimi 0,0,0,0,0")
+
+/// This is the Simics 'magic breakpoint' instruction including a memory
+/// barrier.
+///
+/// Note that the memory barrier guarantees that all variables held in
+/// registers are flushed to memory before the breakpoint, however this might
+/// change the semantics of the program. There is an alternative form of
+/// SIMICS_MAGIC_BREAKPOINT that does not include a barrier. If the idea is
+/// to use the breakpoint for tracing code execution in Simics, the barrier
+/// form may be preferred so that variable values will be visible in memory.
+
+/*#define SIMICS_MAGIC_BREAKPOINT_BARRIER \
+ asm volatile ("rlwimi 0,0,0,0,0" : : : "memory")
+*/
+
+#else // __ASSEMBLER__
+// *INDENT-OFF*
+
+/// This is the Simics 'magic breakpoint' instruction. An assembler macro
+/// form is also provided for use within macros.
+
+//#define SIMICS_MAGIC_BREAKPOINT rlwimi 0,0,0,0,0
+
+// .macro _simics_magic_breakpoint
+// rlwimi 0,0,0,0,0
+// .endm
+
+/// The PK kernel panic default panic sequence for assembler code
+///
+/// By default a kernel panic from assembler forces external debug mode then
+/// generates a \c trap instruction followed by the error code. The \a code
+/// argument must be a compile-time integer immediate. This definition can be
+/// overriden by the application.
+///
+/// See the comments for the non-ASSEMBLER version for further details. Note
+/// that the code space reserved for exception handlers is only 8
+/// instructions, so in the assembler context we don't save DBCR0 as doing so
+/// would require 10.
+
+#ifndef PK_PANIC
+
+#define PK_PANIC(code) _pk_panic code
+#if SIMICS_ENVIRONMENT
+ .macro _pk_panic, code
+ stw %r3, __pk_panic_save_r3@sda21(0)
+ lwz %r3, __pk_panic_dbcr@sda21(0)
+ mtdbcr %r3,
+ .long (\code)
+ .endm
+#else
+ .macro _pk_panic, code
+ tw 31,(\code)/256, (\code)%256
+ .endm
+#endif // SIMICS_ENVIRONMENT
+#endif // PK_PANIC
+
+// *INDENT-ON*
+#endif // __ASSEMBLER__
+
+
+// Application-overridible definitions for the PK boot loader
+
+/// In order to enable the default kernel panic (a trap) to halt the machine,
+/// the Debug Control Register 0 (DBCR0) is initialized in externel debug
+/// mode, with the Trap Debug Event enabled so that the trap will not cause a
+/// program exception, and the FT bit set so that the timers will freeze.
+/// This definition can be overridden by the application.
+///
+/// NB: It is expected that a reliable production system will redefine all of
+/// the 'panic' macros and the default DBCR0 setup.
+
+#ifndef PPE42_DBCR_INITIAL
+#define PPE42_DBCR_INITIAL DBCR_TRAP
+#endif
+
+/// This is the value of the MSR used during initialization. Once PK threads
+/// are started (with \c pk_start_threads()), all machine contexts derive
+/// from the default thread context \c
+/// PK_THREAD_MACHINE_CONTEXT_DEFAULT. This definition can be overriden by
+/// the application.
+///
+/// The default is to enable machine checks only.
+
+#ifndef PPE42_MSR_INITIAL
+#define PPE42_MSR_INITIAL MSR_ME
+#endif
+
+/// The \a argc argument passed to \c main(). This definition can be overriden
+/// by the application.
+
+#ifndef PPE42_ARGC_INITIAL
+#define PPE42_ARGC_INITIAL 0
+#endif
+
+/// The \a argv argument passed to \c main(). This definition can be overriden
+/// by the application.
+
+#ifndef PPE42_ARGV_INITIAL
+#define PPE42_ARGV_INITIAL 0
+#endif
+
+/// Optionally trap the reset for the debugger, which means that the PPE42
+/// will simply spin at the symbol \c __reset_trap after a chip reset. Set R0
+/// to a non-zero value in the debugger to continue execution. This definition
+/// can be overriden by the application.
+
+#ifndef PPE42_RESET_TRAP
+#define PPE42_RESET_TRAP 0
+#endif
+
+#ifndef __ASSEMBLER__
+
+/// The PPE42 PK machine context is simply the MSR, a 32-bit integer.
+
+typedef uint32_t PkMachineContext;
+
+/// Disable interrupts and return the current
+/// context.
+///
+/// \param context A pointer to an PkMachineContext, this is the context that
+/// existed before interrupts were disabled. Typically this
+/// context is restored at the end of a critical section.
+///
+/// Return values other then PK_OK (0) are errors; see \ref pk_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -PK_INVALID_ARGUMENT_INTERRUPT An illegal priority was specified.
+
+UNLESS__PPE42_CORE_C__(extern)
+inline int
+pk_interrupt_disable(PkMachineContext* context)
+{
+*context = mfmsr();
+
+wrteei(0);
+
+return PK_OK;
+}
+
+/// Set the machine context.
+///
+/// \param context A pointer to an PkMachineContext
+///
+/// Return values other then PK_OK (0) are errors; see \ref pk_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -PK_INVALID_ARGUMENT_CONTEXT_SET A null pointer was provided as
+/// the \a context argument or an illegal machine context was specified.
+
+UNLESS__PPE42_CORE_C__(extern)
+inline int
+pk_machine_context_set(PkMachineContext* context)
+{
+if (PK_ERROR_CHECK_API)
+{
+PK_ERROR_IF(context == 0, PK_INVALID_ARGUMENT_CONTEXT_SET);
+}
+
+mtmsr(*context);
+
+return PK_OK;
+}
+
+/// Get the machine context.
+///
+/// \param context A pointer to an PkMachineContext.
+///
+/// Return values other then PK_OK (0) are errors; see \ref pk_errors
+///
+/// \retval 0 Successful completion
+///
+/// \retval -PK_INVALID_ARGUMENT_CONTEXT_GET A null pointer was provided as
+/// the \a context argument.
+
+UNLESS__PPE42_CORE_C__(extern)
+inline int
+pk_machine_context_get(PkMachineContext* context)
+{
+if (PK_ERROR_CHECK_API)
+{
+PK_ERROR_IF(context == 0, PK_INVALID_ARGUMENT_CONTEXT_GET);
+}
+
+*context = mfmsr();
+
+return PK_OK;
+}
+
+extern void __ctx_switch();
+/// The PK context switch for the PPE kernel
+// There is no protected mode in PPE42 so just call kernel code
+#define __pk_switch() __ctx_switch()
+
+
+/// In the PowerPC EABI all initial stack frames require 8 bytes - the 4 bytes
+/// at the SP are zeroed to indicate the end of the stack, and the 4 bytes
+/// behind the SP are for the initial subroutine's LR.
+
+static inline void
+__pk_stack_create_initial_frame(PkAddress* stack, size_t* size)
+{
+*stack -= 8;
+* size -= 8;
+* ((PK_STACK_TYPE*)(*stack)) = 0;
+}
+
+/// The PK Kernel Context for PPE42
+///
+/// The PK portable kernel does not define how the kernel keeps track of
+/// whether PK is running, interrupt levels, and other debug
+/// information. Instead it defines an API that the port must provide to the
+/// portable kernel.
+///
+/// In the PPE42 port, the kernel context is maintained in SPRG0. This
+/// 32-bit value is treated as 6 distinct fields as indicated in the structure
+/// definition.
+typedef union
+{
+
+uint32_t value;
+
+struct
+{
+
+/// A flag indicating that PK is in thread mode after a call of
+/// pk_start_threads().
+unsigned thread_mode : 1;
+
+/// If this field is non-zero then PK is processing an interrupt
+/// and the \c irq field will contain the PkIrqId of the interrupt
+/// that kicked off interrupt processing.
+unsigned processing_interrupt : 1;
+
+/// The priority of the currently running thread. In an interrupt
+/// context, this is the priority of the thread that was interrupted.
+unsigned thread_priority : 6;
+
+/// This bit tracks whether the current context can be discarded or
+/// if the context must be saved. If the processor takes an interrupt
+/// and this bit is set, then the current context will be discarded.
+/// This bit is set at the end of handling an interrupt and prior
+/// to entering the wait enabled state.
+unsigned discard_ctx : 1;
+
+/// The PkIrqId of the currently running (or last run) handler. If
+/// \c processing_interrupt is set, then this is the
+/// PkIrqId of the IRQ that is currently executing.
+unsigned irq : 7;
+
+/// Each PPE application will define (or not) the interpretation of
+/// this field. Since SPRG0 is saved and restored during during thread
+/// context switches, this field can be used to record the progress of
+/// individual threads. The kernel and/or application will provide
+/// APIs or macros to read and write this field.
+unsigned app_specific : 16;
+
+} fields;
+
+} __PkKernelContext;
+
+// These APIs are provided for applications to get and set the app_specific
+// field of the kernel context which is held in sprg0.
+
+static inline uint16_t ppe42_app_ctx_get(void)
+{
+__PkKernelContext __ctx;
+__ctx.value = mfspr(SPRN_SPRG0);
+return __ctx.fields.app_specific;
+}
+
+static inline void ppe42_app_ctx_set(uint16_t app_ctx)
+{
+PkMachineContext mctx;
+__PkKernelContext __ctx;
+mctx = mfmsr();
+wrteei(0);
+__ctx.value = mfspr(SPRN_SPRG0);
+__ctx.fields.app_specific = app_ctx;
+mtspr(SPRN_SPRG0, __ctx.value);
+mtmsr(mctx);
+}
+
+// These APIs are provided to the PK portable kernel by the port.
+
+/// PK threads have been started by a call of pk_start_threads().
+
+#define __pk_kernel_mode_thread() \
+ ({ \
+ __PkKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_SPRG0); \
+ __ctx.fields.thread_mode;})
+
+
+/// PK is executing in a thread context (not an interrupt handler).
+
+#define __pk_kernel_context_thread() \
+ ({ \
+ __PkKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_SPRG0); \
+ __ctx.fields.thread_mode && !__ctx.fields.processing_interrupt;})
+
+
+/// PK is executing an interrupt handler of any priority.
+
+#define __pk_kernel_context_any_interrupt() \
+ ({ \
+ __PkKernelContext __ctx; \
+ __ctx.value = mfspr(SPRN_SPRG0); \
+ __ctx.fields.processing_interrupt;})
+
+
+// PK requires the port to define the type PkThreadQueue, which is a
+// priority queue (where 0 is the highest priority). This queue must be able
+// to handle PK_THREADS + 1 priorities (the last for the idle thread) The
+// port must also define methods for clearing, insertion, deletion and min
+// (with assumed legal priorities). The min operation returns PK_THREADS if
+// the queue is empty (or a queue could be initialized with that entry always
+// present - PK code never tries to delete the idle thread from a thread
+// queue).
+//
+// These queues are used both for the run queue and the pending queue
+// associated with every semaphore.
+//
+// On PPE42 with 32 threads (implied), this is a job for a uint32_t and
+// cntlzw().
+
+static inline void
+__pk_thread_queue_clear(volatile PkThreadQueue* queue)
+{
+*queue = 0;
+}
+
+static inline void
+__pk_thread_queue_insert(volatile PkThreadQueue* queue, PkThreadPriority priority)
+{
+*queue |= (0x80000000u >> priority);
+}
+
+static inline void
+__pk_thread_queue_delete(volatile PkThreadQueue* queue, PkThreadPriority priority)
+{
+*queue &= ~(0x80000000u >> priority);
+}
+
+static inline PkThreadPriority
+__pk_thread_queue_min(volatile PkThreadQueue* queue)
+{
+return cntlzw(*queue);
+}
+
+static inline int
+__pk_thread_queue_member(volatile PkThreadQueue* queue, PkThreadPriority priority)
+{
+return ((*queue >> (31 - priority)) & 1);
+}
+
+static inline void
+__pk_thread_queue_union(volatile PkThreadQueue* queue0,
+volatile PkThreadQueue* queue1)
+{
+*queue0 |= *queue1;
+}
+
+static inline int
+__pk_thread_queue_count(volatile PkThreadQueue* queue)
+{
+return __builtin_popcount(*queue);
+}
+
+
+/// This macro is used to call __pk_start_threads() using the kernel stack,
+/// in a critical section.
+
+#define __pk_call_pk_start_threads() \
+ do { \
+ PkMachineContext ctx; \
+ pk_critical_section_enter(&ctx); \
+ asm volatile ("mr 1, %0; mtlr %1; blrl" : : \
+ "r" (__pk_kernel_stack), \
+ "r" (__pk_start_threads)); \
+ PK_PANIC(PK_START_THREADS_RETURNED); \
+ } while (0)
+
+
+#endif /* __ASSEMBLER__ */
+
+/// The __PkKernelContext 'thread_mode' bit as a flag
+
+#define PPE42_THREAD_MODE 0x8000
+#define PPE42_PROC_IRQ 0x4000
+#define PPE42_DISCARD_CTX 0x0080
+
+#define PPE42_THREAD_MODE_BIT 0
+#define PPE42_PROC_IRQ_BIT 1
+#define PPE42_DISCARD_CTX_BIT 8
+
+#ifndef __ASSEMBLER__
+
+/// Code breakpoints for PPE42
+///
+/// This macro inserts a special PPE42-only breakpoint into the object code
+/// at the place the macro invocation appears. This facility is designed for
+/// VBU/VPO procedure debugging. This type of breakpoint may not be required
+/// on real hardware as we will then have the full power of RISCWatch, gdb,
+/// etc. Once inserted into the code, code breakpoints can be enabled or
+/// disabled by manipulating the global variable _code_breakpoint_enable,
+/// which defaults to 1.
+///
+/// The code breakpoint is implemented as a setup routine and a teardown
+/// routine, executed in an critical section. The actual break
+/// will occur at the address of the call of the teardown routine, in the
+/// context of the calling code. The setup routine saves the state of DBCR0/1
+/// and IAC4, then programs the DBCR for an external debug mode, IAC4
+/// breakpoint. The IAC4 breakpoint is set for the address of the call of the
+/// teardown routine. The teardown routine simply restores the state of the
+/// debug registers that existed before the code breakpoint.
+///
+/// Once hit, restarting from the break requires clearing IAC4 and restarting
+/// instructions:
+///
+/// \code
+///
+/// putspr pu.occ iac4 0
+/// cipinstruct pu.occ start
+///
+/// \endcode
+///
+/// The above restart processes is also encapsulated as the p8_tclEcmd
+/// procedure 'unbreakOcc'.
+///
+/// In code built for the Simics environment (i.e., with the preprocessor
+/// macro SIMICS_ENVIRONMENT=1) this macro simply expands into
+/// SIMICS_MAGIC_BREAKPOINT, and simulation can be continued from the break as
+/// normal. This Simics magic breakpoint is also under the control of
+/// _code_breakpoint_enable. In code not built with SIMICS_ENVIROMENT=1, note
+/// that the CODE_BREAKPOINT is ignored by the Simics PPE42 model as it does
+/// not model debug events.
+
+//void
+//_code_breakpoint_prologue(void);
+
+//void
+//_code_breakpoint_epilogue(void);
+
+//extern uint32_t _code_breakpoint_enable;
+
+#endif // __ASSEMBLER__
+
+
+#endif /* __PPE42_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_asm.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_asm.h
new file mode 100644
index 00000000..6f3923aa
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_asm.h
@@ -0,0 +1,634 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_asm.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_ASM_H__
+#define __PPE42_ASM_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_asm.h
+/// \brief Generic assembler macros for 32-bit PPE42
+
+// Doxygen is confused by assembler; the best I know how to make it
+// work is to put all of the documentation at the beginning like below
+// and effectively comment out the code using Doxygen cond/endcond.
+
+/// \page ppe42_asm Generic assembler macros for 32-bit PPE42
+///
+///
+/// \section _lxzi _l<w,h,b>zi - Load register and Zero from Immediate address
+///
+/// These macros encapsulate the 2-instruction sequence required to
+/// load from a 32-bit immediate address.
+///
+/// \arg \c dreg A register to receive the load data.
+/// \arg \c areg A register to hold the immediate address. This can \e
+/// not be register 0. Note that if \a areg != \a dreg
+/// then \a areg will contain the address at the end of
+/// the macro sequence.
+/// \arg \c addr A 32-bit immediate address, which may be either an
+/// absolute or relocatable expression.
+///
+/// Forms:
+///
+/// \b _lbzi \a dreg, \a areg, \a addr - Load Byte and Zero from Immediate address \n
+/// \b _lhzi \a dreg, \a areg, \a addr - Load Halfword and Zero from Immediate address \n
+/// \b _lwzi \a dreg, \a areg, \a addr - Load Word and Zero from Immediate address \n
+///
+///
+/// \section _stxi _st<w,h,b>i - STore register to Immediate address
+///
+/// These macros encapsulate the 2-instruction sequence required to
+/// store to a 32-bit immediate address.
+///
+/// \arg \c dreg The register to store.
+/// \arg \c areg A register to hold the immediate address. This can \e
+/// not be register 0, and can not be the same as \a dreg.
+/// Note that \a areg will contain the address at the end of
+/// the macro sequence.
+/// \arg \c addr A 32-bit immediate address, which may be either an
+/// absolute or relocatable expression.
+///
+/// Forms:
+///
+/// \b _stbi \a dreg, \a areg, \a addr - STore Byte to Immediate address \n
+/// \b _sthi \a dreg, \a areg, \a addr - STore Halfword to Immediate address \n
+/// \b _stwi \a dreg, \a areg, \a addr - STore Word to Immediate address \n
+///
+///
+/// \section _lstzsd _<l,st><w,h,b><z>sd - Load/STore register from/to Small Data area
+///
+/// These macros encapulate the small data area relocations for access
+/// to storage in the small data sections .sbss, .sdata, .sbss2 and
+/// .sdata2. Use of these macros implies small data area support in
+/// the compile environment (for variables shared between compiled and
+/// assembled code) and initialization code that sets up the small data
+/// area registers R13 (and optionally R2).
+///
+/// The relocations generated by this macro will work for both SVR4 ABI
+/// and EABI environments. In particular, for EABI environments
+/// the link editor will insert offsets to either R13 or R2 depending
+/// on the section of the symbol.
+///
+/// \arg \c dreg The register to load or store.
+/// \arg \c addr A 32-bit immediate address, assumed to be a
+/// relocatable address in one of the small data sections.
+///
+/// Forms:
+///
+/// \b _lbzsd \a dreg, \a addr - Load Byte and Zero from Small Data area \n
+/// \b _lhzsd \a dreg, \a addr - Load Halfword and Zero from Small Data area \n
+/// \b _lwzsd \a dreg, \a addr - Load Word and Zero from Small Data area \n
+/// \b _stbsd \a dreg, \a addr - STore Byte to Small Data area \n
+/// \b _sthsd \a dreg, \a addr - STore Halfword to Small Data area \n
+/// \b _stwsd \a dreg, \a addr - STore Word to Small Data area \n
+///
+///
+/// \section _liw _liw<a> - Load Immediate Word (Absolute)
+///
+/// These macros encapsulate the two instructions required to load a
+/// 32-bit immediate value into a register. If the immediate is an
+/// absolute expression, then the \c 'a' form may be able to optimize
+/// to a single instruction depending on whether only the high- or
+/// low-order bits of the immediate are non-zero.
+///
+/// Forms:
+///
+/// \b _liw \a rd, \a imm - Load register \a rd with the 32-bit immediate \a imm \n
+/// \b _liwa \a rd, \a imm - Load register \a rd with the 32-bit absolute immediate \a imm \n
+///
+///
+/// \section _oriwa _oriwa - OR Immediate Word Absolute
+///
+/// This macro encapsulates the logical OR of a 32-bit immediate with a
+/// register. The immediate value must be an absolute expression.
+///
+/// The PowerPC has instructions for OR-ing 16-bit immediates into the
+/// upper (\c oris) and lower (\c ori) portions of a register. This
+/// macro optimizes the generated code based on which bits (if any) of
+/// the absolte immediate are non-zero.
+///
+/// This special macro is only provided for the OR function. For other
+/// logical operations and recording forms it is necessary in general
+/// to first load the 32-bit immediate into a register (e.g., with \c
+/// _liwa) then perform the logical operation.
+///
+/// \arg \c rd The destination register; at the end will contain \c rs
+/// OR \a imm
+/// \arg \c rs The source register.
+/// \arg \c imm 32-bit absolute expression.
+///
+/// Forms:
+///
+/// \b _oriwa \a rd, \a rs, \a imm - \a rd gets \a rs OR \a imm \n
+///
+///
+/// \section _incr64_fast - 64-bit increment for fast interrupt handlers
+///
+/// This macros implements 64-bit counter update in fast interrupt handlers
+/// which are forbidden from using the carry-bit in the XER (without
+/// saving/restoring it.)
+///
+/// \arg \c rs Scratch register
+/// \arg \c ra Register containing the counter address at entry
+///
+/// \a rs and \a ra must be unique. At the end of the macro the count
+/// is updated to memory and \a ra is unmodified.
+///
+///
+/// \section _setclear_bits Set/Clear/Copy Bits from Immediate Positions
+///
+/// There are situations where it is easier/faster to clear individual bits
+/// and bit fields, set bits or copy fields, based on immediate bit numbers
+/// and locations, rather than loading masks, since setting up a mask
+/// requires 2 instruction in general, whereas these macros generate a single
+/// instruction.
+///
+/// \arg \c rd - The destination register
+/// \arg \c rs - The source register
+/// \arg \c n - An immediate size of a bit field, in the range 0 to 32
+/// \arg \c b - An immediate big-endian bit number in the range 0 to 31
+///
+/// Forms:
+///
+/// \b _clrfield \a rd, \a rs, \a n, \a b - Clear an \a n bit field from \a rs
+/// to \a rd starting from bit \a b \n
+/// \b _clrbit \a rd, \a rs, \a b - Clear bit \a b \n
+/// \b _setbit \a rd, \a rs, \a b - Set bit \a b \n
+/// \b _copyfield \a rd, \a rs, \a n, \a b - Copy an n-bit field from \a rs to
+/// \a rd starting from bit \a b \n
+///
+///
+/// \section pseudo_ops Assembler Pseudo-Ops Macros
+///
+/// Several macros define new 'pseudo-ops'.
+///
+/// \subsection cache_align .cache_align
+///
+/// The \c .cache_align pseudo-op is used to force alignment on a
+/// cache-line boundary. It requires a preprocessor symbol definition for
+/// \c LOG_CACHE_LINE_SIZE
+///
+/// Forms:
+///
+/// \b .cache_align \n
+///
+///
+/// \subsection global_function Local and Global Functions
+///
+/// The \c .function and \c .global_function pseudo-ops define function
+/// symbols in the \c .text section.
+///
+/// Forms:
+///
+/// \b .function \a symbol - Define a local function \a symbol \n
+/// \b .global_function \a symbol - Define a global function \a symbol \n
+///
+///
+/// \subsection epilogue .epilogue
+///
+/// The \c .epilogue pseudo-op adds size and type information for
+/// functions defined in assembler.
+///
+/// \arg \c symbol - Assembler epilogue for the function \a symbol.
+///
+/// Forms:
+///
+/// \b .epilogue \a symbol \n
+///
+///
+/// \cond
+
+#ifdef __ASSEMBLER__
+// *INDENT-OFF*
+
+
+### ****************************************************************************
+### _l<b,h,w>zi
+### _st<b,h,w>i
+### ****************************************************************************
+
+ .macro _lbzi dreg, areg, addr
+ lis \areg, \addr@ha
+ .ifc \areg, \dreg
+ lbz \dreg, \addr@l(\areg)
+ .else
+ lbzu \dreg, \addr@l(\areg)
+ .endif
+ .endm
+
+ .macro _lhzi dreg, areg, addr
+ lis \areg, \addr@ha
+ .ifc \areg, \dreg
+ lhz \dreg, \addr@l(\areg)
+ .else
+ lhzu \dreg, \addr@l(\areg)
+ .endif
+ .endm
+
+ .macro _lwzi dreg, areg, addr
+ lis \areg, \addr@ha
+ .ifc \areg, \dreg
+ lwz \dreg, \addr@l(\areg)
+ .else
+ lwzu \dreg, \addr@l(\areg)
+ .endif
+ .endm
+
+ .macro _stbi dreg, areg, addr
+ .ifc \areg, \dreg
+ .err
+ .endif
+ lis \areg, \addr@ha
+ stbu \dreg, \addr@l(\areg)
+ .endm
+
+ .macro _sthi dreg, areg, addr
+ .ifc \areg, \dreg
+ .err
+ .endif
+ lis \areg, \addr@ha
+ sthu \dreg, \addr@l(\areg)
+ .endm
+
+ .macro _stwi dreg, areg, addr
+ .ifc \areg, \dreg
+ .err
+ .endif
+ lis \areg, \addr@ha
+ stwu \dreg, \addr@l(\areg)
+ .endm
+
+
+### ****************************************************************************
+### _l<b,h,w>zsd
+### _st<b,h,w>sd
+### ****************************************************************************
+
+ .macro _lbzsd dreg, addr
+ lbz \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _lhzsd dreg, addr
+ lhz \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _lwzsd dreg, addr
+ lwz \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _stbsd dreg, addr
+ stb \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _sthsd dreg, addr
+ sth \dreg, \addr@sda21(0)
+ .endm
+
+ .macro _stwsd dreg, addr
+ stw \dreg, \addr@sda21(0)
+ .endm
+
+
+### ****************************************************************************
+### _liw<a>
+### _oriwa
+### ****************************************************************************
+
+ .macro _liw rd, imm
+ lis \rd, \imm@h
+ ori \rd, \rd, \imm@l
+ .endm
+
+ .macro _liwa rd, imm
+ .if (\imm & 0xffff0000)
+ lis \rd, \imm@h
+ .if (\imm & 0xffff)
+ ori \rd, \rd, \imm@l
+ .endif
+ .else
+ li \rd, \imm@l
+ .endif
+ .endm
+
+ .macro _oriwa rd, rs, imm
+ .if (\imm & 0xffff0000)
+ oris \rd, \rs, \imm@h
+ .if (\imm & 0xffff)
+ ori \rd, \rd, \imm@l
+ .endif
+ .else
+ ori \rd, \rs, \imm@l
+ .endif
+ .endm
+
+### ****************************************************************************
+### _incr64_fast
+### ****************************************************************************
+
+ .macro _incr64_fast, rs:req, ra:req
+
+ lwz \rs, 4(\ra)
+ addi \rs, \rs, 1
+ cmpwi \rs, 0
+ stw \rs, 4(\ra)
+ bne 233643278f
+
+ lwz \rs, 0(\ra)
+ addi \rs, \rs, 1
+ stw \rs, 0(\ra)
+233643278:
+
+ .endm
+
+### ****************************************************************************
+### _clrfield
+### _clrbit
+### _setbit
+### _copyfield
+### ****************************************************************************
+
+ .macro _clrfield, rd, rs, n, b
+ rlwinm \rd, \rs, 0, (\b + \n) & 0x1f, (\b - 1) & 0x1f
+ .endm
+
+ .macro _clrbit, rd, rs, b
+ _clrfield \rd, \rs, 1, \b
+ .endm
+
+ .macro _setbit, rd, rs, b
+ .ifle \b - 15
+ oris \rd, \rs, 1 << (15 - \b)
+ .else
+ ori \rd, \rs, 1 << (31 - \b)
+ .endif
+ .endm
+
+ .macro _copyfield, rd, rs, n, b
+ rlwimi \rd, \rs, 0, \b , (\b + \n - 1)
+ .endm
+
+### ****************************************************************************
+### .cache_align
+### .<global_>function
+### .epilogue
+### ****************************************************************************
+
+ .set _log_cache_line_size, LOG_CACHE_LINE_SIZE
+
+ .macro .cache_align
+ .align _log_cache_line_size
+ .endm
+
+ .macro .function symbol
+ .text
+ .align 2
+ .endm
+
+ .macro .global_function symbol
+ .text
+ .align 2
+ .global \symbol
+ .endm
+
+ .macro .epilogue symbol
+ .type \symbol, @function
+ .size \symbol, . - \symbol
+ .endm
+
+### ***************************************************************************
+### 64-bit macros
+### ***************************************************************************
+
+### ***************************************************************************
+### Using symbols for register names makes the code more readable and allows
+### us to do register arithmetic within macros.
+### ***************************************************************************
+
+.equiv r0, 0
+.equiv r1, 1
+.equiv sp, 1
+.equiv r3, 3
+.equiv r4, 4
+.equiv r5, 5
+.equiv r6, 6
+.equiv r7, 7
+.equiv r8, 8
+.equiv r9, 9
+.equiv r10, 10
+
+.equiv r28, 28
+.equiv r29, 29
+.equiv r30, 30
+.equiv r31, 31
+
+.equiv d3, 3
+.equiv d4, 4
+.equiv d5, 5
+.equiv d6, 6
+.equiv d7, 7
+.equiv d8, 8
+.equiv d9, 9
+.equiv d10, 10
+.equiv d28, 28
+.equiv d29, 29
+.equiv d30, 30
+.equiv d31, 31
+
+### ***************************************************************************
+### Load virtual doubleword generic. Load a virtual doubleword from a relocatable
+### address expression. If the optional RA is specified, the address remains in
+### RA.
+### ***************************************************************************
+.macro _lvdg DT:req addr:req RA=-1
+ .if \RA == -1
+ lis \DT, (\addr)@ha
+ lvd \DT, (\addr)@l(\DT)
+ .else
+ lis \RA, (\addr)@ha
+ lvdu \DT, (\addr)@l(\RA)
+ .endif
+.endm
+
+### ***************************************************************************
+### Load virtual doubleword from a relocatable small data area address
+### ***************************************************************************
+.macro _lvdsd DT:req addr:req
+ lvd \DT, (\addr)@sda21(0)
+.endm
+
+### ***************************************************************************
+### Store virtual doubleword generic. Store a virtual doubleword based on a
+### relocatable address expression. The address remains in RA.
+### ***************************************************************************
+.macro _stvdg DS:req addr:req RA:req
+ lis \RA, (\addr)@ha
+ stvdu \DS, (\addr)@l(\RA)
+.endm
+
+### ***************************************************************************
+### Store virtual doubleword to a relocatable small data address expression
+### ***************************************************************************
+.macro _stvdsd DS:req addr:req
+ stvd \DS, (\addr)@sda21(0)
+.endm
+
+### ***************************************************************************
+### Load virtual doubleword absolute. Set DT to an absolute 64-bit constant
+### ***************************************************************************
+.macro _lvda DT, cvalue
+ lwa (\DT + 1)%32, (\cvalue) & 0x00000000ffffffff
+ lwa \DT, (\cvalue) >> 32
+.endm
+
+### ***************************************************************************
+###
+### 64-bit arithmetic macros
+###
+### ***************************************************************************
+
+.macro check_overlap2 DA, DB
+ .if ((\DA - \DB) % 32) == 1 || ((\DA - \DB) % 32) == -1
+ .error "virtual doubleword registers must be identical or non-overlapping"
+ .endif
+.endm
+
+.macro check_overlap3 DA, DB, DC
+ check_overlap2 \DA, \DB
+ check_overlap2 \DA, \DC
+ check_overlap2 \DB, \DC
+.endm
+
+### ***************************************************************************
+### Add virtual doubleword carrying
+### ***************************************************************************
+.macro _addvdc DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ addc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ adde \DT, \DA, \DB
+.endm
+
+### ***************************************************************************
+### Add virtual doubleword to signed 16-bit immediate carrying
+### ***************************************************************************
+.macro _addvdic DT, DA, SI
+ .if \DA == 31
+ .error "d31 for addend register is not supported"
+ .endif
+ check_overlap2 \DT, \DA
+ addi (\DT+1)%32, \DA+1, SI
+ addze \DT, \DA
+.endm
+
+### ***************************************************************************
+### Add virtual doubleword to unsigned word carrying
+### ***************************************************************************
+.macro _addvdwuc DT, DA, RB
+ check_overlap2 \DT, \DA
+ addc (\DT+1)%32, (\DA+1)%32, \RB
+ addze \DT, \DA
+.endm
+
+### ***************************************************************************
+### Subtract virtual doubleword carrying
+### ***************************************************************************
+.macro _subvdc DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ subfc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ subfe \DT, \DA, \DB
+.endm
+
+### ***************************************************************************
+###
+### 64-bit logic macros
+###
+### ***************************************************************************
+
+### ***************************************************************************
+### AND virtual doubleword
+### ***************************************************************************
+.macro _andvd DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ and (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ and \DT, \DA, \DB
+.endm
+
+### ***************************************************************************
+### ANDC virtual doubleword
+### ***************************************************************************
+.macro _andcvd DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ andc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ andc \DT, \DA, \DB
+.endm
+
+### ***************************************************************************
+### EQV virtual doubleword
+### ***************************************************************************
+.macro _eqvvd DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ eqv (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ eqv \DT, \DA, \DB
+.endm
+
+### ***************************************************************************
+### OR virtual doubleword
+### ***************************************************************************
+.macro _orvd DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ or (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ or \DT, \DA, \DB
+.endm
+
+### ***************************************************************************
+### ORC virtual doubleword
+### ***************************************************************************
+.macro _orcvd DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ orc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ orc \DT, \DA, \DB
+.endm
+
+### ***************************************************************************
+### XOR virtual doubleword
+### ***************************************************************************
+.macro _xorvd DT, DA, DB
+ check_overlap3 \DT, \DA, \DB
+ xor (\DT+1)%32, (\DA+1)%32, (\DB+1)%32
+ xor \DT, \DA, \DB
+.endm
+
+// *INDENT-ON*
+#endif /* __ASSEMBLER__ */
+
+/// \endcond
+
+// Local Variables:
+// mode:asm
+// End:
+
+#endif /* __PPE42_ASM_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_boot.S b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_boot.S
new file mode 100644
index 00000000..6c3424f5
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_boot.S
@@ -0,0 +1,193 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_boot.S $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_boot.S
+/// \brief PK bootloader for PPE42
+
+ .nolist
+#include "pk.h"
+ .list
+
+### PK Bootloader for PPE42
+###
+### This is the basic restart initialization of the processor.
+### Parts of this code were derived from examples in the IBM OSopen
+### OpenBIOS for the 405GP written by James Burke.
+###
+### This code does not really do very much, just makes sure that there will
+### be a reasonable state in the machine when control is turned over to
+### the PK application. Any core setup that requires SPR access will be done
+### here. All other setup is expected to take place in system-specific
+### routines.
+###
+### From the PowerPC 405-S Embedded Core User's manual:
+###
+### "In general, the contents of SPRs are undefined after a core, chip or
+### system reset. Some SPRs retain the content they had before the reset
+### occurred."
+###
+### Registers fully reset:
+### DBCR1 - Data compares disabled
+### DCWR - Data cache write-through disabled
+### ESR - No exception syndromes
+### MSR - No exceptions/interrupts are allowed
+###
+### Registers partially reset:
+### CCR0 = 0x00700000 - Sets ICU and DCU PLB Priority
+### DBCR0 [EDM] = 0 - External debug mode disabled
+### [RST] = 0 - No reset action
+### DBSR [MRR] = x - x indicates most recent reset action
+### SGR = 0xffffffff - Storage is guarded
+### TCR [WRC] = 0 - Watchdog timer reset disabled
+### TSR [WRS] = x - x is a copy of TCR[WRC] Watchdog reset status
+### [PIS] = x - undefined
+
+ .global_function __pk_boot
+ .global __reset_trap
+
+__pk_boot:
+
+ ## Trap the reset for the debugger. Set R0 to a non-zero value in the
+ ## debugger to continue.
+
+ .if PPE42_RESET_TRAP
+ li %r0, 0
+__reset_trap:
+ cmpwi %r0, 0
+ beq __reset_trap
+ .endif
+
+ ## Set up PowerPC EABI constant registers. These registers are never
+ ## again touched by the PK kernel or the application (if they are
+ ## behaving).
+
+ _liw %r2, _SDA2_BASE_
+ _liw %r13, _SDA_BASE_
+
+ ## Clear the timer control register. This masks all timer interrupts.
+
+ li %r3, 0
+ mttcr %r3
+
+ ## The stack pointer is initialized for use by the remainder of the
+ ## initialization, including the application main(). The linker script
+ ## defines the initial stack area.
+ ##
+ ## Stacks are always 8-byte aligned. A '0' is stored at the
+ ## stack pointer to indicate the end of the stack chain. Stack frames
+ ## always consist of at least 8 bytes - the backchain pointer and the
+ ## slot above the backchain pointer for the callee's LR.
+
+ _liw %r1, _PK_INITIAL_STACK
+ _clrfield %r1, %r1, 3, 29 # 8-byte align
+ li %r3, 0
+ stwu %r3, -8(%r1)
+
+ ## SPRG0 (__PkKernelContext) is initialized to 0
+ ## indicating that the PK kernel is not in thread mode, and no
+ ## interrupts are active.
+
+ li %r3, 0
+ mtsprg0 %r3
+
+ ## Set up the initial value of Debug Control Register 0. Note that
+ ## DBCR1 is specified to be cleared at reset. VBU simulation requested
+ ## an option that this register not be modified so that they could
+ ## completely control debug behavior from reset of the PPE42.
+
+#ifndef NO_INIT_DBCR0
+ _liwa %r3, PPE42_DBCR_INITIAL
+ mtdbcr %r3
+#endif
+
+ ## The exception vector prefix is set - it must be 512 byte aligned.
+ ## NOTE: for PPE42, the IVPR is read only, but can be changed through scoms
+
+ #_liw %r3, __vectors
+ #andi. %r4, %r3, 0x01ff
+ #beq 1f
+ #_pk_panic PK_BOOT_VECTORS_NOT_ALIGNED
+#1:
+ #mtivpr %r3
+ #sync
+
+ ## The MSR to be used during the rest of intialization is
+ ## established. This MSR should NOT enable
+ ## interrupts, but could enable machine check exceptions.
+
+ _liwa %r3, PPE42_MSR_INITIAL
+ mtmsr %r3
+ sync
+
+#ifdef PK_BOOT_FROM_ROM
+
+ ## NB: I don't think the old linker scripts were necessarily the most
+ ## optimal. We need to revisit this if we actually do ROM boots in PK
+ ## Version 2. Not sure the comments are correct.
+
+ ## Data is copied from the initial ROM image to the RAM. The
+ ## address symbols are defined in the linker command file. The linker
+ ## will have zeroed this area in the ROM image.
+
+ liw %r3, __pk_ram_lma - 4 # src
+ liw %r4, __pk_ram_vma - 4 # dest
+ liw %r5, __pk_ram_size
+ liw %r6, 2
+ srw %r5, %r5, %r6 # Number of word transfers
+ mtctr %r5
+
+copy_loop:
+ lwzu %r5, 4(%r3)
+ stwu %r5, 4(%r4)
+ bdnz copy_loop
+
+#endif /* PK_BOOT_FROM_ROM */
+
+
+ ## Call the system setup code.
+
+ bl __ppe42_system_setup
+
+ ## Call the application. If for some reason we return from
+ ## the call of the application we call an alternate entry point of the
+ ## idle thread.
+ ##
+ ## An initial argc/argv can be passed into main(). argc is expected to
+ ## be a 32-bit immediate integer, and argv is expected to be a 32-bit
+ ## absolute or relocatable expression.
+
+ _liwa %r3, PPE42_ARGC_INITIAL
+ _liw %r4, PPE42_ARGV_INITIAL
+ bl __pk_main
+
+ b __pk_idle_thread_from_bootloader
+
+ .epilogue __pk_boot
+
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_cache.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_cache.h
new file mode 100644
index 00000000..cb06196d
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_cache.h
@@ -0,0 +1,126 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_cache.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_CACHE_H__
+#define __PPE42_CACHE_H__
+
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_cache.h
+/// \brief PowerPC-lite (PPE) cache management header for PK
+///
+/// The data cache flush/invalidate macros defined here create a compiler
+/// memory barrier that will cause GCC to flush/invalidate all memory data
+/// held in registers before the macro.
+
+#ifndef __ASSEMBLER__
+
+/// Determine cache-alignment of a pointer or byte-count
+#define cache_aligned(x) \
+ ((((unsigned long)(x)) & (POW2_32(LOG_CACHE_LINE_SIZE) - 1)) == 0)
+
+/// Cache-align a pointer or byte count. If the 'direction' is <= 0 then we
+/// round down, else round up.
+#define cache_align(x, direction) \
+ ({ \
+ unsigned long __x = (unsigned long)(x); \
+ unsigned long __r; \
+ if ((direction) <= 0) { \
+ __r = __x & ~(((unsigned long)CACHE_LINE_SIZE) - 1); \
+ } else { \
+ if (__x % CACHE_LINE_SIZE) { \
+ __r = __x + (CACHE_LINE_SIZE - (__x % CACHE_LINE_SIZE)); \
+ } \
+ } \
+ (void *)__r; \
+ })
+
+/// Data Cache Block Flush
+#define dcbf(p) asm volatile ("dcbf 0, %0" : : "r" (p) : "memory")
+
+/// Data Cache Block Touch
+#define dcbt(p) asm volatile ("dcbt 0, %0" : : "r" (p) : "memory")
+
+/// Data Cache Block Invalidate (Privileged)
+#define dcbi(p) asm volatile ("dcbi 0, %0" : : "r" (p) : "memory")
+
+void
+dcache_invalidate_all(void);
+
+void
+dcache_flush_all(void);
+
+void
+dcache_invalidate(void* p, size_t bytes);
+
+void
+dcache_flush(void* p, size_t bytes);
+
+/// Invalidate a line in the D-cache
+///
+/// \param p An address withing the cache line to be invalidated.
+///
+/// The dcache_invalidate_line() API is used to invalidate a single cache line
+/// containing the address \a p. Note that invalidation is a destructive
+/// operation that may cause the loss of information. It is the caller's
+/// responsibility to insure that no useful data is inadverdently invalidated.
+/// D-cache invalidation is more-or-less a no-op for data either not in the
+/// cache or marked as non-cacheable.
+///
+/// This API always issues a sync() after the invalidation.
+
+static inline void
+dcache_invalidate_line(void* p)
+{
+ dcbi(p);
+ sync();
+}
+
+/// Flush and invalidate a line from the D-cache
+///
+/// \param p An address within the cache line to be flushed.
+///
+/// The dcache_flush_line() API can be used as a shortcut to flush and
+/// invalidate a single cache line. Note that flushing is not a destructive
+/// operation in the sense that no information is lost, however the caller
+/// must make sure that the entirity of the data to be flushed is contained in
+/// the line that includes the address \a p. D-cache flush is more-or-less a
+/// no-op for data either not in the cache or marked as non-cacheable.
+///
+/// This API always issues a sync() after the flush.
+
+static inline void
+dcache_flush_line(void* p)
+{
+ dcbf(p);
+ sync();
+}
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPE42_CAHE_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_context.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_context.h
new file mode 100644
index 00000000..e54f255d
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_context.h
@@ -0,0 +1,228 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_context.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_CONTEXT_H__
+#define __PPE42_CONTEXT_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_context.h
+/// \brief PPE42 Machine and Thread context for PK
+
+/// \page ppe42_machine_context PPE42 Assembler Macros for PK Machine
+/// Context (Critical Sections)
+///
+/// \section _pk_enter_critical \b _pk_critical_section_enter/exit
+///
+/// These macro encapsulates the instruction sequences required to enter and
+/// exit critical sections, along with the machine context save for later
+/// exiting the critical section.
+///
+/// \arg \c ctxreg A register that will hold (holds) the machine context (MSR)
+/// prior to entering the critical section (to be restored) for \c
+/// _pk_critical_section_enter (\c _pk_critical_section_exit).
+///
+/// \arg \c scrreg A scratch register required for the computation of
+/// \c _pk_critical_section_enter.
+///
+/// Forms:
+///
+/// \b _pk_critical_section_enter \a priority, \a ctxreg, \a scrreg - Enter a
+/// critical section \n
+/// \b _pk_critical_section_exit \a ctxreg - Exit a critical section
+
+#ifdef __ASSEMBLER__
+// *INDENT-OFF*
+
+ .set _msr_ee_bit, MSR_EE_BIT
+
+ .macro _pk_critical_section_enter ctxreg, scrreg
+ mfmsr \ctxreg
+ wrteei 0
+ .endm
+
+ .macro _pk_critical_section_exit ctxreg
+ mtmsr \ctxreg
+ .endm
+
+// ****************************************************************************
+// PK context save/restore macros for 32-bit Embedded PowerPC
+// ****************************************************************************
+
+// All stack frames are 8-byte aligned in conformance with the EABI. PK
+// never saves or restores GPR2 or GPR13. GPR13 is constant in (E)ABI
+// applications - the base of the read-write small data area. GPR2 is
+// system-reserved in ABI applications, and is the base for read-only small data
+// in EABI applications.
+
+// USPRG0 holds the __PkKernelContext structure (defined in ppe42.h) that
+// represents the current kernel context. The layout is as follows:
+//
+// Bits Meaning
+// ==============
+// 0 The 'thread_mode' flag
+// 1 The 'processing_interrupt" flag
+// 2:7 The thread priority of the running thread
+// 8 The 'discard_ctx' flag
+// 9:15 The IRQ currently being processed
+// 16:31 The application specific data
+//
+// When PK is initialized USPRG0 is initialized to 0. When thread-mode is
+// entered (by pk_start_threads()) bit 0 is set to 1. If desired,
+// once initialized (with pk_initialize()) PK can simply
+// handle interrupts, reverting back to the non-thread-mode idle loop when
+// there's nothing to do.
+//
+
+ ## ------------------------------------------------------------
+ ## Unused registers for embedded PPE42`
+ ## ------------------------------------------------------------
+
+ ## Registers GPR2 and GPR13 are never saved or restored. In ABI and
+ ## EABI applications these registers are constant.
+
+ .set UNUSED_GPR2, 0x2 # Dedicated; EABI read-only small data area
+ .set UNUSED_GPR13, 0xd # Dedicated; (E)ABI read-write small data area
+
+ ## ------------------------------------------------------------
+ ## The PK context layout for Embedded PPE42
+ ## ------------------------------------------------------------
+
+ .set PK_CTX_GPR1, 0x00 # Dedicated; Stack pointer
+ .set PK_CTX_LINKAGE, 0x04 # Slot for handler to store LR
+ .set PK_CTX_GPR3, 0x08 # Volatile; Parameter; Return Value
+ .set PK_CTX_GPR4, 0x0c # Volatile; Parameter
+ .set PK_CTX_GPR5, 0x10 # Volatile; Parameter
+ .set PK_CTX_GPR6, 0x14 # Volatile; Parameter
+ .set PK_CTX_CR, 0x18 # Condition register
+ .set PK_CTX_LR, 0x1c # Link register
+
+ .set PK_CTX_GPR7, 0x20 # Volatile; Parameter
+ .set PK_CTX_GPR8, 0x24 # Volatile; Parameter
+ .set PK_CTX_GPR9, 0x28 # Volatile; Parameter
+ .set PK_CTX_GPR10, 0x2c # Volatile; Parameter
+ .set PK_CTX_GPR28, 0x30 # Non-volatile
+ .set PK_CTX_GPR29, 0x34 # Non-volatile
+ .set PK_CTX_GPR30, 0x38 # Non-volatile
+ .set PK_CTX_GPR31, 0x3c # Non-volatile
+
+ .set PK_CTX_XER, 0x40 # Fixed-point exception register
+ .set PK_CTX_CTR, 0x44 # Count register
+ .set PK_CTX_SRR0, 0x48 # Save/restore register 0
+ .set PK_CTX_SRR1, 0x4c # Save/restore register 1
+ .set PK_CTX_GPR0, 0x50 # Volatile; Language specific
+ .set PK_CTX_KERNEL_CTX, 0x54 # Saved __PkKernelContext for IRQ
+
+ .set PK_CTX_SIZE, 0x58 # Must be 8-byte aligned
+
+ ## ------------------------------------------------------------
+ ## Push the interrupted context if necessary
+ ##
+ ## This macro saves off some context in preparation for calling
+ ## the pk_ctx_check_discard routine. This is an attempt to use
+ ## the 32 byte cache more efficiently.
+ ##
+ ## 8 Instructions
+ ## ------------------------------------------------------------
+ ##
+
+ .macro _pk_ctx_push_as_needed branch_addr:req
+
+ stwu %r1, -PK_CTX_SIZE(%r1)
+ stvd %d3, PK_CTX_GPR3(%r1)
+ mfcr %r3
+ mflr %r4
+ stvd %d3, PK_CTX_CR(%r1)
+ _liw %r3, \branch_addr
+ b ctx_check_discard
+ .endm
+
+
+ ## ------------------------------------------------------------
+ ## update the kernel context in response to an interrupt.
+ ## ------------------------------------------------------------
+
+ ## The kernel context is updated with the currently active
+ ## IRQ in bits 9:15.
+
+ .macro _update_kernel_context irqreg, ctxreg
+ rlwimi \ctxreg, \irqreg, 16, 9, 15 //set the irq #
+ oris \ctxreg, \ctxreg, 0x4000 //set the 'processing_interrupt' flag
+ mtsprg0 \ctxreg
+
+#if PK_KERNEL_TRACE_ENABLE
+ mr %r31, \irqreg
+ srwi \ctxreg, \ctxreg, 16
+ PK_KERN_TRACE_ASM16("INTERRUPT_CONTEXT(0x%04x)", \ctxreg)
+ mr \irqreg, %r31
+#endif
+
+ .endm
+// *INDENT-ON*
+
+#else /* __ASSEMBLER__ */
+
+/// PK thread context layout as a C structure.
+///
+/// This is the structure of the stack area pointed to by
+/// thread->saved_stack_pointer when a thread is fully context-switched out.
+
+typedef struct
+{
+ uint32_t r1;
+ uint32_t linkage;
+ uint32_t r3;
+ uint32_t r4;
+ uint32_t r5;
+ uint32_t r6;
+ uint32_t cr;
+ uint32_t lr;
+
+ uint32_t r7;
+ uint32_t r8;
+ uint32_t r9;
+ uint32_t r10;
+ uint32_t r28;
+ uint32_t r29;
+ uint32_t r30;
+ uint32_t r31;
+
+ uint32_t xer;
+ uint32_t ctr;
+ uint32_t srr0;
+ uint32_t srr1;
+ uint32_t r0;
+ uint32_t sprg0;
+
+} PkThreadContext;
+
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPE42_CONTEXT_H__ */
+
+
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_core.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_core.c
new file mode 100644
index 00000000..ec8aec6d
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_core.c
@@ -0,0 +1,157 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_core.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_core.c
+/// \brief The final bits of PK runtime code required to complete the PPE42
+/// port.
+///
+/// The entry points in this file are considered 'core' routines that will
+/// always be present during runtime in any PK application.
+
+#define __PPE42_CORE_C__
+
+#include "pk.h"
+
+typedef union
+{
+ uint64_t value;
+ struct
+ {
+ uint32_t dec_start;
+ uint32_t dec_change_tag;
+ };
+} ppe42_timebase_data_t;
+
+ppe42_timebase_data_t ppe42_tb_data = {0};
+PkTimebase ppe42_64bit_timebase = 0;
+
+
+#if PK_TIMER_SUPPORT
+
+// The tickless kernel timer mechanism for PPE42
+//
+// This routine must be called from a critical section.
+//
+// Tickless timeouts are provided by programming the PIT timer based on when
+// the next timeout will occur. If the timeout is for the end of time there's
+// nothing to do - PK does not use auto-reload mode so no more PIT interrupts
+// will be arriving. Otherwise, if the timeout is longer than the 32-bit PIT
+// timer can handle, we simply schedule the timeout for 2**32 - 1 and
+// __pk_timer_handler() will keep rescheduling it until it finally occurs.
+// If the \a timeout is in the past, we schedule the PIT interrupt for 1 tick
+// in the future in accordance with the PK specification.
+
+#ifndef APPCFG_USE_EXT_TIMEBASE
+void
+__pk_schedule_hardware_timeout(PkTimebase timeout)
+{
+ PkTimebase now;
+ uint32_t new_dec;
+ uint32_t dec;
+
+ if (timeout != PK_TIMEBASE_MAX)
+ {
+
+ now = pk_timebase_get();
+
+ if (timeout <= now)
+ {
+ new_dec = 1;
+ }
+ else if ((timeout - now) > 0xffff0000)
+ {
+ new_dec = 0xffff0000;
+ }
+ else
+ {
+ new_dec = timeout - now;
+ }
+
+ //read and write the DEC back-to-back so that we lose as little time
+ //as possible
+ dec = mfspr(SPRN_DEC);
+ mtspr(SPRN_DEC, new_dec);
+
+ //update our 64bit accumulator with how much time has advanced since
+ //we last changed it.
+ ppe42_64bit_timebase += ppe42_tb_data.dec_start - dec;
+
+ //update our start time so we know how much time has advanced since
+ //this update of the accumulator
+ ppe42_tb_data.dec_start = new_dec;
+ ppe42_tb_data.dec_change_tag++;
+ }
+}
+
+#else
+
+void
+__pk_schedule_hardware_timeout(PkTimebase timeout)
+{
+ PkTimebase now;
+ PkTimebase diff;
+ uint32_t new_dec;
+
+ if (timeout != PK_TIMEBASE_MAX)
+ {
+
+ now = pk_timebase_get();
+
+ //update our 64bit accumulator with the current snapshot
+ ppe42_64bit_timebase = now;
+
+ if (timeout <= now)
+ {
+ new_dec = 1;
+ }
+ else
+ {
+ diff = (timeout - now);
+
+ if (diff > 0xfffffffful)
+ {
+ new_dec = 0xffffffff;
+ }
+ else
+ {
+ new_dec = diff;
+ }
+ }
+
+ mtspr(SPRN_DEC, new_dec);
+
+ }
+}
+
+#endif /* APPCFG_USE_EXT_TIMEBASE */
+
+#endif /* PK_TIMER_SUPPORT */
+
+#undef __PPE42_CORE_C__
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_exceptions.S b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_exceptions.S
new file mode 100644
index 00000000..9c89284c
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_exceptions.S
@@ -0,0 +1,525 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_exceptions.S $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_exceptions.S
+/// \brief PPE42 exception vector area.
+///
+/// \cond
+
+ .nolist
+#include "pk.h"
+ .list
+
+## declare and initializes global variables that hold external irq config data
+## Each PPE macro type (GPE, CME, and SBE) will have it's own implementation of this macro
+## defined in (gpe, cme, sbe)_common.h
+ .hwmacro_irq_cfg_bitmaps
+
+### ****************************************************************************
+### .vectors - This section contains all ppe42 exception vectors
+###
+### ****************************************************************************
+
+ .section .vectors, "ax", @progbits
+
+ .global __vectors
+
+__vectors:
+
+ ############################################################
+ # 0x0000 : Machine Check
+ ############################################################
+
+ ### Unmaskable interrupts (including program interrupts) are promoted
+ ### to machine check interrupts if MSR[UIE] = 0 and MSR[ME] = 1.
+ ### If the machine check was caused by a program interrupt it
+ ### will be forwarded to the program exception handler.
+__machine_check:
+
+ PPE42_MACHINE_CHECK_HANDLER
+
+ ############################################################
+ # 0x0040 : System Reset
+ ############################################################
+ .global __system_reset
+ .org __vectors + 0x0040
+__system_reset:
+ b __pk_boot
+
+ ############################################################
+ # 0x0060 : Data Storage Interrupt
+ ############################################################
+
+ .org __vectors + 0x0060
+__data_storage:
+
+ PPE42_DATA_STORAGE_HANDLER
+
+ ############################################################
+ # 0x0080 : Instruction Storage Interrupt
+ ############################################################
+
+ .org __vectors + 0x0080
+__instruction_storage:
+
+ PPE42_INSTRUCTION_STORAGE_HANDLER
+
+
+ ############################################################
+ # 0x00A0 : External Interrupt
+ ############################################################
+
+ .org __vectors + 0x00A0
+__external_interrupt_vector:
+ _pk_ctx_push_as_needed __get_ext_irq
+
+ ############################################################
+ # 0x00C0 : Alignment Exception
+ ############################################################
+
+ .org __vectors + 0x00C0
+__alignment_exception:
+
+ PPE42_ALIGNMENT_HANDLER
+
+
+ ############################################################
+ # 0x00E0 : Program Interrupt
+ ############################################################
+
+ .org __vectors + 0x00E0
+
+ ### Program exceptions are utilized for emulating the system call
+ ### instruction (0x44000002) which is used for doing context
+ ### switches between threads. They can also be used by the code
+ ### to signal an exception in an error scenario.
+__program_exception:
+ _pk_ctx_push_as_needed program_exception_handler
+
+
+ ############################################################
+ # 0x0100 : DEC Interrupts
+ ############################################################
+
+ .org __vectors + 0x0100
+__dec_interrupt:
+ _pk_ctx_push_as_needed dec_handler
+
+ ############################################################
+ # 0x0120 : FIT Interrupts
+ ############################################################
+ .org __vectors + 0x0120
+__fit_interrupt:
+
+ _pk_ctx_push_as_needed fit_handler
+
+ ############################################################
+ # 0x0140 : Watchdog Interrupts
+ ############################################################
+ .org __vectors + 0x0140
+__watchdog_interrupt:
+
+ _pk_ctx_push_as_needed watchdog_handler
+
+
+### ****************************************************************************
+### The rest of the code in this file doesn't have to be placed anywhere
+### special, so just place it in the .text section.
+### ****************************************************************************
+
+ .section .text, "ax", @progbits
+
+
+ ## The idle thread has no permanent register context. The idle thread
+ ## entry point is re-entered whenever the idle thread is scheduled.
+
+ .global __pk_idle_thread
+ .global __pk_idle_thread_from_bootloader
+
+__pk_idle_thread:
+
+ ## The idle thread 'uses' the kernel stack. Any register context
+ ## pushed here is redundant and is wiped out/ignored every time the
+ ## idle thread is re-scheduled.
+
+ ## The idle thread simply establishes a default machine context and
+ ## enters the wait-enable state. The idle thread is always entered
+ ## with interrupts disabled.
+ ##
+ ## The kernel context is initialized to indicate that the idle thread
+ ## is running - the idle thread priority is PK_THREADS, the
+ ## 'thread-mode' bit is asserted and so is the 'discard-ctx" bit.
+ ## In addition, the previous kernel context is stored in the lower
+ ## 16 bits.
+ ##
+ ## This loop can also be called from the PK bootloader if main()
+ ## returns - in which case we don't muck with the SPRG0 or the stack
+ ## pointer.
+ mfsprg0 %r3
+ srwi %r3, %r3, 16
+ oris %r3, %r3, (PK_THREADS << 8) | PPE42_THREAD_MODE | PPE42_DISCARD_CTX
+ mtsprg0 %r3
+ _lwzsd %r1, __pk_kernel_stack
+
+__pk_idle_thread_from_bootloader:
+
+ PK_KERN_TRACE_ASM16("ENTER_IDLE_STATE")
+
+ _lwzsd %r3, __pk_thread_machine_context_default
+ _oriwa %r3, %r3, MSR_WE
+ mtmsr %r3
+ b .
+
+ ## pk_halt() is implemented on the ppe42 by writing a value of 0x3 to
+ ## the RST field of the DBCR.
+ .global pk_halt
+pk_halt:
+ lis %r31, 0x3000
+ mtdbcr %r31
+ .long 0
+
+
+dec_handler:
+
+ ## The portable timer handler of PK is a full-mode handler with the prototype:
+ ## void (*pk_timer_handler)(void).
+ ##
+ ## To support the portable specification, the kernel clears the
+ ## interrupt by writing the DIS back into the TSR before calling the
+ ## handler. The timer handler does not take any arguments.
+
+ li %r4, PPE42_IRQ_DEC
+ _update_kernel_context %r4, %r3
+
+ _liwa %r3, TSR_DIS
+ mttsr %r3
+
+ bl __pk_timer_handler
+ b check_for_ext_interrupt
+
+program_exception_handler:
+ _pk_panic PPE42_ILLEGAL_INSTRUCTION
+
+ .global __pk_next_thread_resume
+__pk_next_thread_resume:
+
+ _lwzsd %r3, __pk_next_thread
+ _stwsd %r3, __pk_current_thread
+
+ ## Enter the wait enabled state if the thread pointer is null
+ bwz %r3, __pk_idle_thread
+
+ ## switch to the new thread stack
+ lwz %r1, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3)
+
+ ## load sprg0 from the stack and update the thread priority
+ ## in case it changed.
+restore_and_update_sprg0:
+ _lbzsd %r31, __pk_next_priority
+
+ PK_KERN_TRACE_ASM16("RESUME_THREAD(%d)", %r31)
+
+ lwz %r3, PK_CTX_KERNEL_CTX(%r1)
+ rlwimi %r3, %r31, 24, 2, 7
+ mtsprg0 %r3
+
+ b ctx_pop
+
+fit_handler:
+
+ ## The FIT handler is user defined. By
+ ## convention the kernel clears the interrupt by writing the FIS back
+ ## into the TSR.
+
+ li %r4, PPE42_IRQ_FIT
+
+ _update_kernel_context %r4, %r3
+
+ _lwzsd %r3, __ppe42_fit_arg
+
+ _liwa %r6, TSR_FIS
+ mttsr %r6
+
+ _lwzsd %r6, __ppe42_fit_routine
+ mtlr %r6
+ blrl
+
+ b check_for_ext_interrupt
+
+watchdog_handler:
+ ## Watchdog setup is described in the PK Specification.
+ ## The kernel clears TSR[WIS] prior to calling the handler.
+
+ li %r4, PPE42_IRQ_WATCHDOG
+
+ _update_kernel_context %r4, %r3
+
+ _liwa %r6, TSR_WIS
+ mttsr %r6
+
+ _lwzsd %r6, __ppe42_watchdog_routine
+ mtlr %r6
+ blrl
+
+ b check_for_ext_interrupt
+
+
+ ## Check if we can disard the interrupted context.
+ ## This routine expects r3, r4, lr, and cr to already be pushed.
+ ## It also expects r3 to hold the address of the function to jump
+ ## to after the interrupted context has been pushed (if necessary).
+
+ .align 5
+ctx_check_discard:
+
+ ## Prepare to jump to the branch function that was passed in
+ mtlr %r3
+
+ ## Check if the DISCARD_CTX bit is set in the kernel context
+ mfsprg0 %r3
+ bb0wi %r3, PPE42_DISCARD_CTX_BIT, ctx_continue_push
+
+ctx_discard:
+ ## DISCARD_CTX bit was set. Discard stack and branch to interrupt
+ ## handler code
+ addi %r1, %r1, PK_CTX_SIZE
+ blr
+
+ ## DISCARD_CTX bit was not set. Continue saving full context.
+ ## (r3, r4, lr, and cr have already been saved for us) and
+ ## r3 contains the interrupted kernel context
+
+ .global __ctx_switch
+__ctx_switch:
+ stwu %r1, -PK_CTX_SIZE(%r1)
+ stvd %d3, PK_CTX_GPR3(%r1)
+ mfcr %r3
+ mflr %r4
+ stvd %d3, PK_CTX_CR(%r1)
+ _liw %r3 __pk_next_thread_resume
+ mtlr %r3
+ ## emulate what interrupt would do
+ mtsrr0 %r4
+ mfmsr %r3
+ mtsrr1 %r3
+
+ ## ctx_continue_push expects r3 to be value of sprg0
+ mfsprg0 %r3
+
+ctx_continue_push:
+
+ stvd %d5, PK_CTX_GPR5(%r1)
+ stvd %d7, PK_CTX_GPR7(%r1)
+ stvd %d9, PK_CTX_GPR9(%r1)
+ stvd %d28, PK_CTX_GPR28(%r1)
+ stvd %d30, PK_CTX_GPR30(%r1)
+ mfxer %r5
+ mfctr %r6
+ stvd %d5, PK_CTX_XER(%r1)
+ mfsrr0 %r7
+ mfsrr1 %r8
+ stvd %d7, PK_CTX_SRR0(%r1)
+ stw %r0, PK_CTX_GPR0(%r1)
+ stw %r3, PK_CTX_KERNEL_CTX(%r1)
+
+ ## If the 'processing interrupt' bit is set then we were already
+ ## using the kernel stack and don't need to modify or save the current
+ ## stack pointer.
+ bb1wi %r3, PPE42_PROC_IRQ_BIT, ctx_push_completed
+
+ ## load the pointer to the current thread control block
+ _lwzsd %r4, __pk_current_thread
+
+ ## don't save the stack pointer in the thread control block
+ ## if the current thread was the idle thread (null pointer)
+ bwz %r4, switch_to_kernel_stack
+
+ ## we interrupted a bonafide thread, so save off the stack
+ ## pointer
+ stw %r1, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r4)
+
+switch_to_kernel_stack:
+ _stwsd %r1, __pk_saved_sp
+ _lwzsd %r1, __pk_kernel_stack
+
+ctx_push_completed:
+ blr
+
+__get_ext_irq:
+
+ ## Entry invariants:
+ ## 1. external interupts are disabled;
+ ## 2. previous context has ben saved off
+ ## 3. r3 contains the kernel context
+ ## 4. r1 points to the kernel stack
+
+ ## This is HW Macro specific code that is responsible for finding the
+ ## IRQ # and storing it in r4 (phantom IRQ's are assigned a value of EXTERNAL_IRQS).
+
+ hwmacro_get_ext_irq
+
+ ## An active or phantom IRQ was found.
+ ## R3 has the context of the interrupted thread or bottom half
+ ## R4 has the IRQ number.
+ ## The IRQ is converted into a pointer to an 8-byte handler
+ ## structure, and the handler is dispatched. The call is made with the
+ ## parameters:
+
+ ## R3 = private data ptr
+ ## R4 = irq
+
+call_external_irq_handler:
+
+ _update_kernel_context %r4, %r3
+ slwi %r3, %r4, 3 //multiply the irq# by 8
+ _liw %r6, __ppe42_irq_handlers
+ lwzx %r5, %r6, %r3
+ addi %r3, %r3, 4
+ lwzx %r3, %r6, %r3
+ mtlr %r5
+ blrl
+
+ ## Once the interrupt handler returns, check if any interrupts are
+ ## waiting and handle them now.
+
+check_for_ext_interrupt:
+
+ ## Set the CTX_DISCARD bit in the kernel context so that if there is
+ ## an interrupt it will not bother saving the full context.
+ mfsprg0 %r31
+ oris %r31, %r31, PPE42_DISCARD_CTX
+ mtsprg0 %r31
+
+ ###### Enable/Disable External Interrupts #####
+ wrteei 1
+ wrteei 0
+
+ ## If we made it this far, there must not be any interrupts pending.
+ ## If bottom half processing was interrupted we need to restore it
+check_interrupted_bh:
+
+ ## If the thread ID is 33 then the bottom half handler was interrupted
+ ## and needs to be restored.
+ extrwi %r4, %r31, 6, 2
+ cmpwi %r4, 33
+ beq ctx_pop_with_sprg0
+
+check_for_bh:
+ ## if the bottom half queue is pointing to itself then the queue is
+ ## empty and there are no bottom halves that need processing.
+ _lwzsd %r4, _pk_bh_queue
+ lwz %r5, 0(%r4)
+ cmplwbeq %r4, %r5, restore_interrupted_sp
+
+process_bottom_halves:
+ ## Clear the CTX_DISCARD bit so that interrupted bottom half context
+ ## will be saved in case an interrupt occurs after this point. Also
+ ## set the thread ID to 33 so that we know to restore the bottom half
+ ## context that was interrupted.
+ rlwinm %r3, %r31, 0, 9, 1 //clear thread id + discard bit
+ oris %r3, %r3, 0x2100 //set thread id to 33
+ mtsprg0 %r3 //set bottom half context
+
+ ## branch to a C function that processes bottom halves
+ wrteei 1
+ bl _pk_process_bh
+ wrteei 0
+
+ ## restore the previous kernel context (with discard bit set)
+ mtsprg0 %r31
+
+restore_interrupted_sp:
+ ## restore the interrupted thread stack pointer
+ _lwzsd %r1, __pk_saved_sp
+
+ ## If we are not in thread mode (i.e., we took an interrupt in an
+ ## interupt-only configuration of PK or after pk_initialize() but
+ ## before pk_start_threads) simply pop the context and RFI - in this
+ ## case we'll most likely be returning to main() or the non-thread-mode
+ ## idle thread.
+
+check_thread_mode:
+ bb0wi %r31, PPE42_THREAD_MODE_BIT, ctx_pop_with_sprg0
+
+ ## Check if external interrupt activated a delayed context switch. The
+ ## C-level code has taken care of the scheduling decisions - we simply
+ ## need to implement them here.
+check_for_ctx_switch:
+
+ _lwzsd %r3, __pk_delayed_switch
+ bwz %r3, check_for_idle_thread
+
+ ## Clear the delayed switch flag and go to the context switch code to
+ ## finish the switch.
+
+ li %r3, 0
+ _stwsd %r3, __pk_delayed_switch
+
+ b __pk_next_thread_resume
+
+ ## check if we should switch to the wait enabled state (idle)
+check_for_idle_thread:
+ _lwzsd %r3, __pk_current_thread
+ bwz %r3, __pk_idle_thread
+
+ctx_pop_with_sprg0:
+ ## we must ensure that interrupts are disabled while restoring context
+ ##
+ ## restore sprg0 from the saved context
+ lwz %r0, PK_CTX_KERNEL_CTX(%r1)
+ mtsprg0 %r0
+
+#if PK_KERNEL_TRACE_ENABLE
+ srwi %r0, %r0, 16
+ PK_KERN_TRACE_ASM16("RESUME_CONTEXT(0x%04x)", %r0)
+#endif
+
+ctx_pop:
+ lwz %r0, PK_CTX_GPR0(%r1)
+ lvd %d7, PK_CTX_SRR0(%r1)
+ mtsrr1 %r8
+ mtsrr0 %r7
+ lvd %d5, PK_CTX_XER(%r1)
+ mtctr %r6
+ mtxer %r5
+ lvd %d30, PK_CTX_GPR30(%r1)
+ lvd %d28, PK_CTX_GPR28(%r1)
+ lvd %d9, PK_CTX_GPR9(%r1)
+ lvd %d7, PK_CTX_GPR7(%r1)
+ lvd %d5, PK_CTX_GPR5(%r1)
+ lvd %d3, PK_CTX_CR(%r1)
+ mtlr %r4
+ mtcr0 %r3
+ lvd %d3, PK_CTX_GPR3(%r1)
+ addi %r1, %r1, PK_CTX_SIZE
+
+ rfi
+
+/// \endcond
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.c
new file mode 100644
index 00000000..9b7aa8a8
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.c
@@ -0,0 +1,369 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_gcc.h
+/// \brief 32-bit PowerPC functions expected by GCC
+///
+/// GCC expects certain built-in functions to be defined in the environment.
+/// Since PK applications are statically linked, we must define these
+/// functions ourselves to avoid a static link with the GCC libraries, which
+/// would legaly require us to distribute (at least) the binary forms of PK
+/// applications.
+///
+/// We obviously had to look at some GCC library code to understand the
+/// specifications of these routines. However, all of the code here is new -
+/// no structure definitions or lines of executable code were copied from the
+/// GCC sources.
+
+#include "pk.h"
+#include "ppe42_gcc.h"
+
+/// A 64-bit logical right shift.
+///
+/// Note that shifts with negative shift counts or shifts with shift counts
+/// longer than 63 bits are undefined.
+
+uint64_t
+__lshrdi3(uint64_t x, int i)
+{
+ Uint64 input, result;
+
+ if (i == 0)
+ {
+ return x;
+ }
+
+ input.value = x;
+
+ if (i >= 32)
+ {
+ result.word[0] = 0;
+ result.word[1] = input.word[0] >> (i - 32);
+ }
+ else
+ {
+ result.word[0] = input.word[0] >> i;
+ result.word[1] = (input.word[1] >> i) | (input.word[0] << (32 - i));
+ }
+
+ return result.value;
+}
+
+
+/// A 64 bit arithmetic left shift.
+///
+/// Note that shifts with negative shift counts or shifts with shift counts
+/// longer than 63 bits are undefined.
+
+uint64_t
+__ashldi3(uint64_t x, int i)
+{
+ Uint64 input, result;
+
+ if (i == 0)
+ {
+ return x;
+ }
+
+ input.value = x;
+
+ if (i >= 32)
+ {
+ result.word[1] = 0;
+ result.word[0] = input.word[1] << (i - 32);
+ }
+ else
+ {
+ result.word[1] = input.word[1] << i;
+ result.word[0] = (input.word[0] << i) | (input.word[1] >> (32 - i));
+ }
+
+ return result.value ;
+
+}
+
+
+/// A 64 bit arithmetic right shift.
+///
+/// Note that shifts with negative shift counts or shifts with shift counts
+/// longer than 63 bits are undefined.
+
+uint64_t
+__ashrdi3(uint64_t x, int i)
+{
+ Int64 input, result;
+
+ if (i == 0)
+ {
+ return x;
+ }
+
+ input.value = x;
+
+ if (i >= 32)
+ {
+ result.word[0] = input.word[0] >> 31;
+ result.word[1] = input.word[0] >> (i - 32);
+ }
+ else
+ {
+ result.word[0] = input.word[0] >> i;
+ result.word[1] =
+ (((uint32_t)input.word[1]) >> i) |
+ (input.word[0] << (32 - i));
+ }
+
+ return result.value ;
+
+}
+
+
+/// 32-bit Population count
+
+// This is a well-known divide-and-conquer algorithm, e.g. look on Wikipedia
+// under "Hamming Weight". The idea is to compute sums of adjacent bit
+// segments in parallel, in place.
+
+int
+__popcountsi2(uint32_t x)
+{
+ uint32_t m1 = 0x55555555;
+ uint32_t m2 = 0x33333333;
+ uint32_t m4 = 0x0f0f0f0f;
+ x -= (x >> 1) & m1; /* Sum pairs of bits */
+ x = (x & m2) + ((x >> 2) & m2);/* Sum 4-bit segments */
+ x = (x + (x >> 4)) & m4; /* Sum 8-bit segments */
+ x += x >> 8; /* Sum 16-bit segments */
+ return (x + (x >> 16)) & 0x3f; /* Final sum */
+}
+
+
+/// 64-bit Population count
+
+int
+__popcountdi2(uint64_t x)
+{
+ return __popcountsi2(x >> 32) + __popcountsi2(x & 0xffffffff);
+}
+
+
+// 64-bit divides
+//
+// For the unsigned case, note that divide by 0 returns quotient = remainder =
+// 0.
+//
+// For the signed case, in general we perform the division on the absolute
+// values and fix the signs of the quotient and remainder at the end.
+//
+// For the signed case, the convention in other libraries seems to be to
+// ignore the case of the most-negative integer. Although it seems "wrong" to
+// return the wrong answer when the right answer can be easily computed, in
+// the interest of code size we follow the convention here and ignore the most
+// negative integer.
+//
+// The assembler routine __ppe42_udiv64() assembles to ??? bytes. The full C
+// routine __ppc_sdiv64 compiles to ??? bytes with the most-negative checks,
+// but only ??? bytes as configured here.
+
+// For the signed cases, we need to handle the special case that the dividend
+// or divisor is the most negative integer.
+//
+// If the dividend is the most negative integer, then dividing this integer by
+// -1 would overflow as a positive quotient, so we set quotient and remainder
+// to 0 in this case. For divide by 1, the quotient is the most negative
+// integer. Otherwise we adjust the dividend by the absolute value of the
+// divisor, then fix up the quotient later by adding or subtracting 1.
+//
+// If the divisor is the most negative integer, then the quotient is always 0
+// unless the dividend is also the most negative integer, in which case the
+// quotient is 1 and the remainder is 0.
+//
+
+uint64_t
+__udivdi3(uint64_t u, uint64_t v)
+{
+ uint64_t quotient, remainder;
+
+ __ppe42_udiv64(u, v, &quotient, &remainder);
+ return quotient;
+}
+
+
+uint64_t
+__umoddi3(uint64_t u, uint64_t v)
+{
+ uint64_t quotient, remainder;
+
+ __ppe42_udiv64(u, v, &quotient, &remainder);
+ return remainder;
+}
+
+
+#if 0
+ #define INT64_T_MIN ((int64_t)(0x8000000000000000ull))
+#endif
+
+void
+__ppe42_sdiv64(int64_t u, int64_t v,
+ int64_t* quotient, int64_t* remainder)
+{
+ int q_negate, r_negate;
+ uint64_t uu, uv;
+#if 0
+ int fixup = 0;
+#endif
+
+ q_negate = (u < 0) ^ (v < 0);
+ r_negate = (u < 0);
+ uu = (u < 0 ? -u : u);
+ uv = (v < 0 ? -v : v);
+
+#if 0
+
+ if (u == INT64_T_MIN)
+ {
+ if (v == -1)
+ {
+ *quotient = 0;
+ *remainder = 0;
+ return;
+ }
+ else if (v == 1)
+ {
+ *quotient = INT64_T_MIN;
+ *remainder = 0;
+ return;
+ }
+ else if (v == INT64_T_MIN)
+ {
+ *quotient = 1;
+ *remainder = 0;
+ return;
+ }
+ else
+ {
+ fixup = 1;
+ u += (v < 0 ? -v : v);
+ }
+ }
+ else if (v == INT64_T_MIN)
+ {
+ *quotient = 0;
+ *remainder = u;
+ return;
+ }
+
+#endif
+
+ __ppe42_udiv64(uu, uv, (uint64_t*)quotient, (uint64_t*)remainder);
+
+#if 0
+
+ if (fixup)
+ {
+ *quotient += 1;
+ }
+
+#endif
+
+ if (q_negate)
+ {
+ *quotient = -(*quotient);
+ }
+
+ if (r_negate)
+ {
+ *remainder = -(*remainder);
+ }
+}
+
+
+int64_t
+__divdi3(int64_t u, int64_t v)
+{
+ int64_t quotient, remainder;
+
+ __ppe42_sdiv64(u, v, &quotient, &remainder);
+ return quotient;
+}
+
+
+int64_t
+__moddi3(int64_t u, int64_t v)
+{
+ int64_t quotient, remainder;
+
+ __ppe42_sdiv64(u, v, &quotient, &remainder);
+ return remainder;
+}
+
+
+/// 64-bit unsigned compare as a function, returning 0 (<), 1 (==) or 2 (>).
+
+int
+__ucmpdi2(uint64_t i_a, uint64_t i_b)
+{
+ Uint64 a, b;
+ int rv;
+
+ a.value = i_a;
+ b.value = i_b;
+
+ if (a.word[0] < b.word[0])
+ {
+ rv = 0;
+ }
+ else if (a.word[0] > b.word[0])
+ {
+ rv = 2;
+ }
+ else if (a.word[1] < b.word[1])
+ {
+ rv = 0;
+ }
+ else if (a.word[1] > b.word[1])
+ {
+ rv = 2;
+ }
+ else
+ {
+ rv = 1;
+ }
+
+ return rv;
+}
+
+
+
+
+
+
+
+
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.h
new file mode 100644
index 00000000..7b9d37e1
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.h
@@ -0,0 +1,98 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_gcc.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_GCC_H__
+#define __PPE42_GCC_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_gcc.h
+/// \brief 32-bit functions expected by GCC
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// A 64-bit unsigned integer type
+
+typedef union
+{
+ uint64_t value;
+ uint32_t word[2];
+} Uint64;
+
+/// A 64-bit signed integer type
+
+typedef union
+{
+ int64_t value;
+ int32_t word[2];
+} Int64;
+
+uint64_t
+__lshrdi3(uint64_t x, int i);
+
+uint64_t
+__ashldi3(uint64_t x, int i);
+
+uint64_t
+__ashrdi3(uint64_t x, int i);
+
+int
+__popcountsi2(uint32_t x);
+
+int
+__popcountdi2(uint64_t x);
+
+/// Unsigned 64/64 bit divide, returning quotient and remainder via pointers.
+
+void
+__ppe42_udiv64(uint64_t u, uint64_t v, uint64_t* q, uint64_t* r);
+
+/// Signed 64/64 bit divide, returning quotient and remainder via pointers.
+
+void
+__ppe42_sdiv64(int64_t u, int64_t v, int64_t* q, int64_t* r);
+
+uint64_t
+__udivdi3(uint64_t u, uint64_t v);
+
+int64_t
+__divdi3(int64_t u, int64_t v);
+
+int64_t
+__moddi3(int64_t u, int64_t v);
+
+uint64_t
+__umoddi3(uint64_t u, uint64_t v);
+
+int
+__ucmpdi2(uint64_t a, uint64_t b);
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPE42_GCC_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_init.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_init.c
new file mode 100644
index 00000000..f81b5863
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_init.c
@@ -0,0 +1,102 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_init.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_init.c
+/// \brief PPE42 initialization routines
+///
+/// The entry points in this file are routines that are typically used during
+/// initialization, and their code space could be deallocated and recovered if
+/// no longer needed by the application after initialization.
+
+#include "pk.h"
+#include "pk_trace.h"
+
+// Note that __ppe42_system_setup() is called from the PK bootloader early
+// in the initialization, at a point before the aplication has enabled
+// interrupts.
+
+// This function is expected to be defined by the macro specific code (GPE, CME, SBE)
+void __hwmacro_setup(void);
+
+
+void
+__ppe42_system_setup()
+{
+ //Only do this if the application hasn't provided a static table definition
+#ifndef STATIC_IRQ_TABLE
+ PkIrqId irq;
+
+ // Initialize the interrupt vectors.
+ for (irq = 0; irq < EXTERNAL_IRQS; irq++)
+ {
+ __ppe42_irq_handlers[irq].handler = __ppe42_default_irq_handler;
+ }
+
+ //NOTE: EXTERNAL_IRQS is the phantom interrupt assigned irq
+ __ppe42_irq_handlers[irq].handler = __ppe42_phantom_irq_handler;
+
+ // Initialize special interrupt handlers
+
+ __ppe42_fit_routine = __ppe42_default_irq_handler;
+ __ppe42_fit_arg = 0;
+
+ __ppe42_watchdog_routine = __ppe42_default_irq_handler;
+ __ppe42_watchdog_arg = 0;
+
+ /*
+ __ppe42_debug_routine = __ppe42_default_irq_handler;
+ __ppe42_debug_arg = 0;
+ */
+#endif /*STATIC_IRQ_TABLE*/
+
+ //Clear all status bits in the TSR
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+#ifdef APPCFG_USE_EXT_TIMEBASE
+ //Enable the DEC interrupt and configure it to use the external dec_timer signal
+ mtspr(SPRN_TCR, TCR_DIE | TCR_DS);
+#else
+ //Enable the DEC interrupt and configure it to use the internal clock signal
+ mtspr(SPRN_TCR, TCR_DIE);
+#endif /* APPCFG_USE_EXT_TIMEBASE */
+
+#if PK_TIMER_SUPPORT
+#if PK_TRACE_SUPPORT
+ extern PkTraceBuffer g_pk_trace_buf;
+ //set the ppe instance id
+ g_pk_trace_buf.instance_id = (uint16_t)(mfspr(SPRN_PIR) & PIR_PPE_INSTANCE_MASK);
+#endif /* PK_TRACE_SUPPORT */
+#endif /* PK_TIMER_SUPPORT */
+
+ //call macro-specific setup
+ __hwmacro_setup();
+}
+
+
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq.h
new file mode 100644
index 00000000..24f30fa1
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq.h
@@ -0,0 +1,244 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_IRQ_H__
+#define __PPE42_IRQ_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_irq.h
+/// \brief PPE42 interrupt handling for PK
+///
+/// Interrupt handling protocols and interrupt controller programming are
+/// inherently non-portable, however PK defines APIs that may be useful among
+/// different machines.
+///
+
+
+// Define pseudo-IRQ numbers for PPE42 built-in interrupts. These numbers
+// will appear in bits 16:23 of SPRG0 (__PkKernelContext) when the handlers
+// are active
+
+#define PPE42_EXC_MACHINE_CHECK 0x50
+#define PPE42_EXC_DATA_STORAGE 0x53
+#define PPE42_EXC_INSTRUCTION_STORAGE 0x54
+#define PPE42_EXC_ALIGNMENT 0x56
+#define PPE42_EXC_PROGRAM 0x57
+#define PPE42_IRQ_DEC 0x58
+#define PPE42_IRQ_FIT 0x59
+#define PPE42_IRQ_WATCHDOG 0x5A
+
+
+// Unhandled exceptions default to a kernel panic, but the application can
+// override these definition. Note that the exception area only allocates 32
+// bytes (8 instructions) to an unhandled exception, so any redefinition
+// would most likely be a branch to an application-defined handler.
+
+#ifndef PPE42_MACHINE_CHECK_HANDLER
+ #define PPE42_MACHINE_CHECK_HANDLER PK_PANIC( PPE42_MACHINE_CHECK_PANIC)
+#endif
+
+#ifndef PPE42_DATA_STORAGE_HANDLER
+ #define PPE42_DATA_STORAGE_HANDLER PK_PANIC(PPE42_DATA_STORAGE_PANIC)
+#endif
+
+#ifndef PPE42_INSTRUCTION_STORAGE_HANDLER
+#define PPE42_INSTRUCTION_STORAGE_HANDLER \
+ PK_PANIC(PPE42_INSTRUCTION_STORAGE_PANIC)
+#endif
+
+#ifndef PPE42_ALIGNMENT_HANDLER
+ #define PPE42_ALIGNMENT_HANDLER PK_PANIC(PPE42_DATA_ALIGNMENT_PANIC)
+#endif
+
+
+////////////////////////////////////////////////////////////////////////////
+// PK API
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+/// An IRQ handler takes 2 arguments:
+/// \arg \c arg - Private handler data installed by \c ssx_irq_setup() or
+/// \c ssx_irq_handler_set().
+/// \arg \c irq - The IRQ id; to enable a generic handler to manipulate
+/// its own interrupt status .
+
+typedef void (*PkIrqHandler)(void* arg, PkIrqId irq);
+
+/// Declare a subroutine as an IRQ handler
+
+#define PK_IRQ_HANDLER(f) void f(void* arg, PkIrqId irq)
+
+int pk_irq_setup(PkIrqId irq,
+ int polarity,
+ int trigger);
+
+int pk_irq_handler_set(PkIrqId irq,
+ PkIrqHandler handler,
+ void* arg);
+
+void pk_irq_enable(PkIrqId irq);
+void pk_irq_disable(PkIrqId irq);
+void pk_irq_statusclear(PkIrqId irq);
+
+PK_IRQ_HANDLER(__ppe42_default_irq_handler);
+PK_IRQ_HANDLER(__ppe42_phantom_irq_handler);
+
+
+int
+ppe42_fit_setup(int tcr_fp, PkIrqHandler handler, void* arg);
+
+
+/// The address of the optional FIT interrupt handler
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+volatile
+PkIrqHandler __ppe42_fit_routine;
+
+
+/// The private data of the optional FIT interrupt handler
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+volatile
+void* __ppe42_fit_arg;
+
+
+int
+ppe42_watchdog_setup(int tcr_wp, int tcr_wrc,
+ PkIrqHandler handler, void* arg);
+
+
+/// The address of the optional Watchdog interrupt handler
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+volatile
+PkIrqHandler __ppe42_watchdog_routine;
+
+
+/// The private data of the optional Watchdog interrupt handler
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+volatile
+void* __ppe42_watchdog_arg;
+
+
+int
+ppe42_debug_setup(PkIrqHandler handler, void* arg);
+
+
+/// The address of the optional Debug interrupt handler
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+volatile
+PkIrqHandler __ppe42_debug_routine;
+
+
+/// The private data of the optional Watchdog interrupt handler
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+volatile
+void* __ppe42_debug_arg;
+
+#endif /* __ASSEMBLER__ */
+
+// It's hard to be portable and get all of the definitions and headers in the
+// correct order. We need to bring in the system IRQ header here.
+
+#ifdef HWMACRO_GPE
+ #include "gpe_irq.h"
+#else
+ #ifdef HWMACRO_STD
+ #include "std_irq.h"
+ #endif
+#endif
+
+/// \page ppe42_irq_macros_page PPE42 PK IRQ Assembler Macros
+///
+///
+
+#ifndef __ASSEMBLER__
+
+
+/// This structure holds the interrupt handler routine addresses and private
+/// data. Assembler code assumes the given structure layout, so any changes
+/// to this structure will need to be reflected down into the interrupt
+/// dispatch assembler code.
+
+typedef struct
+{
+ PkIrqHandler handler;
+ void* arg;
+} Ppe42IrqHandler;
+
+
+#ifdef STATIC_IRQ_TABLE
+
+#define IRQ_HANDLER(func, arg) \
+ {func, arg},
+
+#define IRQ_HANDLER_DEFAULT \
+ {__ppe42_default_irq_handler, 0},
+
+#define EXTERNAL_IRQ_TABLE_END \
+ {__ppe42_phantom_irq_handler, 0}\
+ };
+
+#define EXTERNAL_IRQ_TABLE_START \
+ Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1] = \
+ {
+
+#else
+
+#define EXTERNAL_IRQ_TABLE_START
+
+#define IRQ_HANDLER(func, arg)
+
+#define IRQ_HANDLER_DEFAULT
+
+#define EXTERNAL_IRQ_TABLE_END
+
+#endif /*STATIC_IRQ_TABLE*/
+
+/// Interrupt handlers for real (implemented interrupts) plus one for the phantom interrupt handler
+extern Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1];
+
+
+/// The 'phantom interrupt' handler
+///
+/// A 'phantom' interrupt occurs when the interrupt handling code in the
+/// kernel is entered, but no interrupt is found pending in the controller.
+/// This is considered a serious bug, as it indictates a short window
+/// condition where a level-sensitive interrupt has been asserted and then
+/// quickly deasserted before it can be handled.
+
+UNLESS__PPE42_IRQ_CORE_C__(extern)
+Ppe42IrqHandler __ppe42_phantom_irq;
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPE42_IRQ_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq_core.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq_core.c
new file mode 100644
index 00000000..0021457f
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq_core.c
@@ -0,0 +1,71 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_irq_core.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_irq_core.c
+/// \brief Core IRQ routines required of any PPE42 configuration of PK
+///
+/// This file is mostly only a placeholder - where 'extern inline' API
+/// functions and 'extern' variables are realized. A couple of default
+/// handlers are also installed here. The entry points in this file are
+/// considered 'core' routines that will always be present at runtime in any
+/// PK application.
+
+#define __PPE42_IRQ_CORE_C__
+
+#include "pk.h"
+
+#ifndef STATIC_IRQ_TABLE
+ Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1];
+#endif
+
+/// This function is installed by default for interrupts not explicitly set up
+/// by the application. These interrupts should never fire.
+
+void
+__ppe42_default_irq_handler(void* arg, PkIrqId irq)
+{
+ PK_PANIC(PK_DEFAULT_IRQ_HANDLER);
+}
+
+
+/// This function is installed by default to handle the case that the
+/// interrupt dispatch code is entered in response to an external
+/// interrupt, but no interrupt is found pending in the interrupt
+/// controller. This should never happen, as it would indicate that a
+/// 'glitch' occurred on the external interrupt input
+/// to the PPE42 core.
+
+void __ppe42_phantom_irq_handler(void* arg, PkIrqId irq)
+{
+ PK_PANIC(PPE42_PHANTOM_INTERRUPT);
+}
+
+
+#undef __PPE42_IRQ_CORE_C__
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_msr.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_msr.h
new file mode 100644
index 00000000..8660f20d
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_msr.h
@@ -0,0 +1,112 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_msr.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_MSR_H__
+#define __PPE42_MSR_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_msr.h
+/// \brief Everything related to the PPE42 Machine State Register
+///
+/// All of the macros defined here that \e modify the MSR create a compiler
+/// memory barrier that will cause GCC to flush/invalidate all memory data
+/// held in registers before the macro. This is consistent with other systems,
+/// e.g., the PowerPC Linux kernel, and is the safest way to define these
+/// macros as it guarantess for example that kernel data structure updates
+/// have completed before exiting a critical section.
+
+#define MSR_SEM 0x7f000000 /* SIB Error Mask */
+#define MSR_IS0 0x00800000 /* Instance-Specific Field 0 */
+#define MSR_SIBRC 0x00700000 /* Last SIB return code */
+#define MSR_LP 0x00080000 /* Low Priority */
+#define MSR_WE 0x00040000 /* Wait State Enable */
+#define MSR_IS1 0x00020000 /* Instance-Specific Field 1 */
+#define MSR_UIE 0x00010000 /* Unmaskable Interrupt Enable */
+#define MSR_EE 0x00008000 /* External Interrupt Enable */
+#define MSR_ME 0x00001000 /* Machine Check Exception Enable */
+#define MSR_IPE 0x00000100 /* Imprecise Mode Enable */
+#define MSR_SIBRCA 0x000000ff /* SIB Return Code Accumulator */
+
+//#define MSR_CE_BIT 14
+#define MSR_EE_BIT 16
+//#define MSR_IR_BIT 26
+//#define MSR_DR_BIT 27
+
+
+#define MSR_SEM_START_BIT 1
+#define MSR_SEM_LEN 7
+#define MSR_SIBRC_START_BIT 9
+#define MSR_SIBRC_LEN 3
+
+
+#ifndef __ASSEMBLER__
+
+/// Move From MSR
+
+#define mfmsr() \
+ ({uint32_t __msr; \
+ asm volatile ("mfmsr %0" : "=r" (__msr)); \
+ __msr;})
+
+
+/// Move to MSR
+
+#define mtmsr(value) \
+ asm volatile ("mtmsr %0" : : "r" (value) : "memory")
+
+
+/// Read-Modify-Write the MSR with OR (Set MSR bits). This operation is only
+/// guaranteed atomic in a critical section.
+
+#define or_msr(x) \
+ mtmsr(mfmsr() | (x))
+
+
+/// Read-Modify-Write the MSR with AND complement (Clear MSR bits). This
+/// operation is only guaranteed atomic in a critical section.
+
+#define andc_msr(x) \
+ mtmsr(mfmsr() & ~(x))
+
+
+/// Write MSR[EE] with an immediate value (0/1)
+///
+/// Note that the immediate value \a i must be a compile-time constant.
+
+#define wrteei(i) \
+ asm volatile ("wrteei %0" : : "i" (i) : "memory")
+
+
+/// Write MSR[EE] from the EE bit of another MSR
+
+#define wrtee(other_msr) \
+ asm volatile ("wrtee %0" : : "r" (other_msr) : "memory")
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPE42_MSR_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.c
new file mode 100755
index 00000000..1dffcef4
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.c
@@ -0,0 +1,103 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2015
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_scom.c
+/// \brief Lowest level PK SCOM definitions.
+///
+/// Currently these SCOM functions are only optimized for functionality, not
+/// speed. Speed optimization will be done when we have full compiler support
+/// for the low-level stvd and lvd SCOM OPs.
+///
+/// A FAPI-lite SCOM can call these PK SCOM functions.
+///
+/// Comment:
+/// - No need to poll for SCOM completion, nor return error code of SCOM fails.
+/// A SCOM fail will cause the GPE to hang if configured to do so. But do we
+/// necessarily have to do this? Wouldn't a gentle recovery from a SCOM fail
+/// be preferred?
+
+#include "pk.h"
+#include "ppe42_scom.h"
+#include "ppe42_msr.h"
+
+
+uint32_t putscom_abs(const uint32_t i_address, uint64_t i_data)
+{
+
+ // Perform the Store Virtual Double instruction
+ PPE_STVD(i_address, i_data);
+
+ // Get the MSR[SIBRC] as the return code
+ uint32_t rc = mfmsr();
+ rc = ((rc & MSR_SIBRC) >> (32 - (MSR_SIBRC_START_BIT + MSR_SIBRC_LEN)));
+ return (rc);
+
+}
+
+uint32_t _putscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t i_data)
+{
+
+ // Perform the Store Virtual Double Index instruction
+ PPE_STVDX(i_chiplet_id, i_address, i_data);
+
+ // Get the MSR[SIBRC] as the return code
+ uint32_t rc = mfmsr();
+ rc = ((rc & MSR_SIBRC) >> (32 - (MSR_SIBRC_START_BIT + MSR_SIBRC_LEN)));
+ return (rc);
+
+}
+
+uint32_t getscom_abs( const uint32_t i_address, uint64_t* o_data)
+{
+ uint64_t temp;
+ // Perform the Load Virtual Double instruction
+ PPE_LVD(i_address, temp);
+ PPE_STVD(o_data, temp);
+
+ // Get the MSR[SIBRC] as the return code
+ uint32_t rc = mfmsr();
+ rc = ((rc & MSR_SIBRC) >> (32 - (MSR_SIBRC_START_BIT + MSR_SIBRC_LEN)));
+ return (rc);
+}
+
+
+uint32_t _getscom( const uint32_t i_chiplet_id, const uint32_t i_address, uint64_t* o_data)
+{
+ uint64_t temp;
+ // Perform the Load Virtual Double Index instruction
+ PPE_LVDX(i_chiplet_id, i_address, temp);
+ PPE_STVD(o_data, temp);
+
+ // Get the MSR[SIBRC] as the return code
+ uint32_t rc = mfmsr();
+ rc = ((rc & MSR_SIBRC) >> (32 - (MSR_SIBRC_START_BIT + MSR_SIBRC_LEN)));
+ return (rc);
+
+}
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.h
new file mode 100755
index 00000000..d3a8d2a7
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.h
@@ -0,0 +1,158 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_scom.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2015
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_scom.h
+/// \brief Include file for PK SCOMs
+///
+
+#ifndef __PK_SCOM_H__
+#define __PK_SCOM_H__
+
+/// SCOM operations return non-zero error codes that may or may not indicate
+/// an actual error, depending on which SCOM is begin accessed. This error
+/// code will appear in the MSR[SIBRC] field, bits[9:11] right after the
+/// SCOM OP returns. The error code value increases with the severity of the
+/// error.
+#define PCB_ERROR_NONE 0
+#define PCB_ERROR_RESOURCE_OCCUPIED 1
+#define PCB_ERROR_CHIPLET_OFFLINE 2
+#define PCB_ERROR_PARTIAL_GOOD 3
+#define PCB_ERROR_ADDRESS_ERROR 4
+#define PCB_ERROR_CLOCK_ERROR 5
+#define PCB_ERROR_PACKET_ERROR 6
+#define PCB_ERROR_TIMEOUT 7
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/// PPE Load Virtual Double operation
+#define PPE_LVD(_m_address, _m_data) \
+ asm volatile \
+ ( \
+ "lvd %[data], 0(%[address]) \n" \
+ : [data]"=r"(_m_data) \
+ : [address]"b"(_m_address) \
+ );
+
+
+// PPE Store Virtual Double operation
+#define PPE_STVD(_m_address, _m_data) \
+ asm volatile \
+ ( \
+ "stvd %[data], 0(%[address]) \n" \
+ : [data]"=&r"(_m_data) \
+ : "[data]"(_m_data), \
+ [address]"b"(_m_address) \
+ : "memory" \
+ );
+
+/// PPE Load Virtual Double Indexed operation
+#define PPE_LVDX(_m_base, _m_offset, _m_data) \
+ asm volatile \
+ ( \
+ "lvdx %[data], %[base], %[offset] \n" \
+ : [data]"=r"(_m_data) \
+ : [base]"b"(_m_base), \
+ [offset]"r"(_m_offset) \
+ );
+
+
+// PPE Store Virtual Double Indexed operation
+#define PPE_STVDX(_m_base, _m_offset, _m_data) \
+ asm volatile \
+ ( \
+ "stvdx %[data], %[base], %[offset] \n" \
+ : [data]"=&r"(_m_data) \
+ : "[data]"(_m_data), \
+ [base]"b"(_m_base), \
+ [offset]"r"(_m_offset) \
+ : "memory" \
+ );
+
+#define PPE_MFMSR(_m_data) \
+ asm volatile \
+ ( \
+ "mfmsr %[data] \n" \
+ : [data]"=&r"(*_m_data) \
+ : "[data]"(*_m_data) \
+ );
+
+/// @brief putscom with absolute address
+/// @param [in] i_address Fully formed SCOM address
+/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used
+/// to optimize the underlying hardware execution
+///
+/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
+uint32_t putscom_abs(const uint32_t i_address, uint64_t i_data);
+
+/// @brief getscom with absolute address
+/// @param [in] i_address Fully formed SCOM address
+/// @param [in] *o_data Pointer to uint64_t data read
+///
+/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
+
+uint32_t getscom_abs( const uint32_t i_address, uint64_t* o_data);
+
+/// @brief Implementation of PPE putscom functionality
+/// @param [in] i_chiplet Chiplet ID (@todo Should only be right justified)
+/// @param [in] i_address Base SCOM address
+/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used
+/// to optimize the underlying hardware execution
+///
+/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
+uint32_t _putscom( const uint32_t i_chiplet, const uint32_t i_address, uint64_t i_data);
+
+
+/// @brief Implementation of PPE getscom functionality
+/// @param [in] i_chiplet Chiplet ID (@todo Should only be right justified)
+/// @param [in] i_address Base SCOM address
+/// @param [in] i_data Pointer to uint64_t data read
+///
+/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
+uint32_t _getscom( uint32_t i_chiplet, uint32_t i_address, uint64_t* o_data);
+
+extern inline uint32_t putscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t i_data)
+{
+ return _putscom(i_chiplet, i_address, i_data);
+}
+
+
+extern inline uint32_t getscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t* o_data)
+{
+ return _getscom(i_chiplet, i_address, o_data);
+}
+
+#ifdef __cplusplus
+} // extern C
+#endif
+
+#endif // __PK_SCOM_H__
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_spr.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_spr.h
new file mode 100644
index 00000000..f95139bd
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_spr.h
@@ -0,0 +1,205 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_spr.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PPE42_SPR_H__
+#define __PPE42_SPR_H__
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \file ppe42_spr.h
+/// \brief Everything related to PPE42-specific SPRs
+
+/// \defgroup ppe42_sprs PPE42 SPRs
+///
+/// These are the documented SPRs of the PPE42. Most of these SPRs are
+/// available in RISCWatch and eCmd using the defined names (minus SPRN_). In
+/// some cases RISCWatch/eCMD use different names, which appear in square
+/// brackets in the brief comments for each register. RISCWatch/eCMD also
+/// allow CR, MSR and IAR (Instruction Address Register) to be accessed as
+/// SPRs.
+///
+/// @{
+
+#define SPRN_XER 0x001 /// Fixed-point exception register
+#define SPRN_LR 0x008 /// Link register
+#define SPRN_CTR 0x009 /// Count register
+#define SPRN_DEC 0x016 /// Decrementer
+#define SPRN_SRR0 0x01a /// Save/restore register 0
+#define SPRN_SRR1 0x01b /// Save/restore register 1
+#define SPRN_EDR 0x03d /// Error Data Register
+#define SPRN_ISR 0x03e /// Interrupt Status Register
+#define SPRN_IVPR 0x03f /// Interrupt Vector Prefix Register
+#define SPRN_SPRG0 0x110 /// SPR general register 0
+#define SPRN_PIR 0x11e /// Processor Identification Register
+#define SPRN_PVR 0x11f /// Processor version register
+#define SPRN_DBCR 0x134 /// Debug Control Register
+#define SPRN_DACR 0x13c /// Debug Address Compare Register
+#define SPRN_TSR 0x150 /// Timer Status Register
+#define SPRN_TCR 0x154 /// Timer Control Register
+
+/* DBCR - Debug Control Register */
+
+#define DBCR_RST_SOFT 0x10000000 /* Reset: 01=Soft Reset */
+#define DBCR_RST_HARD 0x20000000 /* Reset: 10=Hard Reset */
+#define DBCR_RST_HALT 0x30000000 /* Reset: 11=Halt */
+#define DBCR_TRAP 0x01000000 /* Trap Instruction Enable */
+#define DBCR_IACE 0x00800000 /* Instruction Address Compare Enable */
+#define DBCR_DACE_ST 0x00040000 /* Data Address Compare Enable: 01=store */
+#define DBCR_DACE_LD 0x00080000 /* Data Address Compare Enable: 10=load */
+#define DBCR_DACE_STLD 0x000C0000 /* Data Address Compare Enable: 11=both */
+
+/* TCR - Timer Control Register */
+
+#define TCR_WP_MASK 0xc0000000 /* Watchdog timer select bits */
+#define TCR_WP_0 0x00000000 /* WDT uses timer 0 */
+#define TCR_WP_1 0x40000000 /* WDT uses timer 1 */
+#define TCR_WP_2 0x80000000 /* WDT uses timer 2 */
+#define TCR_WP_3 0xc0000000 /* WDT uses timer 3 */
+#define TCR_WRC_MASK 0x30000000 /* Watchdog Reset Control mask */
+#define TCR_WRC_NONE 0x00000000 /* WDT results in no action */
+#define TCR_WRC_SOFT 0x10000000 /* WDT results in Soft reset */
+#define TCR_WRC_HARD 0x20000000 /* WDT results in Hard reset */
+#define TCR_WRC_HALT 0x30000000 /* WDT results in Halt */
+#define TCR_WIE 0x08000000 /* Watchdog Interrupt Enable */
+#define TCR_DIE 0x04000000 /* Decrementer Interrupt Enable */
+#define TCR_FP_MASK 0x03000000 /* FIT Timer Select bits*/
+#define TCR_FP_0 0x00000000 /* FIT uses timer 0 */
+#define TCR_FP_1 0x01000000 /* FIT uses timer 1 */
+#define TCR_FP_2 0x02000000 /* FIT uses timer 2 */
+#define TCR_FP_3 0x03000000 /* FIT uses timer 3 */
+#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */
+#define TCR_DS 0x00400000 /* Decrementer timer select: 0=every cycle, 1=use dec_timer input signal */
+
+#ifndef __ASSEMBLER__
+
+typedef union
+{
+ uint32_t value;
+ struct
+ {
+ unsigned int wp : 2;
+ unsigned int wrc : 2;
+ unsigned int wie : 1;
+ unsigned int die : 1;
+ unsigned int fp : 2;
+ unsigned int fie : 1;
+ unsigned int ds : 1;
+ unsigned int reserved : 22;
+ } fields;
+} Ppe42TCR;
+
+#endif /* __ASSEMBLER__ */
+
+/* TSR - Timer Status Register */
+
+#define TSR_ENW 0x80000000 /* Enable Next Watchdog */
+#define TSR_WIS 0x40000000 /* Watchdog Interrupt Status */
+#define TSR_WRS_MASK 0x30000000 /* Watchdog Reset Status */
+#define TSR_WRS_NONE 0x00000000 /* No watchdog reset has occurred */
+#define TSR_WRS_SOFT 0x10000000 /* Soft reset was forced by the watchdog */
+#define TSR_WRS_HARD 0x20000000 /* Hard reset was forced by the watchdog */
+#define TSR_WRS_HALT 0x30000000 /* Halt was forced by the watchdog */
+#define TSR_DIS 0x08000000 /* Decrementer Interrupt Status */
+#define TSR_FIS 0x04000000 /* FIT Interrupt Status */
+
+/* PIR - Processor Identification Register */
+#define PIR_PPE_TYPE_MASK 0x000000E0
+#define PIR_PPE_TYPE_GPE 0x00000020
+#define PIR_PPE_TYPE_CME 0x00000040
+#define PIR_PPE_INSTANCE_MASK 0x0000001F
+
+#ifndef __ASSEMBLER__
+
+/// Move From SPR
+///
+/// Note that \a sprn must be a compile-time constant.
+
+#define mfspr(sprn) \
+ ({uint32_t __value; \
+ asm volatile ("mfspr %0, %1" : "=r" (__value) : "i" (sprn)); \
+ __value;})
+
+
+/// Move to SPR
+///
+/// Note that \a sprn must be a compile-time constant.
+
+#define mtspr(sprn, value) \
+ ({uint32_t __value = (value); \
+ asm volatile ("mtspr %0, %1" : : "i" (sprn), "r" (__value)); \
+ })
+
+
+/// Read-Modify-Write an SPR with OR (Set SPR bits)
+///
+/// Note that \a sprn must be a compile-time constant. This operation is only
+/// guaranteed atomic in a critical section.
+
+#define or_spr(sprn, x) \
+ mtspr(sprn, mfspr(sprn) | (x))
+
+
+/// Read-Modify-Write an SPR with AND complement (Clear SPR bits)
+///
+/// Note that \a sprn must be a compile-time constant. This operation is only
+/// guaranteed atomic in a critical section.
+
+#define andc_spr(sprn, x) \
+ mtspr(sprn, mfspr(sprn) & ~(x))
+
+#endif /* __ASSEMBLER__ */
+
+#ifdef __ASSEMBLER__
+// *INDENT-OFF*
+
+ /// \cond
+
+ // Use this macro to define new mt<spr> and mf<spr> instructions that
+ // may not exist in the assembler.
+
+ .macro _sprinstrs, name, num
+ .macro mt\name, reg
+ mtspr \num, \reg
+ .endm
+ .macro mf\name, reg
+ mfspr \reg, \num
+ .endm
+ .endm
+
+ _sprinstrs dbcr, SPRN_DBCR
+ _sprinstrs tcr, SPRN_TCR
+ _sprinstrs tsr, SPRN_TSR
+ _sprinstrs sprg0, SPRN_SPRG0
+ _sprinstrs ivpr, SPRN_IVPR
+ _sprinstrs dec, SPRN_DEC
+
+ /// \endcond
+
+// *INDENT-ON*
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PPE42_SPR_H__ */
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.c b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.c
new file mode 100644
index 00000000..4f0e954c
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.c
@@ -0,0 +1,351 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.c $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+// Note: this code does not compile under the ppc2ppe backend.
+// It emits illegal ppe42 asm instructions.
+// __PPE42__ is set by the ppe42 compiler
+#ifdef __PPE42__
+
+#include <ppe42_string.h>
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+void* memset(void* vdest, int ch, size_t len)
+{
+ uint32_t addr = (uint32_t)vdest;
+
+ while(len && (addr & 0x7)) // not 8 byte aligned
+ {
+ uint8_t* p = (uint8_t*)addr;
+ *p = ch;
+ ++addr;
+ --len;
+ }
+
+ if(len >= sizeof(uint64_t))
+ {
+ uint64_t lch = ch & 0xff;
+ lch |= lch << 8;
+ lch |= lch << 16;
+ lch |= lch << 32;
+
+ while(len >= sizeof(uint64_t))
+ {
+ uint64_t* p = (uint64_t*)addr;
+ *p = lch;
+ len -= sizeof(uint64_t);
+ addr += sizeof(uint64_t);
+ }
+ }
+
+ while(len)
+ {
+ uint8_t* p = (uint8_t*)addr;
+ *p = ch;
+ ++addr;
+ --len;
+ }
+
+ return vdest;
+}
+
+
+void* memcpy(void* vdest, const void* vsrc, size_t len)
+{
+
+ // Loop, copying 4 bytes
+ long* ldest = (long*)vdest;
+ const long* lsrc = (const long*)vsrc;
+
+ while (len >= sizeof(long))
+ {
+ *ldest++ = *lsrc++;
+ len -= sizeof(long);
+ }
+
+ // Loop, copying 1 byte
+ char* cdest = (char*)ldest;
+ const char* csrc = (const char*)lsrc;
+ size_t i = 0;
+
+ for (; i < len; ++i)
+ {
+ cdest[i] = csrc[i];
+ }
+
+ return vdest;
+}
+
+void* memmove(void* vdest, const void* vsrc, size_t len)
+{
+ // Copy first-to-last
+ if (vdest <= vsrc)
+ {
+ return memcpy(vdest, vsrc, len);
+ }
+
+ // Copy last-to-first (TO_DO: optimize)
+ char* dest = (char*)(vdest);
+ const char* src = (const char*)(vsrc);
+ size_t i = len;
+
+ for (; i > 0;)
+ {
+ --i;
+ dest[i] = src[i];
+ }
+
+ return vdest;
+}
+
+int memcmp(const void* p1, const void* p2, size_t len)
+{
+ const char* c1 = (const char*)(p1);
+ const char* c2 = (const char*)(p2);
+
+ size_t i = 0;
+
+ for (; i < len; ++i)
+ {
+ long n = (long)(c1[i]) - (long)(c2[i]);
+
+ if (n != 0)
+ {
+ return n;
+ }
+ }
+
+ return 0;
+}
+
+void* memmem(const void* haystack, size_t haystacklen,
+ const void* needle, size_t needlelen)
+{
+ const void* result = NULL;
+
+ if (haystacklen >= needlelen)
+ {
+ const char* c_haystack = (const char*)(haystack);
+ const char* c_needle = (const char*)(needle);
+ bool match = false;
+
+ size_t i = 0;
+
+ for (; i <= (haystacklen - needlelen); i++)
+ {
+ match = true;
+
+ size_t j = 0;
+
+ for (; j < needlelen; j++)
+ {
+ if (*(c_haystack + i + j) != *(c_needle + j))
+ {
+ match = false;
+ break;
+ }
+ }
+
+ if (match)
+ {
+ result = (c_haystack + i);
+ break;
+ }
+ }
+ }
+
+ return (void*)(result);
+}
+
+
+char* strcpy(char* d, const char* s)
+{
+ char* d1 = d;
+
+ do
+ {
+ *d1 = *s;
+
+ if (*s == '\0')
+ {
+ return d;
+ }
+
+ d1++;
+ s++;
+ }
+ while(1);
+}
+
+char* strncpy(char* d, const char* s, size_t l)
+{
+ char* d1 = d;
+ size_t len = 0;
+
+ do
+ {
+ if (len++ >= l)
+ {
+ break;
+ }
+
+ *d1 = *s;
+
+ if (*s == '\0')
+ {
+ break;
+ }
+
+ d1++;
+ s++;
+ }
+ while(1);
+
+ // pad the remainder
+ while( len < l )
+ {
+ d1[len++] = '\0';
+ }
+
+ return d;
+}
+
+int strcmp(const char* a, const char* b)
+{
+ while((*a != '\0') && (*b != '\0'))
+ {
+ if (*a == *b)
+ {
+ a++;
+ b++;
+ }
+ else
+ {
+ return (*a > *b) ? 1 : -1;
+ }
+ }
+
+ if (*a == *b)
+ {
+ return 0;
+ }
+
+ if (*a == '\0')
+ {
+ return -1;
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+size_t strlen(const char* a)
+{
+ size_t length = 0;
+
+ while(*a++)
+ {
+ length++;
+ }
+
+ return length;
+}
+
+size_t strnlen(const char* s, size_t n)
+{
+ size_t length = 0;
+
+ while((length < n) && (*s++))
+ {
+ length++;
+ }
+
+ return length;
+}
+
+char* strcat(char* d, const char* s)
+{
+ char* _d = d;
+
+ while(*_d)
+ {
+ _d++;
+ }
+
+ while(*s)
+ {
+ *_d = *s;
+ _d++;
+ s++;
+ }
+
+ *_d = '\0';
+
+ return d;
+}
+
+char* strncat(char* d, const char* s, size_t n)
+{
+ char* _d = d;
+
+ while(*_d)
+ {
+ _d++;
+ }
+
+ while((*s) && (0 != n))
+ {
+ *_d = *s;
+ _d++;
+ s++;
+ n--;
+ }
+
+ *_d = '\0';
+
+ return d;
+}
+
+
+char* strchr(const char* s, int c)
+{
+ while((*s != '\0') && (*s != c))
+ {
+ s++;
+ }
+
+ if (*s == c)
+ {
+ return (char*)s;
+ }
+
+ return NULL;
+}
+#ifdef __cplusplus
+};
+#endif
+#endif
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.h
new file mode 100644
index 00000000..dfa79c26
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.h
@@ -0,0 +1,73 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_string.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __STRING_H
+#define __STRING_H
+
+#include <stdint.h>
+typedef uint32_t size_t;
+
+#ifndef NULL
+ #ifdef __cplusplus
+ #define NULL 0
+ #else
+ #define NULL ((void*)0)
+ #endif
+#endif
+
+#ifndef __cplusplus
+ typedef int bool;
+ #define false 0
+ #define true 1
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+void* memset(void* s, int c, size_t n) __attribute__ ((weak));
+// void bzero(void *vdest, size_t len); USE memset
+void* memcpy(void* dest, const void* src, size_t num) __attribute__ ((weak));
+void* memmove(void* vdest, const void* vsrc, size_t len) __attribute__ ((weak));
+int memcmp(const void* p1, const void* p2, size_t len) __attribute__((weak, pure));
+void* memmem(const void* haystack, size_t haystacklen,
+ const void* needle, size_t needlelen) __attribute__((weak, pure));
+
+char* strcpy(char* d, const char* s) __attribute__ ((weak));
+char* strncpy(char* d, const char* s, size_t l) __attribute__ ((weak));
+int strcmp(const char* s1, const char* s2) __attribute__((weak, pure));
+size_t strlen(const char* s1) __attribute__((weak, pure));
+size_t strnlen(const char* s1, size_t n) __attribute__((weak, pure));
+
+char* strcat(char* d, const char* s) __attribute__ ((weak));
+char* strncat(char* d, const char* s, size_t n) __attribute__ ((weak));
+
+char* strchr(const char* s, int c) __attribute__((weak, pure));
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_thread_init.S b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_thread_init.S
new file mode 100644
index 00000000..1bed7882
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_thread_init.S
@@ -0,0 +1,134 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_thread_init.S $
+#
+# OpenPOWER sbe Project
+#
+# Contributors Listed Below - COPYRIGHT 2015,2016
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+/// \file ppe42_thread_init.S
+/// \brief PPE42-specific thread initialization
+///
+/// The entry points in this file are routines that are typically used during
+/// initialization, and their code space could be deallocated and recovered if
+/// no longer needed by the application after initialization.
+
+ .nolist
+#include "pk.h"
+ .list
+
+/// \fn void __pk_thread_context_initialize(PkThread *thread, PkThreadRoutine thread_routine, void *private)
+/// \brief Create the initial thread context on the stack
+///
+/// The non-reserved GPRs are prepatterned with 0x0000\<rn\>\<rn\> where \<rn\> is
+/// the register number (as decimal). The initial context is set up with the
+/// thread running in the default machine context, and when the thread is
+/// switched in it will begin executing at the entry point of the thread
+/// routine with the \c private parameter in R3. The LR is initialized such
+/// that when the thread returns, it will return to the entry point of \c
+/// pk_complete().
+#ifdef DOXYGEN_ONLY
+void
+__pk_thread_context_initialize(PkThread *thread,
+ PkThreadRoutine thread_routine,
+ void *private);
+#endif
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \cond
+
+ .global_function __pk_thread_context_initialize
+
+__pk_thread_context_initialize:
+
+ ## R3 = thread (param)
+ ## R4 = thread_routine (param)
+ ## R5 = private (param)
+ ## R6 = thread stack pointer (computed)
+ ## R7 = scratch
+
+ .macro _gpr_init, prefix, reg, val
+ li %r7, \val
+ stw %r7, \prefix\reg(%r6)
+ .endm
+
+ ## Initialize volatile context on the thread stack. The CR is cleared,
+ ## the LR = pk_complete(), R3 has the private parameter.
+
+ lwz %r6, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3)
+
+ stwu %r6, -PK_CTX_SIZE(%r6)
+
+ li %r7, 0
+ stw %r7, PK_CTX_CR(%r6)
+
+ _liw %r7, pk_complete
+ stw %r7, PK_CTX_LR(%r6)
+
+ stw %r5, PK_CTX_GPR3(%r6)
+
+ _gpr_init PK_CTX_GPR, 4, 0x0404
+ _gpr_init PK_CTX_GPR, 5, 0x0505
+ _gpr_init PK_CTX_GPR, 6, 0x0606
+
+ ## XER and CTR are clear, SRR0 = thread_routine, SRR1 = default machine
+ ## context.
+
+ li %r7, 0
+ stw %r7, PK_CTX_XER(%r6)
+ stw %r7, PK_CTX_CTR(%r6)
+
+ stw %r4, PK_CTX_SRR0(%r6)
+
+ _lwzsd %r7, __pk_thread_machine_context_default
+ stw %r7, PK_CTX_SRR1(%r6)
+
+ _gpr_init PK_CTX_GPR, 0, 0x0000
+ _gpr_init PK_CTX_GPR, 7, 0x0707
+ _gpr_init PK_CTX_GPR, 8, 0x0808
+ _gpr_init PK_CTX_GPR, 9, 0x0909
+ _gpr_init PK_CTX_GPR, 10, 0x1010
+
+ ## Initialize the non-volatile context on the thread stack.
+
+ _gpr_init PK_CTX_GPR, 28, 0x2828
+ _gpr_init PK_CTX_GPR, 29, 0x2929
+ _gpr_init PK_CTX_GPR, 30, 0x3030
+ _gpr_init PK_CTX_GPR, 31, 0x3131
+
+ ## Initialize the kernel context on the thread stack.
+ ## Note: Thread priority is set later each time the thread is
+ ## resumed.
+
+ lis %r7, PPE42_THREAD_MODE
+ stw %r7, PK_CTX_KERNEL_CTX(%r6)
+
+ ## Initialization is done - the stack pointer is stored back in the
+ ## thread.
+
+ stw %r6, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3)
+ blr
+
+ .epilogue __pk_thread_context_initialize
+
+/// \endcond
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_timebase.S b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_timebase.S
new file mode 100644
index 00000000..cc40bce4
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42_timebase.S
@@ -0,0 +1,140 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42_timebase.S $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/// \file ppe42_timebase.S
+/// \brief PPE42-specific 64 bit timebase emulation
+///
+ .nolist
+#include "pk.h"
+ .list
+
+/// \fn PkTimebase pk_timebase_get(void)
+/// \brief Returns a 64 bit timebase
+///
+#ifdef DOXYGEN_ONLY
+PkTimebase
+pk_timebase_get(void);
+#endif
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2014
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+/// \cond
+ .global ppe42_64bit_timebase
+ .global ppe42_tb_data
+ .global_function pk_timebase_get
+
+#ifndef APPCFG_USE_EXT_TIMEBASE
+
+ /// Note that it is ok to use this function in a fast interrupt
+ /// context
+ .align 5
+ .global_function pk_timebase32_get
+pk_timebase32_get:
+
+ //load the decrementer start time and change tag
+ lvd %r4, ppe42_tb_data@sda21(0)
+
+ //load the lower 32 bits of the 64bit timebase accumulator
+ lwz %r3, ppe42_64bit_timebase+4@sda21(0)
+
+ //load the current decrementer value
+ mfdec %r0
+
+ //load the change tag again (should already be in the cache)
+ lwz %r6, ppe42_tb_data+4@sda21(0)
+
+ //loop until the change tag is the same (typically should be same)
+ cmplwbne %r5, %r6, pk_timebase32_get
+
+ //calculate how much time has passed since the decrementer was started and store in r6
+ subf %r5, %r0, %r4
+
+ //add the 32bit difference to our 32bit timebase accumulator
+ add %r3, %r5, %r3
+
+ blr
+
+
+/// Use the DEC for our timebase until we have a real timebase register (uses
+/// 9 instructions).
+/// Note: It is not ok to use this function in a fast interrupt context due to
+/// its use of r7
+ .align 5
+pk_timebase_get:
+
+ //load the decrementer start time and change tag
+ lvd %r5, ppe42_tb_data@sda21(0)
+
+ //load 64bit timebase accumulator
+ lvd %r3, ppe42_64bit_timebase@sda21(0)
+
+
+ //load the current decrementer value
+ mfdec %r0
+
+ //load the change tag again (should already be in the cache)
+ lwz %r7, ppe42_tb_data+4@sda21(0)
+
+ //loop until the change tag is the same
+ cmplwbne %r6, %r7, pk_timebase_get
+
+ //calculate how much time has passed since the decrementer was started and store in r6
+ subf %r6, %r0, %r5
+
+ //add the 32bit difference to the 64bit timebase accumulator
+ addc %r4, %r6, %r4
+ addze %r3, %r3
+
+ blr
+
+//enable this once we have a local timebase register in the model
+#else
+
+// use the local timebase register to keep more accurate time with just 6 instructions
+// in the common case and 7 otherwise.
+ .align 5
+pk_timebase_get:
+
+ //load the 64bit timebase accumulator
+ lvd r3, ppe42_64bit_timebase@sda21(0)
+
+ //read the local timebase register (2 instructions)
+ _pk_timebase32_get r5, r5
+
+ //increment the upper 32 bits if the lower 32 bits have flipped
+ cmplwbge r5, r4, update_lower_32
+
+ //increment the upper 32 bits
+ addi r3, r3, 1
+
+update_lower_32:
+ //replace the lower 32bits with what we read from the local timebase register
+ mr r4, r5
+
+ blr
+#endif /* APPCFG_USE_EXT_TIMEBASE */
+/// \endcond
diff --git a/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42math.h b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42math.h
new file mode 100644
index 00000000..e4f98cdd
--- /dev/null
+++ b/src/import/chips/p9/procedures/ppe/pk/ppe42/ppe42math.h
@@ -0,0 +1,84 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: import/chips/p9/procedures/ppe/pk/ppe42/ppe42math.h $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2016 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef _MATH_H
+#define _MATH_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+// These names are emitted by the ppe42 compiler.
+// Implement the ones that will be used.
+
+// 64 bit unsigned divide. Implement if needed
+// unsigned long long __udivdi3(unsigned long long a, unsigned long long b);
+
+/** 32 bit unsigned divide
+ * @param[in] Dividend
+ * @param[in] Divisor
+ * @return quotient
+ */
+unsigned long __udivsi3(unsigned long a, unsigned long b);
+
+/** 32 bit signed divide
+ * @param[in] Dividend
+ * @param[in] Divisor
+ * @return quotient
+ */
+int __divsi3(int _a, int _b);
+
+/** 32 bit unsigned modulus
+ * @param[in] Dividend
+ * @param[in] Divisor
+ * @return modulus
+ */
+unsigned long __umodsi3(unsigned long a, unsigned long b);
+
+/** 32 bit unsigned multiply
+ * @param[in] multiplier
+ * @param[in] multiplier
+ * @return product
+ */
+unsigned long __umulsi3(unsigned long _a, unsigned long _b);
+
+/** 32 bit signed multiply
+ * @param[in] multiplier
+ * @param[in] multiplier
+ * @return product
+ */
+unsigned int __mulsi3(unsigned int _a, unsigned int _b);
+
+/** 64 bit signed multiply
+ * @param[in] multiplier
+ * @param[in] multiplier
+ * @return product
+ */
+unsigned long long __muldi3(unsigned long long _a, unsigned long long _b);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
OpenPOWER on IntegriCloud