summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wenning <wenning@us.ibm.com>2012-05-29 12:02:40 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-06-11 11:45:48 -0500
commit882332b0941f2913111c033c4f90bd6e4ae05da0 (patch)
tree5c85e1bd8590e26de21c946bb918c0ec18f2be4f
parent43705c216502430ed9beb464a991c8e63a60bedb (diff)
downloadtalos-hostboot-882332b0941f2913111c033c4f90bd6e4ae05da0.tar.gz
talos-hostboot-882332b0941f2913111c033c4f90bd6e4ae05da0.zip
proc_slw_build HWP support
Change-Id: Ib704518ebe1b32a125f93be468f05d0d4c1572bb Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1125 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--src/include/stdint.h63
-rw-r--r--src/include/usr/vmmconst.h6
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C21
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/makefile17
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/fapi_sbe_common.H70
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h261
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C718
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api.h283
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h127
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_custom.h142
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.c118
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.h72
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H168
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.C600
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.H271
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pgas.h1044
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_bitmanip.H526
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline.h814
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline_assembler.c1487
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C419
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H52
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml108
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c2008
-rw-r--r--src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h1679
-rw-r--r--src/usr/hwpf/makefile10
25 files changed, 11034 insertions, 50 deletions
diff --git a/src/include/stdint.h b/src/include/stdint.h
index e545e0f29..d794b7867 100644
--- a/src/include/stdint.h
+++ b/src/include/stdint.h
@@ -1,48 +1,53 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/include/stdint.h $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2010 - 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/include/stdint.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2010-2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
#ifndef __STDINT_H
#define __STDINT_H
#include <stddef.h>
-typedef signed char int8_t;
-typedef short int int16_t;
-typedef int int32_t;
-typedef long int int64_t;
+typedef signed char int8_t;
+typedef short int int16_t;
+typedef int int32_t;
+typedef long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long int uint64_t;
-typedef uint64_t size_t;
-typedef int64_t ssize_t;
+typedef uint64_t size_t;
+typedef int64_t ssize_t;
-typedef ssize_t ptrdiff_t;
+typedef ssize_t ptrdiff_t;
#define UINT8_MAX (255U)
#define UINT16_MAX (65535U)
#define UINT32_MAX (4294967295U)
#define UINT64_MAX (18446744073709551615U)
+// add (u)intptr_t support
+typedef long int intptr_t;
+typedef unsigned long int uintptr_t;
+
#endif
diff --git a/src/include/usr/vmmconst.h b/src/include/usr/vmmconst.h
index 516a45137..a43a70a7a 100644
--- a/src/include/usr/vmmconst.h
+++ b/src/include/usr/vmmconst.h
@@ -5,7 +5,7 @@
*
* IBM CONFIDENTIAL
*
- * COPYRIGHT International Business Machines Corp. 2011 - 2012
+ * COPYRIGHT International Business Machines Corp. 2011-2012
*
* p1
*
@@ -83,7 +83,9 @@ enum BlockPriority
#define SLBE_b 12
/** Hardwired pointer to output PORE image, temporary location */
-#define OUTPUT_PORE_IMAGE 0x780000
+/** MAX image size is 512 K */
+#define OUTPUT_PORE_IMG_ADDR 0x780000
+#define MAX_OUTPUT_PORE_IMG_SIZE 512*1024
/**
diff --git a/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C b/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C
index fa39e9b26..e2ad1fec6 100644
--- a/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C
+++ b/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C
@@ -58,7 +58,7 @@
#include "build_winkle_images.H"
// Uncomment these files as they become available:
-// #include "host_build_winkle/host_build_winkle.H"
+#include "proc_slw_build/proc_slw_build.H"
// #include "proc_set_pore_bar/proc_set_pore_bar.H"
namespace BUILD_WINKLE_IMAGES
@@ -77,7 +77,7 @@ using namespace DeviceFW;
*
*/
void * const g_pOutputPoreImg
- = reinterpret_cast<void * const >(OUTPUT_PORE_IMAGE);
+ = reinterpret_cast<void * const >(OUTPUT_PORE_IMG_ADDR);
/**
* @brief Load PORE image and return a pointer to it, or NULL
@@ -164,7 +164,7 @@ void call_host_build_winkle( void *io_pArgs )
const char *l_pPoreImage = NULL;
size_t l_poreSize = 0;
void *l_pImageOut = NULL;
- uint32_t l_sizeImageOut = 0;
+ uint32_t l_sizeImageOut = MAX_OUTPUT_PORE_IMG_SIZE;
TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace,
@@ -213,23 +213,22 @@ void call_host_build_winkle( void *io_pArgs )
(const_cast<TARGETING::Target*>(l_cpu_target)) );
//
- // stub - get address of output buffer for PORE image
+ // stub - get address of output buffer for PORE image for this CPU,
+ // and load it there
//
- l_pImageOut = g_pOutputPoreImg;
+ l_pImageOut = g_pOutputPoreImg;
+ l_sizeImageOut = MAX_OUTPUT_PORE_IMG_SIZE;
+
-#if 0
- // $$$$$ comment out for now $$$$$
// call the HWP with each fapi::Target
FAPI_INVOKE_HWP( l_errl,
proc_slw_build,
l_fapi_cpu_target,
- reinterpret_cast<const void*>(poreImage),
- reinterpret_cast<uint32_t>(poreSize),
+ reinterpret_cast<const void*>(l_pPoreImage),
+ static_cast<uint32_t>(l_poreSize),
l_pImageOut,
&l_sizeImageOut
);
-#endif
-
if ( l_errl )
{
TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace,
diff --git a/src/usr/hwpf/hwp/build_winkle_images/makefile b/src/usr/hwpf/hwp/build_winkle_images/makefile
index f03ef1d30..c970dfd84 100644
--- a/src/usr/hwpf/hwp/build_winkle_images/makefile
+++ b/src/usr/hwpf/hwp/build_winkle_images/makefile
@@ -1,4 +1,4 @@
-# IBM_PROLOG_BEGIN_TAG
+# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
# $Source: src/usr/hwpf/hwp/build_winkle_images/makefile $
@@ -19,8 +19,7 @@
#
# Origin: 30
#
-# IBM_PROLOG_END
-
+# IBM_PROLOG_END_TAG
ROOTPATH = ../../../../..
MODULE = build_winkle_images
@@ -41,14 +40,24 @@ EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images
## NOTE: add a new EXTRAINCDIR when you add a new HWP
## EXAMPLE:
## EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/<HWP_dir>
+EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build
+
+CUSTOMFLAGS+= -D __FAPI
## NOTE: add new object files when you add a new HWP
-OBJS = build_winkle_images.o
+OBJS = build_winkle_images.o \
+ p8_image_help.o \
+ p8_pore_static_data.o \
+ p8_scan_compression.o \
+ pore_inline_assembler.o \
+ proc_slw_build.o \
+ sbe_xip_image.o
## NOTE: add a new directory onto the vpaths when you add a new HWP
## EXAMPLE:
# VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/<HWP_dir>
+VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build
## Point to the PORE image in PNOR
BINARY_FILES = $(IMGDIR)/procpore.dat:1f6e49c91e2a2b0df5fad6c215c8f09d9f19fce6
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/fapi_sbe_common.H b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/fapi_sbe_common.H
new file mode 100644
index 000000000..24868bb52
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/fapi_sbe_common.H
@@ -0,0 +1,70 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/fapi_sbe_common.H $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+#ifndef __FAPI_SBE_COMMON_H
+#define __FAPI_SBE_COMMON_H
+
+// $Id: fapi_sbe_common.H,v 1.1 2012/04/16 23:55:37 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/fapi_sbe_common.H,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! OWNER NAME : Email:
+
+/// \file fapi_sbe_common.H
+/// \brief Definitions common to FAPI and SBE procedures
+///
+/// Several preprocessor macros are required to have different definitions in
+/// C, C++ and SBE assembly procedures. These common forms are collected here.
+
+#if defined __ASSEMBLER__
+
+#define CONST_UINT8_T(name, expr) .set name, (expr)
+#define CONST_UINT32_T(name, expr) .set name, (expr)
+#define CONST_UINT64_T(name, expr) .set name, (expr)
+
+#define ULL(x) x
+
+#elif defined __cplusplus
+
+#include <stdint.h>
+
+#define CONST_UINT8_T(name, expr) const uint8_t name = (expr);
+#define CONST_UINT32_T(name, expr) const uint32_t name = (expr);
+#define CONST_UINT64_T(name, expr) const uint64_t name = (expr);
+
+#define ULL(x) x##ull
+
+#else // C code
+
+// CONST_UINT[8,3,64]_T() can't be used in C code/headers; Use
+//
+// #define <symbol> <value> [ or ULL(<value>) for 64-bit constants
+
+#define ULL(x) x##ull
+
+#endif // __ASSEMBLER__
+
+#endif // __FAPI_SBE_COMMON_H
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h
new file mode 100644
index 000000000..6cdf89108
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h
@@ -0,0 +1,261 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_delta_scan_rw.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+//***** IMPORTANT - Assumptions (you may have to change these settings) ******
+#define ASM_RS4_LAUNCH_BUF_SIZE 24 // Byte size of binary RS4 launch buffer w/last two
+ // nops removed.
+#define OVERRIDE_OFFSET 8 // Byte offset of forward pointer's addr relative
+ // to base forward pointer's addr.
+#define SLW_MS_MAX_BUF_SIZE 50000000 // Max 50MB for SLW mainstore image.
+
+/***** Scan Control Regs *****/
+#define P8_PORE_CLOCK_CONTROLLER_REG 0x00030007 // Addr of clock ctrl scom reg
+#define P8_PORE_SHIFT_REG 0x00038000 // Addr of scom reg that does scan ring shifting
+#define P8_SCAN_CHECK_WORD 0xA5A55A5A // Header check word
+
+/***** Ring state *****/
+#define MAX_RING_SIZE 1000000 // This is the max binary ring size in bits
+
+// Debug and development stuff
+#define IGNORE_FOR_NOW // Causes code sections to be ignored.
+#define DEBUG_SUPPORT // Activates sbe-xip debug support.
+#define PRINT_WF_DIS // Causes wf inline code to be disassembled and written to file.
+
+/***** Return codes *****/
+#define DSLWB_RING_SEARCH_MATCH 0
+#define DSLWB_RING_SEARCH_EXHAUST_MATCH 30
+#define DSLWB_RING_SEARCH_NO_MATCH 31
+#define DSLWB_RING_SEARCH_MESS 32
+#define DSLWB_SLWB_SUCCESS 0
+#define DSLWB_SLWB_NO_RING_MATCH 40
+#define DSLWB_SLWB_DX_ERROR 41
+#define DSLWB_SLWB_WF_ERROR 42
+#define DSLWB_SLWB_WF_IMAGE_ERROR 43
+#define DSLWB_SLWB_IMAGE_ERROR 44
+#define DSLWB_SLWB_UNKNOWN_ERROR 45
+#define IMGBUILD_SUCCESS 0 // Successful image build.
+#define IMGBUILD_ERR_MEMORY 20 // Memory allocation error.
+#define IMGBUILD_ERR_XIP_MISC 25 // Miscellaneous XIP image error.
+#define IMGBUILD_ERR_SECTION_DELETE 50 // Err assoc w/deleting ELF section.
+#define IMGBUILD_ERR_APPEND 51 // Err assoc w/appending to ELF section.
+#define IMGBUILD_ERR_INCOMPLETE_IMG_BUILD 52 // The image was built, but with errors.
+#define IMGBUILD_ERR_FWD_BACK_PTR_MESS 53 // Forward or backward pointer mess.
+#define IMGBUILD_ERR_KEYWORD_NOT_FOUND 54 // Image keyword not found.
+#define IMGBUILD_ERR_MISALIGNED_RING_LAYOUT 55 // Ring layout is misaligned.
+#define IMGBUILD_ERR_IMAGE_TOO_LARGE 56 // Image too large. Exceeded max size.
+#define IMGBUILD_ERR_CHECK_CODE 60 // Coding problem - impossible state.
+
+#ifdef __FAPI
+#define MY_INF(_fmt_, _args_...) FAPI_INF(_fmt_, ##_args_)
+#ifndef SLW_COMMAND_LINE
+#define MY_ERR(_fmt_, _args_...) FAPI_ERR(_fmt_, ##_args_)
+#else
+#define MY_ERR(_fmt_, _args_...) FAPI_INF(_fmt_, ##_args_)
+#endif // End of SLW_COMMAND_LINE
+#define MY_DBG(_fmt_, _args_...) FAPI_DBG(_fmt_, ##_args_)
+#else
+#define MY_INF(_fmt_, _args_...) fprintf(stdout, _fmt_, ##_args_)
+#define MY_ERR(_fmt_, _args_...) fprintf(stderr, _fmt_, ##_args_)
+#define MY_DBG(_fmt_, _args_...) fprintf(stdout, _fmt_, ##_args_)
+#endif // End of FAPI
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef SLW_COMMAND_LINE
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#endif //End of SLW_COMMAND_LINE
+#ifndef SLW_BUILD_WF_P0_FIX
+#include "pore_bitmanip.H"
+#endif // SLW_BUILD_WF_P0_FIX
+#include "p8_pore_api.h"
+#include "p8_pore_static_data.h"
+#include "p8_scan_compression.H"
+#include "sbe_xip_image.h"
+#undef __PORE_INLINE_ASSEMBLER_C__
+#include "pore_inline.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Info:
+// DeltaRingLayout describes the sequential order of the content in the compressed delta
+// ring blocks in the .initf section in the SBE-XIP images.
+// When creating the .initf delta ring blocks, the following rules must be followed:
+// - Everything must be stored in BE format.
+// - {entryOffset; sizeOfThis; sizeOfMeta; metaData} must be word-aligned to ensure
+// that the {rs4Launch} starts on a word boundary.
+// - {rs4Launch} must start on a word boundary (see earlier rule how to do that).
+// - {entryOffset; sizeOfThis; sizeOfMeta; metaData; rs4Launch} must be double-word-
+// aligned to ensure that {rs4Delta} starts on a double-word boundary.
+// - {rs4Delta} must start on a double-word bournday (see earlier rule how to do that).
+//
+typedef struct {
+ uint64_t entryOffset;
+ uint64_t backItemPtr;
+ uint32_t sizeOfThis;
+ uint32_t sizeOfMeta; // Exact size of meta data. Arbitrary size. Not null terminated.
+ uint32_t ddLevel;
+ uint8_t sysPhase;
+ uint8_t override;
+ uint8_t reserved1;
+ uint8_t reserved2;
+ char *metaData; // Arbitrary size. Extra bytes to next alignment are random or 0s.
+ uint32_t *rs4Launch; // Code. Must be 4-byte aligned.
+ uint32_t *rs4Delta; // Data. Must be 8-byte aligned.
+ uint32_t *wfInline; // Code. Must be 4-byte aligned.
+} DeltaRingLayout;
+
+typedef struct {
+ uint32_t sizeOfData;
+ char data[];
+} MetaData;
+
+int p8_ipl_build( void *i_imageIn,
+ uint32_t i_ddLevel,
+ void *i_imageOut,
+ uint32_t i_sizeImageOutMax);
+
+int get_ring_layout_from_image2( const void *i_imageIn,
+ uint32_t i_ddLevel,
+ uint8_t i_sysPhase,
+ DeltaRingLayout **o_rs4RingLayout,
+ void **nextRing);
+
+int write_ring_block_to_image( void *io_image,
+ DeltaRingLayout *i_ringBlock,
+ uint32_t i_sizeImageMax);
+
+int gen_ring_delta_state(
+ uint32_t bitLen,
+ uint32_t *i_init,
+ uint32_t *i_alter,
+ uint32_t *o_delta,
+ uint32_t verbose);
+
+int write_delta_ring_to_image(
+ char *i_fnImage,
+ CompressedScanData *i_RS4,
+ uint32_t i_ddLevel,
+ uint8_t i_sysPhase,
+ uint8_t i_override,
+ char *i_varName,
+ char *i_fnMetaData,
+ uint32_t verbose);
+
+int get_delta_ring_from_image(
+ char *i_fnImage,
+ char *i_varName,
+ uint32_t i_ddLevel,
+ uint8_t i_sysPhase,
+ uint8_t i_override,
+ MetaData **o_metaData,
+ CompressedScanData **o_deltaRingRS4,
+ uint32_t verbose);
+
+int write_wiggle_flip_to_image(
+ void *io_imageOut,
+ uint32_t *i_sizeImageMaxNew,
+ DeltaRingLayout *i_ringLayout,
+ uint32_t *i_wfInline,
+ uint32_t i_wfInlineLenInWords);
+
+int get_ring_layout_from_image(
+ const void *i_imageIn,
+ uint32_t i_ddLevel,
+ uint8_t i_sysPhase,
+ DeltaRingLayout *o_rs4RingLayout,
+ void **nextRing);
+
+int create_wiggle_flip_prg(
+ uint32_t *i_deltaRing,
+ uint32_t i_ringBitLen,
+ uint32_t i_scanSelectData,
+ uint32_t i_chipletID,
+ uint32_t **o_wfInline,
+ uint32_t *o_wfInlineLenInWords);
+
+int append_empty_section(
+ void *io_image,
+ uint32_t *i_sizeImageMaxNew,
+ uint32_t i_sectionId,
+ uint32_t i_sizeSection);
+
+void cleanup(
+ void *buf1=NULL,
+ void *buf2=NULL,
+ void *buf3=NULL,
+ void *buf4=NULL,
+ void *buf5=NULL);
+
+// Byte-reverse a 32-bit integer if on an LE machine
+inline uint32_t myRev32(const uint32_t i_x)
+{
+ uint32_t rx;
+
+#ifdef _BIG_ENDIAN
+ rx = i_x;
+#else
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[3];
+ prx[1] = pix[2];
+ prx[2] = pix[1];
+ prx[3] = pix[0];
+#endif
+
+ return rx;
+}
+
+// Byte-reverse a 64-bit integer if on a little-endian machine
+inline uint64_t myRev64(const uint64_t i_x)
+{
+ uint64_t rx;
+
+#ifdef _BIG_ENDIAN
+ rx = i_x;
+#else
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[7];
+ prx[1] = pix[6];
+ prx[2] = pix[5];
+ prx[3] = pix[4];
+ prx[4] = pix[3];
+ prx[5] = pix[2];
+ prx[6] = pix[1];
+ prx[7] = pix[0];
+#endif
+
+ return rx;
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C
new file mode 100644
index 000000000..6f0fe7af2
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C
@@ -0,0 +1,718 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_image_help.C $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/*------------------------------------------------------------------------------*/
+/* *! TITLE : p8_image_help.C */
+/* *! DESCRIPTION : Helper functions for building and extracting information */
+// from SBE-XIP images.
+/* *! OWNER NAME : Michael Olsen cmolsen@us.ibm.com */
+//
+/* *! EXTENDED DESCRIPTION : */
+//
+/* *! USAGE : */
+//
+/* *! ASSUMPTIONS : */
+//
+/* *! COMMENTS : */
+//
+/*------------------------------------------------------------------------------*/
+
+#include "p8_delta_scan_rw.h"
+
+#ifdef __FAPI
+#include <fapi.H>
+#endif
+extern "C" {
+
+
+// get_ring_layout_from_image()
+//
+int get_ring_layout_from_image( const void *i_imageIn,
+ uint32_t i_ddLevel,
+ uint8_t i_sysPhase,
+ DeltaRingLayout *o_rs4RingLayout,
+ void **nextRing)
+{
+ uint32_t rc=0, rcLoc=0;
+ uint8_t bRingFound=0, bRingEOS=0;
+ DeltaRingLayout *thisRingLayout, *nextRingLayout; //Pointers into memory mapped image. DO NOT CHANGE MEMBERS!
+ uint32_t sizeInitf;
+ SbeXipSection hostSection;
+ void *initfHostAddress0;
+
+ SBE_XIP_ERROR_STRINGS(errorStrings);
+
+ // Always first get the .initf stats from the TOC:
+ // - .initf host address offset and
+ // - .initf size
+ //
+ rc = sbe_xip_get_section( i_imageIn, SBE_XIP_SECTION_RINGS, &hostSection);
+ if (rc) {
+ MY_ERR("ERROR : sbe_xip_get_section() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ MY_ERR("Probable cause:");
+ MY_ERR("\tThe section (=SBE_XIP_SECTION_RINGS=%i) was not found.",SBE_XIP_SECTION_RINGS);
+ return IMGBUILD_ERR_KEYWORD_NOT_FOUND;
+ }
+ if (hostSection.iv_offset==0) {
+ MY_INF("INFO : No ring data exists for the section ID = SBE_XIP_SECTION_RINGS (ID=%i).",SBE_XIP_SECTION_RINGS);
+ return DSLWB_RING_SEARCH_NO_MATCH; // Implies exhaust search as well.
+ }
+ initfHostAddress0 = (void*)((uintptr_t)i_imageIn + hostSection.iv_offset);
+ sizeInitf = hostSection.iv_size;
+
+ // On first call, get the base offset to the .initf section.
+ // On subsequent calls, we're into the search for ddLevel and sysPhase, so use nextRing instead.
+ //
+ if (*nextRing==NULL)
+ nextRingLayout = (DeltaRingLayout*)initfHostAddress0;
+ else
+ nextRingLayout = (DeltaRingLayout*)*nextRing;
+
+ MY_DBG("initfHostAddress0 = 0x%016llx",(uint64_t)initfHostAddress0);
+ MY_DBG("sizeInitf = %i", sizeInitf);
+ MY_DBG("nextRingLayout = 0x%016llx",(uint64_t)nextRingLayout);
+
+ // Populate the output RS4 ring BE layout structure as well as local structure in host LE format where needed.
+ // Note! Entire memory content is in BE format. So we do LE conversions where needed.
+ //
+ bRingFound = 0;
+ bRingEOS = 0;
+
+ // SEARCH loop: Parse ring blocks successively until we find a ring that matches:
+ // ddLevel == i_ddLevel
+ // sysPhase == i_sysPhase
+ //
+ while (!bRingFound && !bRingEOS) {
+ thisRingLayout = nextRingLayout;
+ MY_DBG("Next backItemPtr = 0x%016llx",myRev64(thisRingLayout->backItemPtr));
+ MY_DBG("Next ddLevel = 0x%02x",myRev32(thisRingLayout->ddLevel));
+ MY_DBG("Next sysPhase = %i",thisRingLayout->sysPhase);
+ MY_DBG("Next override = %i",thisRingLayout->override);
+ MY_DBG("Next reserved1 = %i",thisRingLayout->reserved1);
+ MY_DBG("Next reserved2 = %i",thisRingLayout->reserved2);
+
+ if (myRev32(thisRingLayout->ddLevel)==i_ddLevel) { // Is there a non-specific DD level, like for sys phase?
+ if ((thisRingLayout->sysPhase==0 && i_sysPhase==0) ||
+ (thisRingLayout->sysPhase==1 && i_sysPhase==1) ||
+ (thisRingLayout->sysPhase==2 && (i_sysPhase==0 || i_sysPhase==1))) {
+ bRingFound = 1;
+ MY_DBG("\tRing match found!");
+ }
+ }
+ nextRingLayout = (DeltaRingLayout*)((uintptr_t)thisRingLayout + myRev32(thisRingLayout->sizeOfThis));
+ *nextRing = (void*)nextRingLayout;
+ if (nextRingLayout>=(DeltaRingLayout*)((uintptr_t)initfHostAddress0+sizeInitf)) {
+ bRingEOS = 1;
+ *nextRing = NULL;
+ MY_DBG("\tRing search exhausted!");
+ }
+
+ } // End of SEARCH.
+
+ if (bRingFound) {
+ if (bRingEOS)
+ rcLoc = DSLWB_RING_SEARCH_EXHAUST_MATCH;
+ else
+ rcLoc = DSLWB_RING_SEARCH_MATCH;
+ }
+ else {
+ *nextRing = NULL;
+ if (bRingEOS)
+ return DSLWB_RING_SEARCH_NO_MATCH; // Implies exhaust search as well.
+ else {
+ MY_ERR("Messed up ring search. Check code and .rings content. Returning nothing.");
+ return DSLWB_RING_SEARCH_MESS;
+ }
+ }
+
+ o_rs4RingLayout->entryOffset = thisRingLayout->entryOffset;
+ o_rs4RingLayout->backItemPtr = thisRingLayout->backItemPtr;
+ o_rs4RingLayout->sizeOfThis = thisRingLayout->sizeOfThis;
+ o_rs4RingLayout->sizeOfMeta = thisRingLayout->sizeOfMeta;
+ o_rs4RingLayout->ddLevel = thisRingLayout->ddLevel;
+ o_rs4RingLayout->sysPhase = thisRingLayout->sysPhase;
+ o_rs4RingLayout->override = thisRingLayout->override;
+ o_rs4RingLayout->reserved1 = thisRingLayout->reserved1;
+ o_rs4RingLayout->reserved2 = thisRingLayout->reserved2;
+ o_rs4RingLayout->metaData = (char*)(&thisRingLayout->reserved2 +
+ sizeof(thisRingLayout->reserved2));
+ o_rs4RingLayout->rs4Launch = (uint32_t*)((uintptr_t)thisRingLayout +
+ myRev64(thisRingLayout->entryOffset));
+ // Since RS4 launch size is only word-aligned, make sure to point to nearest [higher] double-word boundary.
+ o_rs4RingLayout->rs4Delta = (uint32_t*)((((uintptr_t)thisRingLayout +
+ myRev64(thisRingLayout->entryOffset) +
+ ASM_RS4_LAUNCH_BUF_SIZE-1)/8+1)*8);
+
+ // Check that the ring layout structure in the memory is double-word aligned. This must be so because:
+ // - The entryOffset address must be on an 8-byte boundary because the start of the .initf ELF section must
+ // be 8-byte aligned AND because the rs4Delta member is the last member and which must itself be 8-byte aligned.
+ // - These two things together means that both the beginning and end of the delta ring layout must be 8-byte
+ // aligned, and thus the whole block,i.e. sizeOfThis, must be 8-byte aligned.
+ // Also check that the RS4 delta ring is double-word aligned.
+ // Also check that the RS4 launcher is word aligned.
+ //
+ if (((uintptr_t)thisRingLayout-(uintptr_t)i_imageIn)%8 ||
+ myRev32(o_rs4RingLayout->sizeOfThis)%8 ||
+ (uintptr_t)o_rs4RingLayout->rs4Launch%4 ||
+ (uintptr_t)o_rs4RingLayout->rs4Delta%8) {
+ MY_ERR("ERROR : Ring layout is not double-word-aligned or RS4 launcher is not word aligned.");
+ MY_ERR(" thisRingLayout#8 = 0x%016llx",(uint64_t)thisRingLayout%8);
+ MY_ERR(" myRev32(o_rs4RingLayout->sizeOfThis)#8 = %i",myRev32(o_rs4RingLayout->sizeOfThis)%8);
+ MY_ERR(" o_rs4RingLayout->rs4Launch#4 = 0x%016llx",(uint64_t)o_rs4RingLayout->rs4Launch%4);
+ MY_ERR(" o_rs4RingLayout->rs4Delta#8 = 0x%016llx",(uint64_t)o_rs4RingLayout->rs4Delta%8);
+ return IMGBUILD_ERR_MISALIGNED_RING_LAYOUT;
+ }
+
+ if (*nextRing > (void*)((uintptr_t)initfHostAddress0 + sizeInitf)) {
+ MY_INF("INFO : Book keeping got messed up during .initf search. Initf section does not appear aligned.");
+ MY_INF("initfHostAddress0+sizeInitf = 0x%016llx",(uint64_t)initfHostAddress0+sizeInitf);
+ MY_INF("nextRing = %i",*(uint32_t*)nextRing);
+ MY_INF("Continuing...");
+ }
+
+ return rcLoc;
+}
+
+
+
+// create_wiggle_flip_prg() function
+// Notes:
+// - WF procedure needs to be updated with polling protocol.
+// - WF procedure needs to reflect P0/P1 usage policy
+int create_wiggle_flip_prg( uint32_t *i_deltaRing, // scan ring delta state
+ uint32_t i_ringBitLen, // length of ring
+ uint32_t i_scanSelectData, // Scan ring modifier data
+ uint32_t i_chipletID, // Chiplet ID
+ uint32_t **o_wfInline, // location of the PORE instructions data stream
+ uint32_t *o_wfInlineLenInWords) // final length of data stream
+{
+ uint32_t rc=P8_PORE_SUCCESS_RC; //defined in p8_pore_api_const.h
+ uint32_t i=0;
+ uint32_t scanSelectAddr=0;
+ uint32_t scanRing_baseAddr=0;
+ uint32_t scanRing_poreAddr=0;
+ uint32_t scanRingCheckWord=0;
+ uint32_t count=0;
+ uint32_t rotateLen=0, remainder=0, remainingBits=0;
+ uint32_t osIndex=0;
+ int pgas_rc=0;
+ uint64_t pore_imm64b=0;
+ uint32_t maxWfInlineLenInWords = 10*MAX_RING_SIZE/32;
+ PoreInlineContext ctx;
+ PoreInlineLocation src3=0, tgt3=0;
+
+ *o_wfInline = (uint32_t*)malloc(maxWfInlineLenInWords);
+
+ //pore_inline_context_create(&ctx, buf, P8_PORE_BUFSIZE * 4, 0, PORE_INLINE_CHECK_PARITY);
+ pore_inline_context_create(&ctx, *o_wfInline, maxWfInlineLenInWords * 4, 0, 0);
+
+ // Get chiplet and Ring Addr info.
+ // --------------------------------------------------------------------------
+
+ // Set Default scanselq addr and scanring addr vars
+ scanSelectAddr=P8_PORE_CLOCK_CONTROLLER_REG; // 0x00030007: port 3 - clock cotrol endpt, x07- scanselq (regin & types)
+ // Descr: Addr of clock control SCOM reg.
+ scanRing_baseAddr=P8_PORE_SHIFT_REG; // 0x00038000: port 3, addr bit 16 must be set to 1
+ // Also called GENERIC_CLK_SCANDATA0
+ // Descr: SCOM reg for scan ring shifting.
+ scanRing_poreAddr=scanRing_baseAddr; // Init scan ring rotate addr
+ scanRingCheckWord=P8_SCAN_CHECK_WORD; // Header check word for checking ring write was successful
+
+ // Program scanselq reg for scan clock control setup before ring scan
+ // --------------------------------------------------------------------------
+
+#ifndef SLW_BUILD_WF_P0_FIX
+// The following fix is a direct copy of the setp1_mcreadand macro in ./ipl/sbe/p8_slw.H
+ uint64_t CLEAR_MC_TYPE_MASK=0x47;
+ PoreInlineLocation src1=0, src2=0, tgt1=0, tgt2=0;
+ pgas_rc = pore_MR( &ctx, D1, P0) ||
+ pore_ANDI( &ctx, D1, D1, BIT(57)) ||
+ PORE_LOCATION( &ctx, src1) ||
+ pore_BRANZ( &ctx, D1, src1) ||
+ pore_MR( &ctx, P1, P0) ||
+ PORE_LOCATION( &ctx, src2) ||
+ pore_BRA( &ctx, tgt2) ||
+ PORE_LOCATION( &ctx, tgt1) ||
+ pore_MR( &ctx, D1, P0) ||
+ pore_ANDI( &ctx, D1, D1, CLEAR_MC_TYPE_MASK) ||
+ pore_ORI( &ctx, D1, D1, BIT(60)) ||
+ pore_MR( &ctx, P1, D1) ||
+ PORE_LOCATION( &ctx, tgt2);
+ if (pgas_rc>0) {
+ MY_ERR("***setp1_mcreadand rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+ pgas_rc = pore_inline_branch_fixup( &ctx, src1, tgt1) ||
+ pore_inline_branch_fixup( &ctx, src2, tgt2);
+ if (pgas_rc>0) {
+ MY_ERR("***inline_branch_fixup rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+#else
+ uint32_t epmCID = 0x11;
+ pgas_rc = pore_LS(&ctx, P0, epmCID); //bits 2:7 get loaded to perv reg 26:31
+ if (pgas_rc>0) {
+ MY_ERR("***LS rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+#endif
+
+ pore_imm64b = ((uint64_t)i_scanSelectData) << 32;
+ pgas_rc = pore_STI(&ctx, scanSelectAddr, P0, pore_imm64b);
+ if (pgas_rc>0) {
+ MY_ERR("***STI rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+
+ // Preload the scan data/shift reg with the scan header check word.
+ //
+ pore_imm64b = ((uint64_t)scanRingCheckWord) << 32;
+ pgas_rc = pore_LI(&ctx, D0, pore_imm64b );
+ if (pgas_rc > 0) {
+ MY_ERR("***(1)LI D0 rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+ pgas_rc = pore_STD(&ctx, D0, scanRing_baseAddr, P0);
+ if (pgas_rc > 0) {
+ MY_ERR("***STD D0 rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+
+ // Check how many 32-bit shift ops are needed and if we need final shift of remaining bit.
+ count = i_ringBitLen/32;
+ remainder = i_ringBitLen%32;
+ if (remainder >0)
+ count = count + 1;
+
+ // From P7+: skip first 32 bits associated with FSI engine
+ //TODO: check with perv design team if FSI 32 bit assumption is still valid in p8
+ //remainingBits=i_ringBitLen-32;
+ // CMO: I changed the following to not skip the first 32-bit.
+ //remainingBits = i_ringBitLen-32; //Yong impl.
+ remainingBits = i_ringBitLen; //Mike impl.
+
+ MY_DBG("count=%i rem=%i remBits=%i",count,remainder,remainingBits);
+
+ // Compare 32 bit data at a time then shift ring (p7+ reqmt)
+ // TODO: check if p8 still requires skipping the 1st 32 bit
+
+ // Read and compare init and flush values 32 bits at a time. Store delta in o_delta buffer.
+ //for (i=1; i<count; i++) { //Yong impl
+ for (i=0; i<count; i++) { //Mike impl
+
+ //====================================================================================
+ // If flush & init values are identical, increase the read count, no code needed.
+ // When the discrepancy is found, read (rotate the ring) up to current address
+ // then scan/write in the last 32 bits
+ //====================================================================================
+ // TODO: add polling routine and change the max ring to 65535? Need to check with HW team
+ // Note: For PORE scan instruction, set Port to 3. Bit 16 Must be set to 1.
+
+ if (i_deltaRing[i] > 0) {
+
+ if (rotateLen > 0) {
+ //--------------------------------------------------------------------------
+ // Rotate scan ring by the current rotate length
+ // rotate length is equivalent to current rotate addr - previous rotate addr
+ //
+ // Note space overflow is checked by inline assembler in P8
+ // TODO: Not useing SCR1RDA : check with perv team
+ // TODO: what to do with 1st 32 bit for FSI??
+ //--------------------------------------------------------------------------
+ //CMO: This addr calc only works if baseAddr=0 in those bits where rotateLen=1?
+ scanRing_poreAddr=scanRing_baseAddr | rotateLen;
+
+ MY_DBG("base addr = 0x8%x, pore addr = 0x8%x, rotatelen = %d", scanRing_baseAddr, scanRing_poreAddr, rotateLen);
+
+ //SCR1RD: shift out then read
+ pgas_rc=pore_LD(&ctx, D0, scanRing_poreAddr, P0);
+ if (pgas_rc > 0) {
+ MY_ERR("***LD D0 rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+
+ } // End of if (rotateLen>0)
+
+ // If the rotate length is <= 32, rotate by 32 or remaining bits if len <32
+ if (remainingBits>32)
+ scanRing_poreAddr = scanRing_baseAddr | 32;
+ else
+ scanRing_poreAddr = scanRing_baseAddr | remainingBits;
+
+ //LI : Load XORed value to Scratch 1 reg. (same as p7+)
+ //TODO: Check why not overwrite with init values?
+ pore_imm64b = ((uint64_t)i_deltaRing[i]) << 32;
+
+ pgas_rc = pore_LI(&ctx, D0, pore_imm64b );
+ if (pgas_rc > 0) {
+ MY_ERR("***(2)LI D0 rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+
+ pgas_rc = pore_STD(&ctx, D0, scanRing_poreAddr, P0);
+ if (pgas_rc > 0) {
+ MY_ERR("***STD D0 rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+
+ rotateLen=0; //reset rotate length
+ }
+ else {
+ // OK, so i_deltaRing==0 (init and alter states are identical)
+ // Increase rotate length by remaining scan bits (32 by default)
+ // TODO : the max rotate ring size needs to be modified.
+ // there will be no size limit, but will add polling once the feture is available
+
+ // Increase rotate length by remaining scan bits (default 32 bits)
+ if (remainingBits>32)
+ rotateLen = rotateLen + 32;
+ else
+ rotateLen = rotateLen + remainingBits;
+
+ // This section will be modfied
+ // PORE does not release PIB/PCB until CC acks, thus limiting bandwidth
+ // It will time out if more than 4095 bits need to be rotated
+ // If rotate length is more than 4032 (allows to rotate up to 4064 bits
+ // Rotate the chain and reset rotate length counter
+ if (rotateLen>0xFC0) {
+ scanRing_poreAddr = scanRing_baseAddr | rotateLen;
+ pgas_rc = pore_LD(&ctx, D0, scanRing_poreAddr, P0);
+ if (pgas_rc > 0) {
+ MY_ERR("***LD D0 rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+
+ rotateLen=0;
+ } //end of if (roateLen >0xFC0)
+
+ } //end of else (i_deltaRing==0)
+
+ if (remainingBits>32)
+ remainingBits = remainingBits - 32;
+ else
+ remainingBits = 0;
+
+ } // End of for loop
+
+ // If the scan ring has not been rotated to the original position
+ // shift the ring by remaining shift bit length
+ if (rotateLen>0) {
+ scanRing_poreAddr=scanRing_baseAddr | rotateLen;
+ pgas_rc = pore_LD(&ctx, D0, scanRing_poreAddr, P0);
+ if (pgas_rc > 0) {
+ MY_ERR("***LD D0 rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+ rotateLen=0;
+ }
+
+ // Finally, check that our header check word went through in one piece.
+ //
+ // Load the output check word...
+ pgas_rc = pore_LD(&ctx, D0, scanRing_baseAddr, P0) |
+ // Compare against the reference header check word...
+ pore_XORI( &ctx, D0, D0, ((uint64_t)scanRingCheckWord) << 32) |
+ // For now, branch to HALT instruction if not equal, otherwise return in the following instruction...
+ // But eventually branch to firmware error_handler if not equal
+ // pore_BRANZ(&ctx, D0, error_handler) ||
+ PORE_LOCATION( &ctx, src3) |
+// pore_BRANZ( &ctx, D0, ctx.lc+8) || // Jump two 4-byte instr (incl this one) to get to HALT.
+ pore_BRANZ( &ctx, D0, tgt3) | // Jump two 4-byte instr (incl this one) to get to HALT.
+ pore_RET( &ctx) |
+ PORE_LOCATION( &ctx, tgt3) |
+ pore_HALT( &ctx);
+ if (pgas_rc > 0) {
+ MY_ERR("***LD, XORI, BRANZ, RET or HALT went wrong rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+ pgas_rc = pore_inline_branch_fixup( &ctx, src3, tgt3);
+ if (pgas_rc>0) {
+ MY_ERR("***inline_branch_fixup rc = %d", pgas_rc);
+ return pgas_rc;
+ }
+
+ osIndex = ctx.lc/4;
+ *o_wfInlineLenInWords = osIndex;
+
+ return rc;
+}
+
+
+
+// write_wiggle_flip_to_image()
+// 1 - mmap input image,
+// 2 - Compose delta binary buffer containing RS4 launcher + RS4 delta data,
+// 3 - Append delta buffer to .initf section.
+// 4 - Save new image to output image file.
+int write_wiggle_flip_to_image( void *io_imageOut,
+ uint32_t *i_sizeImageMaxNew,
+ DeltaRingLayout *i_ringLayout,
+ uint32_t *i_wfInline,
+ uint32_t i_wfInlineLenInWords)
+{
+ uint32_t rc=0, bufLC;
+ uint32_t sizeImageIn, sizeNewDataBlock;
+ uint32_t sizeImageOutThisEst=0, sizeImageOutThis=0;
+ void *initfBuffer=NULL;
+ uint32_t ringRingsOffset=0;
+ uint64_t ringPoreAddress=0,backPtr=0,fwdPtr=0,fwdPtrCheck;
+
+ SBE_XIP_ERROR_STRINGS(errorStrings);
+
+ MY_DBG("wfInlineLenInWords=%i", i_wfInlineLenInWords);
+
+ // Modify the input ring layout content
+ // - Remove the qualifier section: ddLevel, sysPhase, override and reserved1+2. This means
+ // reducing the entryOffset by the size of these qualifiers.
+ // - Adjust sizeOfThis
+ // - Use new wfInline member of ring layout struct.
+ // - Ignore the rs4Delta member
+ //
+ // For sizeOfThis, we must ensure 4-byte alignment WF code. That is easy since both entryOffset
+ // and wfInlineLenInWord are already word-aligned.
+ //
+ i_ringLayout->entryOffset = myRev64( myRev64(i_ringLayout->entryOffset) -
+ sizeof(i_ringLayout->ddLevel) -
+ sizeof(i_ringLayout->sysPhase) -
+ sizeof(i_ringLayout->override) -
+ sizeof(i_ringLayout->reserved1) -
+ sizeof(i_ringLayout->reserved2) );
+ i_ringLayout->sizeOfThis = myRev32( myRev64(i_ringLayout->entryOffset) +
+ i_wfInlineLenInWords*4 );
+ // Not really any need for this. Just being consistent. Once we have transitioned completely to new
+ // headers, then ditch i_wfInline from parm list and assign wfInline to layout in main program.
+ i_ringLayout->wfInline = i_wfInline;
+
+ if (((uintptr_t)i_ringLayout)%4 || myRev64(i_ringLayout->entryOffset)%4) {
+ MY_ERR("ERROR : Ring layout is not word-aligned.");
+ return IMGBUILD_ERR_MISALIGNED_RING_LAYOUT;
+ }
+
+ // Calc the size of the data section we're adding and the resulting output image.
+ //
+ rc = sbe_xip_image_size( io_imageOut, &sizeImageIn);
+ if (rc) {
+ MY_ERR("ERROR : sbe_xip_image_size() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ return IMGBUILD_ERR_XIP_MISC;
+ }
+ sizeNewDataBlock = myRev32(i_ringLayout->sizeOfThis);
+ // ...estimate max size of new image
+ sizeImageOutThisEst = sizeImageIn + sizeNewDataBlock + SBE_XIP_MAX_SECTION_ALIGNMENT; //
+
+ if (sizeImageOutThisEst>*i_sizeImageMaxNew) {
+ MY_ERR("ERROR : Estimated new image size (=%i) would exceed max allowed size (=%i).",
+ sizeImageOutThisEst, *i_sizeImageMaxNew);
+ *i_sizeImageMaxNew = sizeImageOutThisEst;
+ return IMGBUILD_ERR_IMAGE_TOO_LARGE;
+ }
+
+ MY_DBG("Input image size\t\t= %6i\n\tNew initf data block size\t= %6i\n\tOutput image size\t\t<=%6i",
+ sizeImageIn, sizeNewDataBlock, sizeImageOutThisEst);
+ MY_DBG("entryOffset = %i\n\tsizeOfThis = %i\n\tMeta data size = %i",
+ (uint32_t)myRev64(i_ringLayout->entryOffset), myRev32(i_ringLayout->sizeOfThis), myRev32(i_ringLayout->sizeOfMeta));
+ MY_DBG("Back item ptr = 0x%016llx",myRev64(i_ringLayout->backItemPtr));
+ MY_DBG("DD level = %i\n\tSys phase = %i\n\tOverride = %i\n\tReserved1+2 = %i",
+ myRev32(i_ringLayout->ddLevel), i_ringLayout->sysPhase, i_ringLayout->override, i_ringLayout->reserved1|i_ringLayout->reserved2);
+
+ // Combine rs4RingLayout members into a unified buffer (initfBuffer).
+ //
+ initfBuffer = malloc((size_t)sizeNewDataBlock);
+ if (initfBuffer == NULL) {
+ MY_ERR("ERROR : malloc() of initf buffer failed.");
+ return IMGBUILD_ERR_MEMORY;
+ }
+ // ... and copy the WF ring layout content into initfBuffer in BIG-ENDIAN format.
+ bufLC = 0;
+ memcpy( (uint8_t*)initfBuffer+bufLC, &i_ringLayout->entryOffset, (uintptr_t)&i_ringLayout->metaData-(uintptr_t)&i_ringLayout->entryOffset);
+ bufLC = (uintptr_t)&i_ringLayout->metaData-(uintptr_t)&i_ringLayout->entryOffset;
+ memcpy( (uint8_t*)initfBuffer+bufLC, i_ringLayout->metaData, myRev32(i_ringLayout->sizeOfMeta));
+
+ bufLC = (uint32_t)myRev64(i_ringLayout->entryOffset);
+ // The above forces word-alignment of bufLC as [previous] metaData member is only byte aligned.
+ memcpy( (uint8_t*)initfBuffer+bufLC, i_wfInline, i_wfInlineLenInWords*4);
+
+ // Append WF ring layout to .rings section of in-memory input image.
+ // Note! All layout members should already be 4-byte-aligned.
+ //
+ rc = sbe_xip_append( io_imageOut,
+ SBE_XIP_SECTION_RINGS,
+ (void*)initfBuffer,
+ sizeNewDataBlock,
+ sizeImageOutThisEst,
+ &ringRingsOffset);
+ MY_DBG("ringRingsOffset=0x%08x",ringRingsOffset);
+ if (rc) {
+ MY_ERR("ERROR : sbe_xip_append() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ if (initfBuffer) free(initfBuffer);
+ return IMGBUILD_ERR_XIP_MISC;
+ }
+ // ...get new image size, update return size, and test if successful update.
+ sbe_xip_image_size( io_imageOut, &sizeImageOutThis);
+ MY_DBG("Output image size (final)\t=%i",sizeImageOutThis);
+ *i_sizeImageMaxNew = sizeImageOutThis;
+ rc = sbe_xip_validate( io_imageOut, sizeImageOutThis);
+ if (rc) {
+ MY_ERR("ERROR : sbe_xip_validate() of output image failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ if (initfBuffer) free(initfBuffer);
+ return IMGBUILD_ERR_XIP_MISC;
+ }
+ MY_DBG("Successful append of RS4 ring to .rings. Next, update forward ptr...");
+
+ // Update forward pointer associated with the ring/var name + any override offset.
+ //
+ // Convert the ring offset (wrt .rings address) to an PORE address
+ rc = sbe_xip_section2pore(io_imageOut, SBE_XIP_SECTION_RINGS, ringRingsOffset, &ringPoreAddress);
+ fwdPtr = ringPoreAddress;
+ MY_DBG("fwdPtr=0x%016llx", fwdPtr);
+ if (rc) {
+ MY_ERR("ERROR : sbe_xip_section2pore() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ if (initfBuffer) free(initfBuffer);
+ return IMGBUILD_ERR_XIP_MISC;
+ }
+ // ...then update the forward pointer, i.e. the old "variable/ring name's" pointer.
+ // DO NOT add any 8-byte offset if override ring. The backItemPtr already has this
+ // from p8_delta_scan.
+ //
+ backPtr = myRev64(i_ringLayout->backItemPtr);
+ MY_DBG("backPtr = 0x%016llx", backPtr);
+ rc = sbe_xip_write_uint64( io_imageOut,
+ backPtr,
+ fwdPtr);
+ rc = rc+sbe_xip_read_uint64(io_imageOut,
+ backPtr,
+ &fwdPtrCheck);
+ if (rc) {
+ MY_ERR("ERROR : sbe_xip_[write,read]_uint64() failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ if (initfBuffer) free(initfBuffer);
+ return IMGBUILD_ERR_XIP_MISC;
+ }
+ if (fwdPtrCheck!=ringPoreAddress || backPtr!=myRev64(i_ringLayout->backItemPtr)) {
+ MY_ERR("ERROR : Forward or backward pointer mess. Check code.");
+ MY_ERR("fwdPtr =0x%016llx",fwdPtr);
+ MY_ERR("fwdPtrCheck =0x%016llx",fwdPtrCheck);
+ MY_ERR("layout bckPtr=0x%016llx",myRev64(i_ringLayout->backItemPtr));
+ MY_ERR("backPtr =0x%016llx",backPtr);
+ if (initfBuffer) free(initfBuffer);
+ return IMGBUILD_ERR_FWD_BACK_PTR_MESS;
+ }
+ // ...test if successful update.
+ rc = sbe_xip_validate( io_imageOut, sizeImageOutThis);
+ if (rc) {
+ MY_ERR("ERROR : sbe_xip_validate() of output image failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ MY_ERR("Probable cause:");
+ MY_ERR("\tsbe_xip_write_uint64() updated at the wrong address (=0x%016llx)",
+ myRev64(i_ringLayout->backItemPtr));
+ if (initfBuffer) free(initfBuffer);
+ return IMGBUILD_ERR_XIP_MISC;
+ }
+
+ if (initfBuffer) free(initfBuffer);
+
+ return rc;
+}
+
+
+
+// append_empty_section()
+int append_empty_section( void *io_image,
+ uint32_t *i_sizeImageMaxNew,
+ uint32_t i_sectionId,
+ uint32_t i_sizeSection)
+{
+ uint32_t rc=0;
+ uint32_t sizeImageIn=0, sizeImageOutThis=0, sizeImageOutThisEst=0;
+ uint32_t offsetCheck=1;
+ void *bufEmpty=NULL;
+
+ SBE_XIP_ERROR_STRINGS(errorStrings);
+
+ rc = 0;
+
+ if (i_sizeSection==0) {
+ MY_INF("INFO : Requested append size = 0. Nothing to do.");
+ return rc;
+ }
+
+ // Check if there is enough room in the new image to add section.
+ //
+ sbe_xip_image_size( io_image, &sizeImageIn);
+ // ...estimate max size of new image
+ sizeImageOutThisEst = sizeImageIn + i_sizeSection + SBE_XIP_MAX_SECTION_ALIGNMENT;
+ if (sizeImageOutThisEst>*i_sizeImageMaxNew) {
+ MY_ERR("ERROR : Estimated new image size (=%i) would exceed max allowed size (=%i).",
+ sizeImageOutThisEst, *i_sizeImageMaxNew);
+ *i_sizeImageMaxNew = sizeImageOutThisEst;
+ return IMGBUILD_ERR_IMAGE_TOO_LARGE;
+ }
+
+ // Add the 0-initialized buffer as a section append.
+ //
+ bufEmpty = calloc( i_sizeSection, 1);
+ rc = sbe_xip_append( io_image,
+ i_sectionId,
+ bufEmpty,
+ i_sizeSection,
+ sizeImageOutThisEst,
+ &offsetCheck);
+ if (rc) {
+ MY_ERR("ERROR : xip_append() failed: %s\n",SBE_XIP_ERROR_STRING(errorStrings, rc));
+ if (bufEmpty)
+ free(bufEmpty);
+ return DSLWB_SLWB_IMAGE_ERROR;
+ }
+ if (offsetCheck)
+ MY_INF("INFO : Section was not empty at time of xip_append(). It contained %i bytes.",offsetCheck);
+ // ...get new image size, update return size, and test if successful update.
+ sbe_xip_image_size( io_image, &sizeImageOutThis);
+ MY_DBG("Output image size (final)\t=%i",sizeImageOutThis);
+ *i_sizeImageMaxNew = sizeImageOutThis;
+ rc = sbe_xip_validate( io_image, sizeImageOutThis);
+ if (rc) {
+ MY_ERR("ERROR : xip_validate() of output image failed: %s", SBE_XIP_ERROR_STRING(errorStrings, rc));
+ if (bufEmpty) free(bufEmpty);
+ return IMGBUILD_ERR_XIP_MISC;
+ }
+
+ if (bufEmpty)
+ free(bufEmpty);
+
+ return rc;
+}
+
+
+
+void cleanup( void *buf1,
+ void *buf2,
+ void *buf3,
+ void *buf4,
+ void *buf5)
+{
+ if (buf1) free(buf1);
+ if (buf2) free(buf2);
+ if (buf3) free(buf3);
+ if (buf4) free(buf4);
+ if (buf5) free(buf5);
+}
+
+
+}
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api.h
new file mode 100644
index 000000000..0656f0a1c
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api.h
@@ -0,0 +1,283 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/* $Id: p8_pore_api.h,v 1.2 2012/04/11 16:58:29 cmolsen Exp $ */
+/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_pore_api.h,v $ */
+/*------------------------------------------------------------------------------*/
+/* *! (C) Copyright International Business Machines Corp. 2010 */
+/* *! All Rights Reserved -- Property of IBM */
+/* *! *** IBM Confidential *** */
+/*------------------------------------------------------------------------------*/
+/* *! TITLE p8_pore_api */
+/* *! DESCRIPTION : PORE APIs */
+/* *! OWNER NAME : Nicole Schwartz Email: nschwart@us.ibm.com */
+/* *! BACKUP NAME : */
+/* *! ADDITIONAL COMMENTS : */
+
+/*------------------------------------------------------------------------------*/
+/* Don't forget to create CVS comments when you check in your changes! */
+/*------------------------------------------------------------------------------*/
+
+#ifndef _P8P_PORE_API_H
+#define _P8P_PORE_API_H
+
+/**
+ * Contains all external APIs used by firmware to generate/modify the P7+
+ * PORE image.
+ */
+
+
+#include "p8_pore_api_custom.h"
+/*#include <p7p_pore_image.h>*/
+#include "p8_pore_api_const.h"
+
+typedef struct {
+ char ringName[50];
+ uint32_t ringAddress;
+ uint32_t clockControlData;
+ uint32_t length;
+} p8_pore_ringInfoStruct;
+
+
+/**
+ * Generate a set of PORE instructions that will initialize a scan ring.
+ *
+ * @param i_ringAddr host Address of scan ring
+ * @param i_ringBitLen host Number of bits in the scan ring
+ * @param i_ring host Pointer to initialized ring data, left-aligned binary
+ * @param i_flush host Pointer to ring data for flush state, left-aligned binary
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE image in 32-bit words
+ * @param o_streamLenInWords host Actual size of PORE image in 32-bit words
+ * @param o_streamOutput BigEndian Pointer to allocated local memory to write PORE image into, this is
+ * the location to write the ring data into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_gen_scan( uint32_t i_ringAddr,
+ uint32_t i_ringBitLen,
+ uint32_t* i_ring,
+ uint32_t* i_flush,
+ uint32_t i_maxStreamLenInWords,
+ uint32_t* o_streamLenInWords,
+ uint32_t* o_streamOutput );
+
+/**
+ * Generate or update a set of PORE instructions that will initialize a scom register.
+ *
+ * @param i_scomAddr host Address of scom register
+ * @param i_scomData host Two 32-bit words of scom register data
+ * @param i_operation host Should data be appended or existing data updated
+ * P8_PORE_SCOM_APPEND : add scom instructions to the end of the existing image
+ * P8_PORE_SCOM_OR : overlay scom data onto existing instruction by bitwise OR
+ * P8_PORE_SCOM_AND : overlay scom data onto existing instruction by bitwise AND
+ * P8_PORE_SCOM_REPLACE : replace existing instructions with new data
+ * P8_PORE_SCOM_NOOP : replace existing instructions with NOOP, i_scomData is junk
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE image in 32-bit words
+ * @param o_streamOutput BigEndian Pointer to allocated local memory to write PORE image into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_BAD_ARG_RC : some input argument is nonsensical
+ * P8_PORE_ADDR_NOT_FOUND : could not find existing scom for overlay (AND/OR) operation
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_gen_scom( uint32_t i_scomAddr,
+ uint32_t i_scomData[2],
+ uint32_t i_operation,
+ uint32_t i_maxStreamLenInWords,
+ uint32_t* o_streamOutput );
+
+/**
+ * Generate or update a set of PORE instructions that will initialize an
+ * architected register in the processor, ie. SPR or GPR. It is assumed that
+ * all updates will replace any existing data for that register. If the data
+ * does not already exist then it will be appended.
+ *
+ * @param i_regName host Constant that determines which SPR to write (see p8_pore_const.h)
+ * @param i_regData host Two 32-bit words of register data
+ * @param i_coreIndex host Core to operate on
+ * @param i_threadIndex host Thread to operate on, used for HSPRG0 and LPCR
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE image in 32-bit words
+ * @param o_streamOutput BigEndian Pointer to allocated local memory to write PORE image into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_gen_cpureg( uint32_t i_regName,
+ uint32_t i_regData[2],
+ uint32_t i_coreIndex,
+ uint32_t i_threadIndex,
+ uint32_t i_maxStreamLenInWords,
+ uint32_t* o_streamOutput );
+
+/**
+ * Generate a set of PORE instructions that will perform a branch operation
+ * to a relative address offset
+ *
+ * @param i_offset host Relative offset to branch to
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE instruction(s) in 32-bit words
+ * @param i_branchType host Set to 0 for relative branch (BRA), set to 1 for branch to subroutine (BSR)
+ * @param o_streamLenInWords host Actual size of PORE instruction(s) in 32-bit words
+ * @param o_streamOutput BigEndian Pointer to allocated local memory to write PORE image into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_gen_relbranch( uint32_t i_offset,
+ uint32_t i_maxStreamLenInWords,
+ uint32_t i_branchType,
+ uint32_t* o_streamLenInWords,
+ uint32_t* o_streamOutput );
+
+/**
+ * Generate a set of PORE instructions that will perform a branch operation
+ * to an absolute address.
+ *
+ * @param i_address host Absolute address to branch to
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE instruction(s) in 32-bit words
+ * @param o_streamLenInWords host Actual size of PORE instruction(s) in 32-bit words
+ * @param o_streamOutput host Pointer to allocated local memory to write PORE image into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_gen_absbranch( uint32_t i_address,
+ uint32_t i_maxStreamLenInWords,
+ uint32_t* o_streamLenInWords,
+ uint32_t* o_streamOutput );
+
+/**
+ * Generate a set of PORE instructions that are invalid and will cause an
+ * error. It is used to populate a region of memory that the PORE shouldn't
+ * execute.
+ *
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE instruction(s) in 32-bit words
+ * @param o_streamOutput BigEndian Pointer to allocated local memory to write PORE image into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_fill_invalid( uint32_t i_maxStreamLenInWords,
+ uint32_t* o_streamOutput );
+
+/**
+ * Generate a set of PORE instructions that are return statements. It is used
+ * to populate a region of memory that the PORE should return from.
+ *
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE instruction(s) in 32-bit words
+ * @param o_streamOutput BigEndian Pointer to allocated local memory to write PORE image into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_fill_return( uint32_t i_maxStreamLenInWords,
+ uint32_t* o_streamOutput );
+
+/**
+ * Generate a WAIT PORE instruction.
+ *
+ * @param i_wait host Number of pcb_nclk cycles to wait
+ * @param i_maxStreamLenInWords host Max space available for resulting PORE instruction(s) in 32-bit words
+ * @param o_streamLenInWords host Actual size of PORE instruction(s) in 32-bit words
+ * @param o_streamOutput BigEndian Pointer to allocated local memory to write PORE image into
+ *
+ * @return uint32_t Error return codes
+ * P8_PORE_SUCCESS_RC : No errors
+ * P8_PORE_IMAGE_TOO_BIG_RC : size of PORE image exceeded allowed space
+ * P8_PORE_XXX_RC : other errors...
+ */
+uint32_t p8_pore_gen_wait( uint32_t i_wait,
+ uint32_t i_maxStreamLenInWords,
+ uint32_t* o_streamLenInWords,
+ uint32_t* o_streamOutput );
+
+
+#endif /* _P8_PORE_H */
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they can be included here.
+
+$Log: p8_pore_api.h,v $
+Revision 1.2 2012/04/11 16:58:29 cmolsen
+Removed #define of __PORE_INLINE_ASSEMBLER_C__
+
+Revision 1.1 2011/08/25 12:28:04 yjkim
+initial checkin
+
+Revision 1.8 2010/08/31 14:47:15 schwartz
+Changed comments about scom operations to include SCOM in the name
+
+Revision 1.7 2010/08/30 23:27:16 schwartz
+Added TRACE statements to include specified number of arguments
+Defined branch type constants
+Added constant for last scom op used to check if operation input to gen_scan is valid
+Added mult spr error constant
+Added p7p_pore_gen_wait API
+Changed additional C++ style comments to C style
+Initialized all variables to 0
+Removed FTRACE statements
+Added additional information to trace statements
+Updated gen_scom to use the defined operation constants
+Updated branch gen_relbranch to use defined branch type constants
+Added rc check for calls to p7p_pore_gen_cpureg_status and p7p_pore_span_128byte_boundary subroutines
+
+Revision 1.6 2010/08/26 03:57:02 schwartz
+Changed comments to C-style
+Changed "" to <> for #includes
+Moved RINGINFO struct and RINGINDEX constant into separate object file, includes created static_data.h file
+Put p7p_pore in front of #defines
+Removed ring length from ringInfoStruct
+Renamed scom operators to have SCOM in the name
+Fixed gen_scan to use SCANRD and SCANWR pore instructions
+Fixed compiler warnings
+
+Revision 1.5 2010/07/01 21:42:11 schwartz
+Included format (host or big endian) in parameter definitions
+
+Revision 1.4 2010/06/23 23:09:05 schwartz
+Updated ordering of include statements so p7p_pore_api_custom.h is first
+Updated definition of gen_cpureg to include coreIndex and threadIndex
+
+Revision 1.3 2010/05/24 02:32:07 schwartz
+Fixed errors that appear when using -Werrors flag
+Added in cvs logging (hopefully)
+
+
+*/
+
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h
new file mode 100644
index 000000000..43a2a3e5c
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h
@@ -0,0 +1,127 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_const.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/* $Id: p8_pore_api_const.h,v 1.1 2011/08/25 12:32:33 yjkim Exp $ */
+/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_pore_api_const.h,v $ */
+
+/**
+ * Contains any constants uses as inputs or outputs to the p7p_pore functions
+ */
+
+
+/****************************/
+/***** SCOM Operators *****/
+/****************************/
+#define P8_PORE_SCOM_APPEND 0 /* add scom instructions to the end of the existing image */
+#define P8_PORE_SCOM_REPLACE 1 /* replace existing instructions with new data */
+#define P8_PORE_SCOM_OR 2 /* overlay scom data onto existing instruction by bitwise OR */
+#define P8_PORE_SCOM_AND 3 /* overlay scom data onto existing instruction by bitwise AND */
+#define P8_PORE_SCOM_NOOP 4 /* replace existing instructions with NOP */
+#define P8_PORE_SCOM_LAST_OP 4 /* keep track of the last op for checking correctness of op input */
+
+
+/***************************/
+/***** CPU Registers *****/
+/***************************/
+#define P8_PORE_HSPRG0 304
+#define P8_PORE_HRMOR 313
+#define P8_PORE_LPCR 318
+#define P8_PORE_HMEER 337
+#define P8_PORE_HID0 1008
+#define P8_PORE_HID1 1009
+#define P8_PORE_HID4 1012
+#define P8_PORE_HID5 1014
+#define P8_PORE_MSR 2000
+
+
+/****************************/
+/***** Branch Types *****/
+/****************************/
+#define P8_PORE_BRA_REL 0 /* generate relative branch instruction */
+#define P8_PORE_BRA_SUB 1 /* generate branch to subroutine instruction */
+
+
+/**************************/
+/***** Return Codes *****/
+/**************************/
+#define P8_PORE_SUCCESS_RC 0x00000000 /* Success, no errors */
+#define P8_PORE_IMAGE_TOO_BIG_RC 0x00000001 /* size of PORE image exceeded allowed space */
+#define P8_PORE_BAD_ARG_RC 0x00000002 /* some input argument is nonsensical */
+#define P8_PORE_NO_ADDR_FOUND_RC 0x00000003 /* address to overlay not found */
+#define P8_PORE_MULT_ADDR_FOUND_RC 0x00000004 /* address to replace/overlay found multiple times */
+#define P8_PORE_MULT_SPR_FOUND_RC 0x00000005 /* spr to add/replace found multiple times*/
+#define P8_PORE_BAD_RING_ADDR_RC 0x00000006 /* don't recognize the ring addr*/
+
+
+/* may need to include errors for 128byte_bound check and cpureg_status check */
+/*...etc...*/
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they can be included here.
+
+$Log: p8_pore_api_const.h,v $
+Revision 1.1 2011/08/25 12:32:33 yjkim
+initial checkin
+
+Revision 1.7 2010/11/03 19:13:16 schwartz
+Added code to gen_cpureg to handle changes to MSR
+
+Revision 1.6 2010/08/30 23:27:16 schwartz
+Added TRACE statements to include specified number of arguments
+Defined branch type constants
+Added constant for last scom op used to check if operation input to gen_scan is valid
+Added mult spr error constant
+Added p7p_pore_gen_wait API
+Changed additional C++ style comments to C style
+Initialized all variables to 0
+Removed FTRACE statements
+Added additional information to trace statements
+Updated gen_scom to use the defined operation constants
+Updated branch gen_relbranch to use defined branch type constants
+Added rc check for calls to p7p_pore_gen_cpureg_status and p7p_pore_span_128byte_boundary subroutines
+
+Revision 1.5 2010/08/26 15:13:34 schwartz
+Fixed more C++ style comments to C style comments
+
+Revision 1.4 2010/08/26 03:57:02 schwartz
+Changed comments to C-style
+Changed "" to <> for #includes
+Moved RINGINFO struct and RINGINDEX constant into separate object file, includes created static_data.h file
+Put p7p_pore in front of #defines
+Removed ring length from ringInfoStruct
+Renamed scom operators to have SCOM in the name
+Fixed gen_scan to use SCANRD and SCANWR pore instructions
+Fixed compiler warnings
+
+Revision 1.3 2010/06/23 23:07:40 schwartz
+Updated define statements for SPRs, constant values are actual SPR values from Book IV
+
+Revision 1.2 2010/05/24 02:33:14 schwartz
+Fixed errors that appear when using -Werrors flag
+Added in cvs logging (hopefully)
+
+
+*/
+
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_custom.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_custom.h
new file mode 100644
index 000000000..a35fb1006
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_custom.h
@@ -0,0 +1,142 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_api_custom.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/* $Id: p8_pore_api_custom.h,v 1.5 2012/05/22 21:25:21 cmolsen Exp $ */
+/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_pore_api_custom.h,v $ */
+
+#include <stdint.h> /* for uint32_t */
+#include <stdio.h> /* for printf */
+#ifndef __HOSTBOOT_MODULE
+#include <netinet/in.h> /* for htonl */
+#endif
+
+/**
+ * This file should be modified by users to appropriately handle some
+ * environment-specific operations.
+ */
+
+
+/*********************************/
+/***** Logging and Tracing *****/
+/*********************************/
+/**
+ * All tracing functions assume printf-style formatting
+ */
+
+#ifndef __FAPI
+/* Trace an informational message */
+#define P8_PORE_ITRACE0(msg) printf("PORE> INFO: " msg "\n");
+#define P8_PORE_ITRACE1(msg, arg0) printf("PORE> INFO: " msg "\n", arg0);
+
+/* Trace an error message */
+#define P8_PORE_ETRACE0(msg) printf("PORE> ERROR: " msg "\n");
+#define P8_PORE_ETRACE1(msg, arg0) printf("PORE> ERROR: " msg "\n", arg0);
+#define P8_PORE_ETRACE2(msg, arg0, arg1) printf("PORE> ERROR: " msg "\n", arg0, arg1);
+#define P8_PORE_ETRACE3(msg, arg0, arg1, arg2) printf("PORE> ERROR: " msg "\n", arg0, arg1, arg2);
+#define P8_PORE_ETRACE4(msg, arg0, arg1, arg2, arg3) printf("PORE> ERROR: " msg "\n", arg0, arg1, arg2, arg3);
+#define P8_PORE_ETRACE5(msg, arg0, arg1, arg2, arg3, arg4) printf("PORE> ERROR: " msg "\n", arg0, arg1, arg2, arg3, arg4);
+#endif
+/* Used for debug, Cronus/FW should leave these empty */
+#define P8_PORE_DTRACE0(msg)
+#define P8_PORE_DTRACE1(msg, arg0)
+#define P8_PORE_DTRACE2(msg, arg0, arg1)
+#define P8_PORE_DTRACE3(msg, arg0, arg1, arg2)
+#define P8_PORE_DTRACE4(msg, arg0, arg1, arg2, arg3)
+
+/****** Following is only used for debug purposes ******/
+/* FW/Cronus should NOT include this section */
+/* DTRACE - Print debug statements to command line */
+/* FTRACE - Print text PORE instructions of cpureg setup to DEBUG_FILE */
+/*
+#define P8_PORE_DTRACE0(msg) printf("PORE> DEBUG: " msg "\n");
+#define P8_PORE_DTRACE1(msg, arg0) printf("PORE> DEBUG: " msg "\n", arg0);
+#define P8_PORE_DTRACE2(msg, arg0, arg1) printf("PORE> DEBUG: " msg "\n", arg0, arg1);
+#define P8_PORE_DTRACE3(msg, arg0, arg1, arg2) printf("PORE> DEBUG: " msg "\n", arg0, arg1, arg2);
+#define P8_PORE_DTRACE4(msg, arg0, arg1, arg2, arg3) printf("PORE> DEBUG: " msg "\n", arg0, arg1, arg2, arg3);
+*/
+
+/**********************************/
+/***** Endian-ness Handling *****/
+/**********************************/
+/**
+ * Handle byte-swapping if necessary
+ */
+
+/* Default to big-endian format on both sides */
+#define P8_PORE_HOST_TO_BIG32( bit32_int ) htonl(bit32_int)
+#define P8_PORE_BIG32_TO_HOST( bit32_int ) ntohl(bit32_int)
+#define P8_PORE_HOST_TO_BIG16( bit16_int ) htonl(bit16_int)
+#define P8_PORE_BIG16_TO_HOST( bit16_int ) ntohl(bit16_int)
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they can be included here.
+
+$Log: p8_pore_api_custom.h,v $
+Revision 1.5 2012/05/22 21:25:21 cmolsen
+Updated to remove FAPI tracing, which is not allowed in plain C files.
+
+Revision 1.4 2012/05/21 14:45:41 cmolsen
+Updated to address Gerrit review II comments about printf() usage.
+
+Revision 1.3 2012/05/15 19:53:38 cmolsen
+Updated to address Gerrit review comments:
+- Hostboot doesn't support printf().
+
+Revision 1.2 2012/04/13 16:45:32 cmolsen
+Includes __HOSTBOOT_MODULE exclude of <netinit/in.h>
+
+Revision 1.1 2011/08/25 12:28:38 yjkim
+initial check in
+
+Revision 1.10 2010/08/30 23:27:17 schwartz
+Added TRACE statements to include specified number of arguments
+Defined branch type constants
+Added constant for last scom op used to check if operation input to gen_scan is valid
+Added mult spr error constant
+Added p7p_pore_gen_wait API
+Changed additional C++ style comments to C style
+Initialized all variables to 0
+Removed FTRACE statements
+Added additional information to trace statements
+Updated gen_scom to use the defined operation constants
+Updated branch gen_relbranch to use defined branch type constants
+Added rc check for calls to p7p_pore_gen_cpureg_status and p7p_pore_span_128byte_boundary subroutines
+
+Revision 1.9 2010/08/30 14:57:54 schwartz
+Removed FTRACE and associated #define statements
+Changed TRACE macros to multiple macros with specified number of args
+
+Revision 1.6 2010/08/26 15:13:34 schwartz
+Fixed more C++ style comments to C style comments
+
+Revision 1.5 2010/06/23 23:06:37 schwartz
+Defined additional trace functions to be used for debugging, not in FW or Cronus
+
+Revision 1.4 2010/05/24 02:34:07 schwartz
+Fixed errors that appear when using -Werrors flag
+Added in cvs logging (hopefully)
+
+
+*/
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.c b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.c
new file mode 100644
index 000000000..e1a8387c0
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.c
@@ -0,0 +1,118 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.c $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/* $Id: p8_pore_static_data.c,v 1.1 2011/08/25 12:32:01 yjkim Exp $ */
+/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_pore_static_data.c,v $ */
+/*------------------------------------------------------------------------------*/
+/* *! (C) Copyright International Business Machines Corp. 2010 */
+/* *! All Rights Reserved -- Property of IBM */
+/* *! *** IBM Confidential *** */
+/*------------------------------------------------------------------------------*/
+/* *! TITLE p7p_pore_static_data */
+/* *! DESCRIPTION : Static data for PORE APIs */
+/* *! OWNER NAME : Nicole Schwartz Email: nschwart@us.ibm.com */
+/* *! BACKUP NAME : */
+/* *! ADDITIONAL COMMENTS : */
+
+/*------------------------------------------------------------------------------*/
+/* Don't forget to create CVS comments when you check in your changes! */
+/*------------------------------------------------------------------------------*/
+/* HvPlic include needed for PHYP, must be first include */
+/*#include "HvPlicModule.H"*/
+#include "p8_pore_api_custom.h"
+#include "p8_pore_api.h"
+#include "p8_pore_static_data.h"
+
+/* Note: this info is a place holder until we get all other rings */
+const p8_pore_ringInfoStruct P8_PORE_RINGINFO[] = {
+ /*ring name ring local address scan region/type*/
+ { "REPR_RING_C0", 0x00034A08, 0x48000080 },
+ { "REPR_RING_C1", 0x00034A02, 0x48002000 },
+ { "REPR_RING_C2", 0x00034A01, 0x48004000 },
+ { "REPR_RING_C3", 0x00034A04, 0x48000800 },
+ { "REPR_RING_C4", 0x00034A07, 0x48000100 },
+ { "REPR_RING_C5", 0x00034A05, 0x48000400 },
+ { "REPR_RING_C6", 0x00034A07, 0x48000100 },
+ { "REPR_RING_C7", 0x00034A05, 0x48000400 },
+ /* P7P data
+ { "EX_ECO_BNDY", 0x00034A08, 0x48000080 },
+ { "EX_ECO_GPTR", 0x00034A02, 0x48002000 },
+ { "EX_ECO_MODE", 0x00034A01, 0x48004000 },
+ { "EX_ECO_LBST", 0x00034A04, 0x48000800 },
+ { "EX_ECO_TIME", 0x00034A07, 0x4800010000000000 },
+ { "EX_ECO_ABST", 0x00034A05, 0x4800040000000000 },
+ { "EX_ECO_REGF", 0x00034A03, 0x4800100000000000 },
+ { "EX_ECO_REPR", 0x00034A06, 0x4800020000000000 },
+ { "EX_ECO_FUNC", 0x00034800, 0x4800800000000000 },
+ { "EX_ECO_L3REFR", 0x00030200, 0x0200800000000000 },
+ { "EX_ECO_DPLL_FUNC", 0x00030400, 0x0400800000000000 },
+ { "EX_ECO_DPLL_GPTR", 0x00030402, 0x0400200000000000 },
+ { "EX_ECO_DPLL_MODE", 0x00030401, 0x0400400000000000 },
+ { "EX_CORE_BNDY", 0x00033008, 0x3000008000000000 },
+ { "EX_CORE_GPTR", 0x00033002, 0x3000200000000000 },
+ { "EX_CORE_MODE", 0x00033001, 0x3000400000000000 },
+ { "EX_CORE_LBST", 0x00033004, 0x3000080000000000 },
+ { "EX_CORE_TIME", 0x00033007, 0x3000010000000000 },
+ { "EX_CORE_ABST", 0x00033005, 0x3000040000000000 },
+ { "EX_CORE_REGF", 0x00032003, 0x2000100000000000 },
+ { "EX_CORE_REPR", 0x00033006, 0x3000020000000000 },
+ { "EX_CORE_FUNC", 0x00032000, 0x2000800000000000 },
+ { "EX_CORE_L2FARY", 0x00031009, 0x1000900000000000 },
+ */
+};
+
+const int P8_PORE_RINGINDEX=sizeof P8_PORE_RINGINFO/sizeof P8_PORE_RINGINFO[0];
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they can be included here.
+
+$Log: p8_pore_static_data.c,v $
+Revision 1.1 2011/08/25 12:32:01 yjkim
+initial checkin
+
+Revision 1.5 2010/10/19 22:34:41 schwartz
+added #include <p7p_pore_static_data.h>
+
+Revision 1.4 2010/08/26 15:13:33 schwartz
+Fixed more C++ style comments to C style comments
+
+Revision 1.3 2010/08/26 03:57:02 schwartz
+Changed comments to C-style
+Changed "" to <> for #includes
+Moved RINGINFO struct and RINGINDEX constant into separate object file, includes created static_data.h file
+Put p7p_pore in front of #defines
+Removed ring length from ringInfoStruct
+Renamed scom operators to have SCOM in the name
+Fixed gen_scan to use SCANRD and SCANWR pore instructions
+Fixed compiler warnings
+
+Revision 1.2 2010/07/09 15:38:35 schwartz
+Changed ring names to uppercase and updated length of rings. Neither of these pieces of data are used in the gen_scan API, but is used when generating rings for verification
+
+Revision 1.1 2010/06/23 23:10:06 schwartz
+Moved constants ringInfoStruct and RINGINDEX into this file
+
+
+*/
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.h
new file mode 100644
index 000000000..dd18808b4
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.h
@@ -0,0 +1,72 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_static_data.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/* $Id: p8_pore_static_data.h,v 1.1 2011/08/25 12:31:51 yjkim Exp $ */
+/* $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_pore_static_data.h,v $ */
+/*------------------------------------------------------------------------------*/
+/* *! (C) Copyright International Business Machines Corp. 2010 */
+/* *! All Rights Reserved -- Property of IBM */
+/* *! *** IBM Confidential *** */
+/*------------------------------------------------------------------------------*/
+/* *! TITLE p8_pore_static_data */
+/* *! DESCRIPTION : Static data for PORE APIs */
+/* *! OWNER NAME : Nicole Schwartz Email: nschwart@us.ibm.com */
+/* *! BACKUP NAME : */
+/* *! ADDITIONAL COMMENTS : */
+/* */
+/*------------------------------------------------------------------------------*/
+/* Don't forget to create CVS comments when you check in your changes! */
+/*------------------------------------------------------------------------------*/
+
+#ifndef _P8_PORE_STATIC_DATA_H
+#define _P8_PORE_STATIC_DATA_H
+
+extern const p8_pore_ringInfoStruct P8_PORE_RINGINFO[];
+extern const int P8_PORE_RINGINDEX;
+
+#endif /* _P8_PORE_STATIC_DATA_H */
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they can be included here.
+
+$Log: p8_pore_static_data.h,v $
+Revision 1.1 2011/08/25 12:31:51 yjkim
+initial check-in
+
+Revision 1.2 2010/08/26 15:13:34 schwartz
+Fixed more C++ style comments to C style comments
+
+Revision 1.1 2010/08/26 03:57:02 schwartz
+Changed comments to C-style
+Changed "" to <> for #includes
+Moved RINGINFO struct and RINGINDEX constant into separate object file, includes created static_data.h file
+Put p7p_pore in front of #defines
+Removed ring length from ringInfoStruct
+Renamed scom operators to have SCOM in the name
+Fixed gen_scan to use SCANRD and SCANWR pore instructions
+Fixed compiler warnings
+
+
+*/
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H
new file mode 100644
index 000000000..a99cbc99e
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H
@@ -0,0 +1,168 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_pore_table_gen_api.H $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/*------------------------------------------------------------------------------*/
+/* *! (C) Copyright International Business Machines Corp. 2012 */
+/* *! All Rights Reserved -- Property of IBM */
+/* *! *** IBM Confidential *** */
+/*------------------------------------------------------------------------------*/
+/* *! TITLE : p8_pore_table_gen_api */
+/* *! DESCRIPTION : Contains all external APIs used by firmware (PHYP) to */
+// generate/modify the P8 PORE SLW image.
+/* *! OWNER NAME : Michael Olsen Email: cmolsen@us.ibm.com */
+/* *! ADDITIONAL COMMENTS : */
+// - Start file: p7p_pore_api.h
+// - _table_entry structs must agree with Greg's proc_slw_ram.H
+//
+/*------------------------------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "pore_bitmanip.H"
+#include "sbe_xip_image.h"
+
+//#ifndef _P8_PORE_API_H
+//#define _P8_PORE_API_H
+
+//#include <p8_pore_api_custom.h>
+//#include <p8_pore_image.h>
+//#include <p8_pore_api_const.h>
+
+/* Common header for *.c and .S ramming code: Call it ../sbe/proc_slw_ram.H ? */
+// Header defs (P8&PORE 64-bit notation where bits are numbered from left-to-right)
+#define RAM_HEADER_END_START 0
+#define RAM_HEADER_END_MASK BITS(RAM_HEADER_END_START,1)
+#define RAM_HEADER_TYPE_START 2
+#define RAM_HEADER_TYPE_MASK BITS(RAM_HEADER_TYPE_START,2)
+#define RAM_HEADER_SPRN_START 4
+#define RAM_HEADER_SPRN_MASK BITS(RAM_HEADER_SPRN_START,10)
+#define RAM_HEADER_THREAD_START 16
+#define RAM_HEADER_THREAD_MASK BITS(RAM_HEADER_THREAD_START,3)
+// MTSPR instr defs
+#define RAM_MTSPR_INSTR_TEMPL ( ( (uint64_t)31<<(63-5) | (uint64_t)467<<(63-30) ) )
+#define RAM_MTSPR_SPR_START 11
+#define RAM_MTSPR_SPR_MASK BITS(RAM_MTSPR_SPR_START,10)
+// Header defs (C notation where bits are numbered from right-to-left, and reducing to 32-bit)
+#define RAM_HEADER_END_START_C ( 31-RAM_HEADER_END_START+1-1 )
+#define RAM_HEADER_END_MASK_C (uint32_t)(RAM_HEADER_END_MASK>>32)
+#define RAM_HEADER_TYPE_START_C ( 31-RAM_HEADER_TYPE_START+1-2 )
+#define RAM_HEADER_TYPE_MASK_C (uint32_t)(RAM_HEADER_TYPE_MASK>>32)
+#define RAM_HEADER_SPRN_START_C ( 31-RAM_HEADER_SPRN_START+1-10 )
+#define RAM_HEADER_SPRN_MASK_C (uint32_t)(RAM_HEADER_SPRN_MASK>>32)
+#define RAM_HEADER_THREAD_START_C ( 31-RAM_HEADER_THREAD_START+1-3 )
+#define RAM_HEADER_THREAD_MASK_C (uint32_t)(RAM_HEADER_THREAD_MASK>>32)
+// MTSPR instr defs
+#define RAM_MTSPR_INSTR_TEMPL_C ( ( (uint32_t)31<<(31-5) | (uint32_t)467<<(31-30) ) )
+#define RAM_MTSPR_SPR_START_C ( 31-RAM_MTSPR_SPR_START+1-10 )
+//#define RAM_MTSPR_SPR_MASK_C (uint32_t)(BITS(RAM_MTSPR_SPR_START,10)>>32)
+#define RAM_MTSPR_SPR_MASK_C (uint32_t)(RAM_MTSPR_SPR_MASK>>32)
+
+/* Other defs needed for ramming */
+// TOC names
+#define SLW_HOST_REG_VECTOR_TOC_NAME "slw_host_reg_vector"
+#define SLW_HOST_SCOM_VECTOR_TOC_NAME "slw_host_scom_vector"
+#define SLW_HOST_REG_TABLE_TOC_NAME "slw_core_reg_table"
+
+// Defines for slw_build() to update "host_runtime_scome" w/pointer to "slw_host_runtime" at SLW image build time.
+#define HOST_RUNTIME_SCOM_TOC_NAME "host_runtime_scom" // Null 1st, then fill w/addr of SLW_HOST_RUNTIME_TOC_NAME
+#define SLW_HOST_RUNTIME_TOC_NAME "slw_host_runtime"
+
+
+// RAM table defines
+#define XIPSIZE_RAM_ENTRY ( (sizeof(RamTableEntry)+7)/8*8 )
+#define SLW_MAX_CORES 16
+#define SLW_MAX_CPUREGS_CORE 8
+#define SLW_MAX_CPUREGS_THREADS 3
+#define SLW_CORE_THREADS 8
+#define SLW_MAX_CPUREGS_OPS ( SLW_MAX_CPUREGS_CORE + \
+ SLW_CORE_THREADS*SLW_MAX_CPUREGS_THREADS )
+#define SLW_SLW_SECTION_SIZE ( SLW_MAX_CORES * SLW_MAX_CPUREGS_OPS * XIPSIZE_RAM_ENTRY )
+
+// Return codes
+#define SLW_RAM_SUCCESS 0
+#define SLW_RAM_HEADERS_NOT_SYNCED 1
+#define SLW_RAM_IMAGE_SIZE_MISMATCH 2
+#define SLW_RAM_TABLE_ENTRY_OVERFLOW 3
+#define SLW_RAM_CODE_ERROR 4
+#define SLW_RAM_INVALID_PARAMETER 5
+#define SLW_RAM_WARNING_TABLE_CONTAMINATION 10
+
+#ifdef __cpluscplus
+extern "C" {
+#endif
+
+typedef struct ram_instr_t {
+ uint32_t header;
+ uint32_t instr;
+ uint64_t data;
+} RamTableEntry;
+
+// SLW supported SPR registers
+typedef struct {
+ const char *name;
+ uint32_t value;
+ uint32_t swizzled;
+} SlwSprRegs;
+
+const SlwSprRegs SLW_SPR_REGS[] = {
+ /* name value swizzled */
+ // ...core regs
+ { "P8_SPR_HRMOR", 313, ( 313>>5 | ( 313&0x1f)<<5 ) },
+ { "P8_SPR_HMEER", 337, ( 337>>5 | ( 337&0x1f)<<5 ) },
+ { "P8_SPR_PMICR", 852, ( 852>>5 | ( 852&0x1f)<<5 ) },
+ { "P8_SPR_PMCR", 884, ( 884>>5 | ( 884&0x1f)<<5 ) },
+ { "P8_SPR_HID0", 1008, ( 1008>>5 | (1008&0x1f)<<5 ) },
+ { "P8_SPR_HID1", 1009, ( 1009>>5 | (1009&0x1f)<<5 ) },
+ { "P8_SPR_HID4", 1012, ( 1012>>5 | (1012&0x1f)<<5 ) },
+ { "P8_SPR_HID5", 1014, ( 1014>>5 | (1014&0x1f)<<5 ) },
+ // ...thread regs
+ { "P8_SPR_HSPRG0", 304, ( 304>>5 | ( 304&0x1f)<<5 ) },
+ { "P8_SPR_LPCR", 318, ( 318>>5 | ( 318&0x1f)<<5 ) },
+ // Greg, this is NOT in jbishop's SS. Got it from ur ST. But 1023 is max!
+ { "P8_SPR_MSR", 2000, ( 2000>>5 | (2000&0x1f)<<5 ) }
+};
+
+const int SLW_SPR_REGS_SIZE = sizeof(SLW_SPR_REGS)/sizeof(SLW_SPR_REGS[0]);
+
+
+/* Name: p8_pore_gen_cpureg()
+ * Description: Populates ramming entries in the .slw section
+ * Parameter list: i_image - pointer to SLW mainstore image
+ * i_sizeImage - size of SLW mainstore image
+ * i_regName - unswizzled SPR register value
+ * i_regData - data to write to SPR register
+ * i_coreId - the core ID to operate on
+ * i_threadId - the thread ID to operate on
+ */
+uint32_t p8_pore_gen_cpureg(void *i_image,
+ uint32_t i_sizeImage,
+ uint32_t i_regName,
+ uint64_t i_regData,
+ uint32_t i_coreId,
+ uint32_t i_threadId);
+
+#ifdef __cpluscplus
+}
+#endif
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.C b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.C
new file mode 100644
index 000000000..1cf8f8f46
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.C
@@ -0,0 +1,600 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.C $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+// $Id: p8_scan_compression.C,v 1.3 2012/05/22 15:57:28 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_scan_compression.C,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! OWNER NAME: Bishop Brock Email: Bishop Brock; bcbrock@us.ibm.com
+// *!
+// *! General Description:
+// *!
+// *! See below.
+//------------------------------------------------------------------------------
+//
+// Note: This file was originally named p8_scan_compression.c; See CVS archive
+// for revision history of p8_scan_compression.c.
+
+/// \file p8_scan_compression.C
+/// \brief APIs related to scan chain compression.
+///
+/// RS4 Compression Format
+/// ======================
+///
+/// Scan strings are compressed using a simple run-length encoding called
+/// RS4. The string to be decompressed and scanned is the difference between
+/// the current state of the ring and the desired final state of the ring. A
+/// run-time optimization supports the case that the current state of the ring
+/// is the flush state.
+///
+/// Both the data to be compressed and the final compressed data are treated
+/// as strings of 4-bit nibbles. When packaged in the scan data structure
+/// however the compressed string must begin on an 8-byte boundary and is
+/// always read 8 bytes at a time. In the scan data structure the compressed
+/// strings are also padded with 0x0 nibbles to the next even multiple of 8
+/// bytes. The compressed string consists of control nibbles and data nibbles.
+/// The string format includes a special control/data sequence that marks the
+/// end of the string and the final bits of scan data.
+///
+/// Runs of 0x0 nibbles (rotates) are encoded using a simple variable-length
+/// integer encoding known as a "stop code". This code treats each nibble in
+/// a variable-length integer encoding as an octal digit (the low-order 3
+/// bits) plus a stop bit (the high-order bit). The examples below
+/// illustrate the encoding.
+///
+/// 1xxx - Rotate 0bxxx nibbles (0 - 7)
+/// 0xxx 1yyy - Rotate 0bxxxyyy nibbles (8 - 63)
+/// 0xxx 0yyy 1zzz - Rotate 0bxxxyyyzzz nibbles (64 - 511)
+/// etc.
+///
+/// A 0-length rotate (code 0b1000) is needed to resynchronize the state
+/// machine in the event of long scans (see below), or a string that begins
+/// with a non-0x0 nibble.
+///
+/// Runs of non-0x0 nibbles (scans) are inserted verbatim into the compressed
+/// string after a control nibble indicating the number of nibbles of
+/// uncompressed data. If a run is longer than 15 nibbles, the compression
+/// algorithm must insert a 0-length rotate and a new scan-length control
+/// before continuing with the non-0 data nibbles.
+///
+/// xxxx - Scan 0bxxxx nibbles which follow, 0bxxxx != 0
+///
+/// The special case of a 0b0000 code where a scan count is expected marks the
+/// end of the string. The end of string marker is always followed by a
+/// nibble that contains the terminal bit count in the range 0-3. If the
+/// length of the original binary string was not an even multiple of 4, then a
+/// final nibble contains the final scan data left justified.
+///
+/// 0000 00nn [ttt0] - Terminate 0bnn bits, data 0bttt0 if 0bnn != 0
+///
+///
+/// BNF Grammar
+/// ===========
+///
+/// Following is a BNF grammar for the strings accepted by the RS4
+/// decompression and scan algorithm. At a high level, the state machine
+/// recognizes a series of 1 or more sequences of a rotate (R) followed by a
+/// scan (S) or end-of-string marker (E), followed by the terminal count (T)
+/// and optional terminal data (D).
+///
+/// (R S)* (R E) T D?
+///
+/// \code
+///
+/// <rs4_string> ::= <rotate> <terminate> |
+/// <rotate> <scan> <rs4_string>
+///
+/// <rotate> ::= <octal_stop> |
+/// <octal_go> <rotate>
+///
+/// <octal_go> ::= '0x0' | ... | '0x7'
+///
+/// <octal_stop> ::= '0x8' | ... | '0xf'
+///
+/// <scan> ::= <scan_count(N)> <data(N)>
+///
+/// <scan_count(N)> ::= * 0bnnnn, for N = 0bnnnn, N != 0 *
+///
+/// <data(N)> ::= * N nibbles of uncompressed data *
+///
+/// <terminate> ::= '0x0' <terminal_count(0)> |
+/// '0x0' <terminal_count(T, T > 0)> <terminal_data(T)>
+///
+/// <terminal_count(T)> ::= * 0b00nn, for T = 0bnn *
+///
+/// <terminal_data(1)> ::= '0x0' | '0x8'
+///
+/// <terminal_data(2)> ::= '0x0' | '0x4' | '0x8' | '0xc'
+///
+/// <terminal_data(3)> ::= '0x0' | '0x2' | '0x4' | ... | '0xe'
+///
+/// \endcode
+
+
+#include <stdlib.h>
+#include "p8_scan_compression.H"
+
+// Diagnostic aids for debugging
+#ifdef DEBUG_P8_SCAN_COMPRESSION
+
+#ifdef __FAPI
+
+#include "fapi.H"
+#define fprintf(stream, ...) FAPI_ERR(__VA_ARGS__)
+#define BUG_NEWLINE ""
+
+#else // __FAPI
+
+#include <stdio.h>
+#define BUG_NEWLINE "\n"
+
+#endif // __FAPI
+
+#define BUG(rc) \
+ ({ \
+ fprintf(stderr,"%s:%d : Trapped rc = %d" BUG_NEWLINE, \
+ __FILE__, __LINE__, (rc)); \
+ (rc); \
+ })
+
+#define BUGX(rc, ...) \
+ ({ \
+ BUG(rc); \
+ fprintf(stderr, ##__VA_ARGS__); \
+ (rc); \
+ })
+
+#else // DEBUG_P8_SCAN_COMPRESSION
+
+#define BUG(rc) (rc)
+#define BUGX(rc, ...) (rc)
+
+#endif // DEBUG_P8_SCAN_COMPRESSION
+
+// Note: For maximum flexibility we provide private versions of
+// endian-conversion routines rather than counting on a system-specific header
+// to provide these.
+
+// Byte-reverse a 32-bit integer if on a little-endian machine
+
+static uint32_t
+revle32(const uint32_t i_x)
+{
+ uint32_t rx;
+
+#ifndef _BIG_ENDIAN
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[3];
+ prx[1] = pix[2];
+ prx[2] = pix[1];
+ prx[3] = pix[0];
+#else
+ rx = i_x;
+#endif
+ return rx;
+}
+
+
+#if COMPRESSED_SCAN_DATA_VERSION != 1
+#error This code assumes CompressedScanData structure version 1 layout
+#endif
+
+void
+compressed_scan_data_translate(CompressedScanData* o_data,
+ CompressedScanData* i_data)
+{
+ o_data->iv_magic = revle32(i_data->iv_magic);
+ o_data->iv_size = revle32(i_data->iv_size);
+ o_data->iv_algorithmReserved = revle32(i_data->iv_algorithmReserved);
+ o_data->iv_length = revle32(i_data->iv_length);
+ o_data->iv_scanSelect = revle32(i_data->iv_scanSelect);
+ o_data->iv_headerVersion = i_data->iv_headerVersion;
+ o_data->iv_flushOptimization = i_data->iv_flushOptimization;
+ o_data->iv_chipletId = i_data->iv_chipletId;
+}
+
+
+// Return a big-endian-indexed nibble from a byte string
+
+static int
+get_nibble(const uint8_t* i_string, const uint32_t i_i)
+{
+ uint8_t byte;
+ int nibble;
+
+ byte = i_string[i_i / 2];
+ if (i_i % 2) {
+ nibble = byte & 0xf;
+ } else {
+ nibble = byte >> 4;
+ }
+ return nibble;
+}
+
+
+// Set a big-endian-indexed nibble in a byte string
+
+static int
+set_nibble(uint8_t* io_string, const uint32_t i_i, const int i_nibble)
+{
+ uint8_t* byte;
+
+ byte = &(io_string[i_i / 2]);
+ if (i_i % 2) {
+ *byte = (*byte & 0xf0) | i_nibble;
+ } else {
+ *byte = (*byte & 0x0f) | (i_nibble << 4);
+ }
+ return i_nibble;
+}
+
+
+// Encode an unsigned integer into a 4-bit octal stop code directly into a
+// nibble stream at io_string<i_i>, returning the number of nibbles in the
+// resulting code.
+
+static int
+stop_encode(const uint32_t i_count, uint8_t* io_string, const uint32_t i_i)
+{
+ uint32_t count;
+ int digits, offset;
+
+ // Determine the number of octal digits. There is always at least 1.
+
+ count = i_count >> 3;
+ digits = 1;
+ while (count) {
+ count >>= 3;
+ digits++;
+ }
+
+ // First insert the stop (low-order) digit
+
+ offset = digits - 1;
+ set_nibble(io_string, i_i + offset, (i_count & 0x7) | 0x8);
+
+ // Now insert the high-order digits
+
+ count = i_count >> 3;
+ offset--;
+ while (count) {
+ set_nibble(io_string, i_i + offset, count & 0x7);
+ offset--;
+ count >>= 3;
+ }
+
+ return digits;
+}
+
+
+// Decode an unsigned integer from a 4-bit octal stop code appearing in a byte
+// string at i_string<i_i>, returning the number of nibbles decoded.
+
+static int
+stop_decode(uint32_t* o_count, const uint8_t* i_string, const uint32_t i_i)
+{
+ int digits, nibble;
+ uint32_t i, count;
+
+ digits = 0;
+ count = 0;
+ i = i_i;
+
+ do {
+ nibble = get_nibble(i_string, i);
+ count = (count * 8) + (nibble & 0x7);
+ i++;
+ digits++;
+ } while ((nibble & 0x8) == 0);
+
+ *o_count = count;
+ return digits;
+}
+
+
+// RS4 compression algorithm notes:
+//
+// RS4 compression processes i_string as a string of nibbles. Final
+// special-case code handles the 0-3 remaining terminal bits.
+//
+// There is a special case for 0x0 nibbles embedded in a string of non-0x0
+// nibbles. It is more efficient to encode a single 0x0 nibble as part of a
+// longer string of non 0x0 nibbles. However it is break-even (actually a
+// slight statistical advantage) to break a scan seqeunce for 2 0x0 nibbles.
+//
+// If a run of 15 scan nibbles is found the scan is terminated and we return
+// to the rotate state. Runs of more than 15 scans will always include a
+// 0-length rotate between the scan sequences.
+//
+// Returns the number of nibbles in the compressed string.
+
+static uint32_t
+_rs4_compress(CompressedScanData* o_data,
+ const uint8_t* i_string,
+ const uint32_t i_length)
+{
+ int state; /* 0 : Rotate, 1 : Scan */
+ uint32_t n; /* Number of whole nibbles in i_data */
+ uint32_t r; /* Number of reminaing bits in i_data */
+ uint32_t i; /* Nibble index in i_string */
+ uint32_t j; /* Nibble index in data */
+ uint32_t k; /* Location to place scan count */
+ uint32_t count; /* Counts rotate/scan nibbles */
+ uint8_t* data; /* The compressed scan data area */
+
+ n = i_length / 4;
+ r = i_length % 4;
+ i = 0;
+ j = 0;
+ k = 0; /* Makes GCC happy */
+ data = (uint8_t*)o_data + sizeof(CompressedScanData);
+ count = 0;
+ state = 0;
+
+ // Process the bulk of the string. Note that state changes do not
+ // increment 'i' - the nibble at i_data<i> is always scanned again.
+
+ while (i < n) {
+ if (state == 0) {
+ if (get_nibble(i_string, i) == 0) {
+ count++;
+ i++;
+ } else {
+ j += stop_encode(count, data, j);
+ count = 0;
+ k = j;
+ j++;
+ state = 1;
+ }
+ } else {
+ if (get_nibble(i_string, i) == 0) {
+ if (((i + 1) < n) && (get_nibble(i_string, i + 1) == 0)) {
+ set_nibble(data, k, count);
+ count = 0;
+ state = 0;
+ } else {
+ set_nibble(data, j, 0);
+ count++;
+ i++;
+ j++;
+ }
+ } else {
+ set_nibble(data, j, get_nibble(i_string, i));
+ count++;
+ i++;
+ j++;
+ }
+ if ((state == 1) && (count == 15)) {
+ set_nibble(data, k, 15);
+ state = 0;
+ count = 0;
+ }
+ }
+ }
+
+ // Finish the current state and insert the terminate code (scan 0). If we
+ // finish on a scan we must insert a null rotate first.
+
+ if (state == 0) {
+ j += stop_encode(count, data, j);
+ } else {
+ set_nibble(data, k, count);
+ j += stop_encode(0, data, j);
+ }
+ set_nibble(data, j, 0);
+ j++;
+
+ // Insert the remainder count nibble, and if non-0, the remainder data
+ // nibble.
+
+ set_nibble(data, j, r);
+ j++;
+ if (r != 0) {
+ set_nibble(data, j, get_nibble(i_string, n));
+ j++;
+ }
+
+ // Return the number of nibbles in the compressed string.
+
+ return j;
+}
+
+
+// The worst-case compression for RS4 requires 2 nibbles of control overhead
+// per 15 nibbles of data (17/15), plus a maximum of 2 nibbles of termination.
+// We always allocate this worst-case amount of memory including the header
+// and any rounding required to guarantee that the allocated length is a
+// multiple of 8 bytes. The final size is also rounded up to a multiple of 8
+// bytes.
+
+int
+rs4_compress(CompressedScanData** o_data,
+ uint32_t* o_size,
+ const uint8_t* i_string,
+ const uint32_t i_length,
+ const uint64_t i_scanSelect,
+ const uint8_t i_chipletId,
+ const uint8_t i_flushOptimization)
+{
+ int rc;
+ uint32_t nibbles, bytes;
+
+ nibbles = (((((i_length + 3) / 4) + 14) / 15) * 17) + 2;
+ bytes = ((nibbles + 1) / 2) + sizeof(CompressedScanData);
+ bytes = ((bytes + 7) / 8) * 8;
+
+ *o_data = (CompressedScanData*)calloc(bytes, 1);
+
+ if (*o_data == 0) {
+ rc = BUG(SCAN_COMPRESSION_NO_MEMORY);
+ } else {
+ nibbles = _rs4_compress(*o_data, i_string, i_length);
+ bytes = ((nibbles + 1) / 2) + sizeof(CompressedScanData);
+ bytes = ((bytes + 7) / 8) * 8;
+
+ (*o_data)->iv_magic = revle32(RS4_MAGIC);
+ (*o_data)->iv_size = revle32(bytes);
+ (*o_data)->iv_algorithmReserved = revle32(nibbles);
+ (*o_data)->iv_length = revle32(i_length);
+ (*o_data)->iv_scanSelect = revle32((uint32_t)(i_scanSelect >> 32));
+ (*o_data)->iv_headerVersion = COMPRESSED_SCAN_DATA_VERSION;
+ (*o_data)->iv_flushOptimization = i_flushOptimization;
+ (*o_data)->iv_reserved = 0;
+ (*o_data)->iv_chipletId = i_chipletId;
+
+ *o_size = bytes;
+
+ rc = SCAN_COMPRESSION_OK;
+ }
+
+ return rc;
+}
+
+
+// Decompress an RS4-encoded string into a output string whose length must be
+// exactly i_length bits.
+//
+// Returns a scan compression return code.
+
+static int
+_rs4_decompress(uint8_t* o_string,
+ const uint8_t* i_string,
+ const uint32_t i_length)
+{
+ int rc;
+ int state; /* 0 : Rotate, 1 : Scan */
+ uint32_t i; /* Nibble index in i_string */
+ uint32_t j; /* Nibble index in o_string */
+ uint32_t k; /* Loop index */
+ uint32_t bits; /* Number of output bits decoded so far */
+ uint32_t count; /* Count of rotate nibbles */
+ uint32_t nibbles; /* Rotate encoding or scan nibbles to process */
+ int r; /* Remainder bits */
+
+ rc = 0;
+ i = 0;
+ j = 0;
+ bits = 0;
+ state = 0;
+
+ // Decompress the bulk of the string
+
+ do {
+ if (state == 0) {
+ nibbles = stop_decode(&count, i_string, i);
+ if ((bits + (4 * count)) > i_length) {
+ rc = BUG(SCAN_DECOMPRESSION_SIZE_ERROR);
+ break;
+ }
+ i += nibbles;
+ bits += (4 * count);
+ for (k = 0; k < count; k++) {
+ set_nibble(o_string, j, 0);
+ j++;
+ }
+ state = 1;
+ } else {
+ nibbles = get_nibble(i_string, i);
+ i++;
+ if (nibbles == 0) {
+ break;
+ }
+ if ((bits + (4 * nibbles)) > i_length) {
+ rc = BUG(SCAN_DECOMPRESSION_SIZE_ERROR);
+ break;
+ }
+ bits += (4 * nibbles);
+ for (k = 0; k < nibbles; k++) {
+ set_nibble(o_string, j, get_nibble(i_string, i));
+ i++;
+ j++;
+ }
+ state = 0;
+ }
+ } while (1);
+
+ // Now handle string termination
+
+ if (!rc) {
+ r = get_nibble(i_string, i);
+ i++;
+ if (r != 0) {
+ if ((bits + r) > i_length) {
+ rc = BUG(SCAN_DECOMPRESSION_SIZE_ERROR);
+ } else {
+ bits += r;
+ set_nibble(o_string, j, get_nibble(i_string, i));
+ }
+ }
+ }
+
+ // Final check to insure the string was valid
+
+ if (!rc) {
+ if (bits != i_length) {
+ rc = BUGX(SCAN_DECOMPRESSION_SIZE_ERROR,
+ "bits = %zu, i_length = %zu\n",
+ bits, i_length);
+ }
+ }
+
+ return rc;
+}
+
+
+int
+rs4_decompress(uint8_t** o_string,
+ uint32_t* o_length,
+ const CompressedScanData* i_data)
+{
+ int rc;
+ uint32_t bytes;
+
+ do {
+ if (revle32(i_data->iv_magic) != RS4_MAGIC) {
+ rc = BUG(SCAN_DECOMPRESSION_MAGIC_ERROR);
+ break;
+ }
+
+ *o_length = revle32(i_data->iv_length);
+ bytes = ((*o_length + 7) / 8) * 8;
+ *o_string = (uint8_t*)calloc(bytes, 1);
+ if (*o_string == 0) {
+ rc = BUG(SCAN_COMPRESSION_NO_MEMORY);
+ break;
+ }
+
+ rc = _rs4_decompress(*o_string,
+ (uint8_t*)i_data + sizeof(CompressedScanData),
+ *o_length);
+ } while (0);
+
+ return rc;
+}
+
+
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.H b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.H
new file mode 100644
index 000000000..73585572f
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.H
@@ -0,0 +1,271 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/p8_scan_compression.H $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+#ifndef __P8_SCAN_COMPRESSION_H__
+#define __P8_SCAN_COMPRESSION_H__
+
+// $Id: p8_scan_compression.H,v 1.1 2012/04/16 23:56:00 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/utils/p8_scan_compression.H,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! OWNER NAME: Bishop Brock Email: Bishop Brock; bcbrock@us.ibm.com
+// *!
+// *! General Description:
+// *!
+// *! See below.
+//------------------------------------------------------------------------------
+//
+// Note: This file was originally named p8_scan_compression.c; See CVS archive
+// for revision history of p8_scan_compression.c.
+
+/// \file p8_scan_compression.H
+/// \brief Structure definitions and protoypes related to scan chain
+/// compression.
+///
+/// This header declares and documents the entry points defined in
+/// p8_scan_compression.C. Some constants are also required by the scan
+/// decompression PORE assembly procedures.
+
+#include "fapi_sbe_common.H"
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+/// Compressed Scan Chain Data Structure Format
+///
+/// The compressed scan ring data structure must be 8-byte aligned in
+/// memory. The container data structure consists of this 24-byte header
+/// followed by an arbitrary number of 8 byte doublewords containing the
+/// compressed scan data. Images are always stored and processed in
+/// big-endian byte order. This container format is common across all
+/// decompression algorithms.
+///
+/// Bytes - Content
+///
+/// 0:3 - A 32-bit "magic number" that identifies and validates the
+/// compression algorithm and algorithm version used to compress the data.
+///
+/// 4:7 - The 32-bit size of the entire data structure in \e bytes. This
+/// consists of this 24-byte header plus the compressed scan data. This value
+/// is always a multiple of 8.
+///
+/// 8:11 - This 32-bit value is reserved to the compression
+/// algorithm. Typically this field is used to record the 'size' of the
+/// compressed string in units specific to each algorithm.
+///
+/// 12:15 - The length of the original scan chain in \e bits.
+///
+/// 16:19 - The 32 high-order bits of the value written to the Scan Select
+/// register to set up the scan. The Scan Select register only defines these
+/// bits.
+///
+/// 20 - The Scan Chain Data Structure version number
+///
+/// 21 - Flush-optimize : Is this byte is non-zero, the ring state to be
+/// modified is the flush state of the ring.
+///
+/// 22 - Reserved
+///
+/// 23 - The 7-bit pervasive chiplet Id + Multicast bit of the chiplet to
+/// scan. This value is loaded directly into P0. The decompression
+/// algorithms provide two entry points - one that uses this value as the
+/// chiplet Id, and another that allows the caller to specify the chiplet Id
+/// in the call.
+
+typedef struct {
+
+ /// Magic number - See \ref scan_compression_magic
+ uint32_t iv_magic;
+
+ /// Total size in bytes, including the container header
+ uint32_t iv_size;
+
+ /// Reserved to the algorithm
+ uint32_t iv_algorithmReserved;
+
+ /// Length of the original scan chain in bits
+ uint32_t iv_length;
+
+ /// The high-order 32 bits of the Scan Select Register
+ ///
+ /// Note that the Scan Select register only defines the high order 32
+ /// bits, so we only need store the 32 high-order bits. This field is
+ /// 8-byte aligned so that the doubleword loaded by the PORE can be
+ /// directly written to the scan select register.
+ uint32_t iv_scanSelect;
+
+ /// Data structure (header) version
+ uint8_t iv_headerVersion;
+
+ /// Flush-state optimization
+ ///
+ /// Normally, modifying the state of the ring requires XOR-ing the
+ /// difference state (the compressed state) with the current ring state as
+ /// it will appear in the Scan Data Register. If the current state of the
+ /// ring is the scan-0 flush state, then by definition the Scan Data
+ /// Register is always 0. Therefore we can simply write the difference to
+ /// the Scan Data Register rather than using a read-XOR-write.
+ uint8_t iv_flushOptimization;
+
+ /// Alignment padding
+ uint8_t iv_reserved;
+
+ /// 7-bit pervasive chiplet Id + Multicast bit
+ ///
+ /// This field is right-justified in an 8-byte aligned doubleword so that
+ /// the P0 register can be directly updated from the doubelword value in a
+ /// data register.
+ uint8_t iv_chipletId;
+
+} CompressedScanData;
+
+
+/// Endian-translate a CompressedScanData structure
+///
+/// \param o_data A pointer to a CompressedScanData structure to receive the
+/// endian-translated form of \a i_data.
+///
+/// \param i_data A pointer to the original CompressedScanData structure.
+///
+/// This API performs an endian-converting copy of a CompressedScanData
+/// structure. This copy is guaranteed to be done in such a way that \a i_data
+/// and \a o_data may be the same pointer for in-place conversion. Due to the
+/// symmetry of reverse, translating a structure twice is always guaranteed to
+/// return the origial structure to its original byte order.
+void
+compressed_scan_data_translate(CompressedScanData* o_data,
+ CompressedScanData* i_data);
+
+
+/// Compress a scan string using the RS4 compression algorithm
+///
+/// \param o_data This algorithm uses malloc() to allocate memory for the
+/// compresed data, and returns a pointer to this memory in \a o_data. After
+/// the call this memory is owned by the caller who is responsible for
+/// free()-ing the data area once it is no longer required. Note that the
+/// CompressedScanData is always created in big-endian format, however the
+/// caller can use compresed_scan_data_translate() to create a copy of the
+/// header in host format.
+///
+/// \param o_size The effective size of the entire compressed scan data
+/// structure (header + compressed data) pointed to by \a o_data, in bytes.
+/// This value will always be a multiple of 8.
+///
+/// \param i_string The string to compress. Scan data to compress is
+/// left-justified in this input string.
+///
+/// \param i_length The length of the input string in \e bits. It is assumed
+/// the \a i_string contains at least (\a i_length + 7) / 8 bytes.
+///
+/// \param i_scanSelect The 64-bit value written to the Scan Select register
+/// to set up for the scan. Only the 32 high-order bits are actually stored.
+///
+/// \param i_chipletId The 7-bit value for the iv_chipletId field of the
+/// CompressedScanData.
+///
+/// \param i_flushOptimization This input parameter should be set to a non-0
+/// value if it is known that this ring difference will be applied to a scan-0
+/// flush state. This will improve the performance of the decompress-scan
+/// routine. If the initial state of the ring is unknown, set this parameter
+/// to 0.
+///
+/// \returns See \ref scan_compression_codes
+int
+rs4_compress(CompressedScanData** o_data,
+ uint32_t* o_size,
+ const uint8_t* i_string,
+ const uint32_t i_length,
+ const uint64_t i_scanSelect,
+ const uint8_t i_chipletId,
+ const uint8_t i_flushOptimization);
+
+
+/// Decompress a scan string compressed using the RS4 compression algorithm
+///
+/// \param o_string The API malloc()-s this data area to contain the
+/// decompressed string. After this call the caller owns \a o_string and is
+/// responsible for free()-ing this data area once it is no longer required.
+///
+/// \param o_length The length of the decompressed string in \e bits. The
+/// caller may assume that \a o_string contains at least (\a o_length + 7) / 8
+/// bytes.
+///
+/// \param i_data A pointer to the CompressedScanData header + data to be
+/// decompressed.
+int
+rs4_decompress(uint8_t** o_string,
+ uint32_t* o_length,
+ const CompressedScanData* i_data);
+
+#endif // __ASSEMBLER__
+
+
+/// The current version of the CompressedScanData structure
+///
+/// This constant is required to be a #define to guarantee consistency between
+/// the header format and cmopiled code.
+#define COMPRESSED_SCAN_DATA_VERSION 1
+
+/// The size of the CompressedScanData structure
+CONST_UINT8_T(COMPRESSED_SCAN_DATA_SIZE, 24);
+
+
+/// \defgroup scan_compression_magic Scan Compression Magic Numbers
+///
+/// @ {
+
+/// RS4 Magic
+CONST_UINT32_T(RS4_MAGIC, 0x52533401); /* "RS4" + Version 0x01 */
+
+/// @}
+
+
+/// \defgroup scan_compression_codes Scan Compression Return Codes
+///
+/// @{
+
+/// Normal return code
+CONST_UINT8_T(SCAN_COMPRESSION_OK, 0);
+
+/// The (de)compression algorithm could not allocate enough memory for the
+/// (de)compression.
+CONST_UINT8_T(SCAN_COMPRESSION_NO_MEMORY, 1);
+
+/// Magic number mismatch on scan decompression
+CONST_UINT8_T(SCAN_DECOMPRESSION_MAGIC_ERROR, 2);
+
+/// Decompression size error
+///
+/// Decompression produced a string of a size different than indicated in the
+/// header, indicating either a bug or data corruption. Note that the entire
+/// application should be considered corrupted if this error occurs since it
+/// may not be discovered until after the decompression buffer is overrun.
+CONST_UINT8_T(SCAN_DECOMPRESSION_SIZE_ERROR, 3);
+
+/// @}
+
+#endif // __P8_SCAN_COMPRESSION_H__
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pgas.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pgas.h
new file mode 100644
index 000000000..92fb57646
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pgas.h
@@ -0,0 +1,1044 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pgas.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+#ifndef __PGAS_H__
+#define __PGAS_H__
+
+#define __PGAS__
+
+// $Id: pgas.h,v 1.16 2012/05/23 19:03:40 bcbrock Exp $
+
+// ** WARNING : This file is maintained as part of the OCC firmware. Do **
+// ** not edit this file in the PMX area, the hardware procedure area, **
+// ** or the PoreVe area as any changes will be lost. **
+
+/// \file pgas.h
+/// \brief Pore GAS
+///
+/// PGAS is documented in a seperate standalone document entitled <em> PGAS :
+/// PORE GAS (GNU Assembler) User's and Reference Manual <\em>.
+///
+/// This file defines support macros for the GNU PORE assembler, and the PORE
+/// inline assembler and disassebler which follow the PGAS assembly syntax.
+/// If the compile swith PGAS_PPC is defined in the environment then pgas.h
+/// includes pgas_ppc.h which transforms a PowerPC assembler into an assembler
+/// for PORE.
+
+// These are the opcodes and mnemonics as defined by the PORE hardware
+// manual. Many of them will change names slightly in PGAS.
+
+#define PORE_OPCODE_NOP 0x0f
+#define PORE_OPCODE_WAIT 0x01
+#define PORE_OPCODE_TRAP 0x02
+#define PORE_OPCODE_HOOK 0x4f
+
+#define PORE_OPCODE_BRA 0x10
+#define PORE_OPCODE_BRAZ 0x12
+#define PORE_OPCODE_BRANZ 0x13
+#define PORE_OPCODE_BRAI 0x51
+#define PORE_OPCODE_BSR 0x14
+#define PORE_OPCODE_BRAD 0x1c
+#define PORE_OPCODE_BSRD 0x1d
+#define PORE_OPCODE_RET 0x15
+#define PORE_OPCODE_CMPBRA 0x56
+#define PORE_OPCODE_CMPNBRA 0x57
+#define PORE_OPCODE_CMPBSR 0x58
+#define PORE_OPCODE_LOOP 0x1f
+
+#define PORE_OPCODE_ANDI 0x60
+#define PORE_OPCODE_ORI 0x61
+#define PORE_OPCODE_XORI 0x62
+
+#define PORE_OPCODE_AND 0x25
+#define PORE_OPCODE_OR 0x26
+#define PORE_OPCODE_XOR 0x27
+
+#define PORE_OPCODE_ADD 0x23
+#define PORE_OPCODE_ADDI 0x24
+#define PORE_OPCODE_SUB 0x29
+#define PORE_OPCODE_SUBI 0x28
+#define PORE_OPCODE_NEG 0x2a
+
+#define PORE_OPCODE_COPY 0x2c
+#define PORE_OPCODE_ROL 0x2e
+
+#define PORE_OPCODE_LOAD20 0x30
+#define PORE_OPCODE_LOAD64 0x71
+#define PORE_OPCODE_SCR1RD 0x32
+#define PORE_OPCODE_SCR1RDA 0x73
+#define PORE_OPCODE_SCR2RD 0x36
+#define PORE_OPCODE_SCR2RDA 0x77
+#define PORE_OPCODE_WRI 0x78
+#define PORE_OPCODE_BS 0x74
+#define PORE_OPCODE_BC 0x75
+#define PORE_OPCODE_SCR1WR 0x39
+#define PORE_OPCODE_SCR2WR 0x3a
+#define PORE_OPCODE_SCAND 0x7c
+
+
+// These are the PGAS versions of the PORE opcodes used in the legacy PGAS_PPC
+// assembler and the current PORE inline assembler/disassembler.
+
+#define PGAS_OPCODE_NOP PORE_OPCODE_NOP
+#define PGAS_OPCODE_WAITS PORE_OPCODE_WAIT
+#define PGAS_OPCODE_TRAP PORE_OPCODE_TRAP
+#define PGAS_OPCODE_HOOKI PORE_OPCODE_HOOK
+
+#define PGAS_OPCODE_BRA PORE_OPCODE_BRA
+#define PGAS_OPCODE_BRAZ PORE_OPCODE_BRAZ
+#define PGAS_OPCODE_BRANZ PORE_OPCODE_BRANZ
+#define PGAS_OPCODE_BRAI PORE_OPCODE_BRAI
+#define PGAS_OPCODE_BSR PORE_OPCODE_BSR
+#define PGAS_OPCODE_BRAD PORE_OPCODE_BRAD
+#define PGAS_OPCODE_BSRD PORE_OPCODE_BSRD
+#define PGAS_OPCODE_RET PORE_OPCODE_RET
+#define PGAS_OPCODE_CMPIBRAEQ PORE_OPCODE_CMPBRA
+#define PGAS_OPCODE_CMPIBRANE PORE_OPCODE_CMPNBRA
+#define PGAS_OPCODE_CMPIBSREQ PORE_OPCODE_CMPBSR
+#define PGAS_OPCODE_LOOP PORE_OPCODE_LOOP
+
+#define PGAS_OPCODE_ANDI PORE_OPCODE_ANDI
+#define PGAS_OPCODE_ORI PORE_OPCODE_ORI
+#define PGAS_OPCODE_XORI PORE_OPCODE_XORI
+
+#define PGAS_OPCODE_AND PORE_OPCODE_AND
+#define PGAS_OPCODE_OR PORE_OPCODE_OR
+#define PGAS_OPCODE_XOR PORE_OPCODE_XOR
+
+#define PGAS_OPCODE_ADD PORE_OPCODE_ADD
+#define PGAS_OPCODE_ADDS PORE_OPCODE_ADDI
+#define PGAS_OPCODE_SUB PORE_OPCODE_SUB
+#define PGAS_OPCODE_SUBS PORE_OPCODE_SUBI
+#define PGAS_OPCODE_NEG PORE_OPCODE_NEG
+
+#define PGAS_OPCODE_MR PORE_OPCODE_COPY
+#define PGAS_OPCODE_ROLS PORE_OPCODE_ROL
+
+#define PGAS_OPCODE_LS PORE_OPCODE_LOAD20
+#define PGAS_OPCODE_LI PORE_OPCODE_LOAD64
+#define PGAS_OPCODE_LD0 PORE_OPCODE_SCR1RD /* Used by LD */
+#define PGAS_OPCODE_LD0ANDI PORE_OPCODE_SCR1RDA /* Used by LDANDI */
+#define PGAS_OPCODE_LD1 PORE_OPCODE_SCR2RD /* Used by LD */
+#define PGAS_OPCODE_LD1ANDI PORE_OPCODE_SCR2RDA /* Used by LDANDI */
+#define PGAS_OPCODE_STI PORE_OPCODE_WRI
+#define PGAS_OPCODE_BSI PORE_OPCODE_BS
+#define PGAS_OPCODE_BCI PORE_OPCODE_BC
+#define PGAS_OPCODE_STD0 PORE_OPCODE_SCR1WR /* Used by STD */
+#define PGAS_OPCODE_STD1 PORE_OPCODE_SCR2WR /* Used by STD */
+#define PGAS_OPCODE_SCAND PORE_OPCODE_SCAND
+
+
+// These are the programmer-visible register names as defined by the PORE
+// hardware manual. All of these names (except the PC) appear differently in
+// the PGAS syntax, in some cases to reduce confusion, in other cases just to
+// have more traditional short mnemonics.
+
+#define PORE_REGISTER_PRV_BASE_ADDR0 0x0
+#define PORE_REGISTER_PRV_BASE_ADDR1 0x1
+#define PORE_REGISTER_OCI_BASE_ADDR0 0x2
+#define PORE_REGISTER_OCI_BASE_ADDR1 0x3
+#define PORE_REGISTER_SCRATCH0 0x4
+#define PORE_REGISTER_SCRATCH1 0x5
+#define PORE_REGISTER_SCRATCH2 0x6
+#define PORE_REGISTER_ERROR_MASK 0x7
+#define PORE_REGISTER_EXE_TRIGGER 0x9
+#define PORE_REGISTER_DATA0 0xa
+#define PORE_REGISTER_PC 0xe
+#define PORE_REGISTER_IBUF_ID 0xf
+
+
+// PgP IBUF_ID values
+
+#define PORE_ID_GPE0 0x00
+#define PORE_ID_GPE1 0x01
+#define PORE_ID_SLW 0x08
+#define PORE_ID_SBE 0x04
+
+
+// Condition Codes
+
+#define PORE_CC_UGT 0x8000
+#define PORE_CC_ULT 0x4000
+#define PORE_CC_SGT 0x2000
+#define PORE_CC_SLT 0x1000
+#define PORE_CC_C 0x0800
+#define PORE_CC_V 0x0400
+#define PORE_CC_N 0x0200
+#define PORE_CC_Z 0x0100
+
+
+#ifdef __ASSEMBLER__
+
+////////////////////////////////////////////////////////////////////////////
+// PGAS Base Assembler Support
+////////////////////////////////////////////////////////////////////////////
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Condition Codes
+ //////////////////////////////////////////////////////////////////////
+
+ .set CC_UGT, PORE_CC_UGT
+ .set CC_ULT, PORE_CC_ULT
+ .set CC_SGT, PORE_CC_SGT
+ .set CC_SLT, PORE_CC_SLT
+ .set CC_C, PORE_CC_C
+ .set CC_V, PORE_CC_V
+ .set CC_N, PORE_CC_N
+ .set CC_Z, PORE_CC_Z
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Utility Macros
+ //////////////////////////////////////////////////////////////////////
+
+ // 'Undefine' PowerPC mnemonics to trap programming errors
+
+ .macro ..undefppc1, i
+ .ifnc \i, ignore
+ .macro \i, args:vararg
+ .error "This is a PowerPC opcode - NOT a PGAS opcode or extended mnemonic"
+ .endm
+ .endif
+ .endm
+
+ .macro .undefppc, i0, i1=ignore, i2=ignore, i3=ignore
+ ..undefppc1 \i0
+ ..undefppc1 \i1
+ ..undefppc1 \i2
+ ..undefppc1 \i3
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Argument Checking Macros
+ //////////////////////////////////////////////////////////////////////
+ //
+ // These macros remain in the final pgas.h file because 1) they are
+ // required for some PGAS pseudo-ops, and 2) to support robust
+ // assembler macro definitions.
+
+ // Check an unsigned immediate for size
+
+ .macro ..checku, x:req, bits:req, err="Unsigned value too large"
+
+ .if (((\bits) <= 0) || ((\bits) > 63))
+ .error "The number of bits must be in the range 0 < bits < 64"
+ .endif
+
+ .iflt (\x)
+ .error "An unsigned value is required here"
+ .endif
+
+ .ifgt ((\x) - (0xffffffffffffffff >> (64 - (\bits))))
+ .error "\err"
+ .endif
+
+ .endm
+
+ // Check unsigned 16/22-bit immediates for size
+ //
+ // In general, PGAS can check immediate values for size restrictions,
+ // but unfortunately is not able to check address offset immediates for
+ // range.
+
+ .macro ..check_u16, u16
+ ..checku (\u16), 16, "Unsigned immediate is larger than 16 bits"
+ .endm
+
+ .macro ..check_u24, u24
+ ..checku (\u24), 24, "Unsigned immediate is larger than 24 bits"
+ .endm
+
+ // Check a 16/20/22-bit signed immediate for size
+
+ .macro ..check_s16, s16
+ .iflt \s16
+ .iflt \s16 + 0x8000
+ .error "Immediate value too small for a signed 16-bit field"
+ .endif
+ .else
+ .ifgt \s16 - 0x7fff
+ .error "Immediate value too large for a signed 16-bit field"
+ .endif
+ .endif
+ .endm
+
+ .macro ..check_s20, s20
+ .iflt \s20
+ .iflt \s20 + 0x80000
+ .error "Immediate value too small for a signed 20-bit field"
+ .endif
+ .else
+ .ifgt \s20 - 0x7ffff
+ .error "Immediate value too large for a signed 20-bit field"
+ .endif
+ .endif
+ .endm
+
+ .macro ..check_s22, s22
+ .iflt \s22
+ .iflt \s22 + 0x200000
+ .error "Immediate value too small for a signed 22-bit field"
+ .endif
+ .else
+ .ifgt \s22 - 0x1fffff
+ .error "Immediate value too large for a signed 22-bit field"
+ .endif
+ .endif
+ .endm
+
+ // Check a putative SCOM address for bits 0 and 8:11 == 0.
+
+ .macro ..check_scom, address
+ .if ((\address) & 0x80f00000)
+ .error "Valid SCOM addresses must have bits 0 and 8:11 equal to 0."
+ .endif
+ .endm
+
+ // A register required to be D0
+
+ .macro ..d0, reg
+ .if (\reg != D0)
+ .error "Data register D0 is required here"
+ .endif
+ .endm
+
+ // A register pair required to be D0, D1 in order
+
+ .macro ..d0d1, reg1, reg2
+ .if (((\reg1) != D0) && ((\reg2) != D1))
+ .error "Register-Register ALU operations are only defined on the source pair D0, D1"
+ .endif
+ .endm
+
+ // A register pair required to be D0, D1 in any order
+ .macro ..dxdy, reg1, reg2, err="Expecting D0, D1 in either order"
+ .if !((((\reg1) == D0) && ((\reg2) == D1)) || \
+ (((\reg1) == D1) && ((\reg2) == D0)))
+ .error "\err"
+ .endif
+ .endm
+
+ // A register pair required to be the same register
+
+ .macro ..same, dest, src
+ .if ((\dest) != (\src))
+ .error "PGAS requires the src and dest register of ADDS/SUBS to be explicit and identical"
+ .endif
+ .endm
+
+ // A "Data" register
+
+ .macro ..data, reg:req, err="Expecting a 'Data' register"
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .error "\err"
+ .endif
+ .endif
+ .endm
+
+ // An "Address" register
+
+ .macro ..address, reg:req, err=:"Expecting an 'Address' register"
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .error "\err"
+ .endif
+ .endif
+ .endm
+
+ // A "Pervasive Chiplet ID" register
+
+ .macro ..pervasive_chiplet_id, reg:req, err="Expecting a 'Pervasive Chiplet ID' register"
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .error "\err"
+ .endif
+ .endif
+ .endm
+
+ // A "Branch Compare Data" register
+
+ .macro ..branch_compare_data, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != CTR)
+ .error "Expecting a 'Branch Compare Data' register"
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "LS Destination" register; Also the set for ADDS/SUBS
+
+ .macro ..ls_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .if (\reg != CTR)
+ .error "Expecting an 'LS Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "LI Destination" register
+
+ .macro ..li_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != CTR)
+ .error "Expecting an 'LI Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "LIA Destination" register
+
+ .macro ..lia_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != TBAR)
+ .error "Expecting an 'LIA Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "MR Source" register
+
+ .macro ..mr_source, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .if (\reg != CTR)
+ .if (\reg != PC)
+ .if (\reg != ETR)
+ .if (\reg != SPRG0)
+ .if (\reg != IFR)
+ .if (\reg != EMR)
+ .error "Expecting an 'MR Source' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+ // An "MR Destination" register
+
+ .macro ..mr_destination, reg
+ .if (\reg != D0)
+ .if (\reg != D1)
+ .if (\reg != A0)
+ .if (\reg != A1)
+ .if (\reg != P0)
+ .if (\reg != P1)
+ .if (\reg != CTR)
+ .if (\reg != PC)
+ .if (\reg != ETR)
+ .if (\reg != SPRG0)
+ .if (\reg != EMR)
+ .error "Expecting an 'MR Destination' register"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PORE address spaces
+ //////////////////////////////////////////////////////////////////////
+
+ // The ..set_address_space pseudo-op defines the default address
+ // space. It must be defined in order to use BRAA, BRAIA, BSR and
+ // CMPIBSR. Pseudo-ops are provided to set the default space of the
+ // program. Note that code assembled for PNOR will also work in the
+ // OCI space in the Sleep/Winkle engine.
+
+ .set PORE_SPACE_UNDEFINED, 0xffff
+ .set PORE_SPACE_OCI, 0x8000
+ .set PORE_SPACE_PNOR, 0x800b
+ .set PORE_SPACE_OTPROM, 0x0001
+ .set PORE_SPACE_SEEPROM, 0x800c
+ .set PORE_SPACE_PIBMEM, 0x0008
+
+ .macro ..set_default_space, s
+ ..check_u16 (\s)
+ .set _PGAS_DEFAULT_SPACE, (\s)
+ .endm
+
+ .macro ..check_default_space
+ .if (_PGAS_DEFAULT_SPACE == PORE_SPACE_UNDEFINED)
+ .error "The PGAS default address space has not been defined"
+ .endif
+ .endm
+
+ ..set_default_space PORE_SPACE_UNDEFINED
+
+ .macro .oci
+ ..set_default_space PORE_SPACE_OCI
+ .endm
+
+ .macro .pnor
+ ..set_default_space PORE_SPACE_PNOR
+ .endm
+
+ .macro .seeprom
+ ..set_default_space PORE_SPACE_SEEPROM
+ .endm
+
+ .macro .otprom
+ ..set_default_space PORE_SPACE_OTPROM
+ .endm
+
+ .macro .pibmem
+ ..set_default_space PORE_SPACE_PIBMEM
+ .pibmem_port (PORE_SPACE_PIBMEM & 0xf)
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Address-Generation Pseudo Ops
+ //////////////////////////////////////////////////////////////////////
+
+ // .QUADA, .QUADIA
+
+ .macro .quada, offset:req
+ ..check_default_space
+ .long _PGAS_DEFAULT_SPACE
+ .long (\offset)
+ .endm
+
+ .macro .quadia, space:req, offset:req
+ ..check_u16 (\space)
+ .long (\space)
+ .long (\offset)
+ .endm
+
+ //////////////////////////////////////////////////////////////////////
+ // "A"- and "IA"-form Instructions
+ //////////////////////////////////////////////////////////////////////
+
+ // BRAA (Branch Address) is a 'long branch' to an address in the
+ // default memory space.
+
+ .macro braa, offset:req
+ braia _PGAS_DEFAULT_SPACE, (\offset)
+ .endm
+
+ // LA (Load Address) loads the full address of an address in the
+ // default memory space.
+
+ .macro la, dest:req, offset:req
+ lia (\dest), _PGAS_DEFAULT_SPACE, (\offset)
+ .endm
+
+ // STA (Store Address) stores the full address of an address in the
+ // default memory space.
+
+ .macro sta, mem_offset:req, base:req, addr_offset:req
+ stia (\mem_offset), (\base), _PGAS_DEFAULT_SPACE, (\addr_offset)
+ .endm
+
+ // BSRIA is a subroutine branch into another memory space. This has to
+ // be emulated by a local subroutine branch and a BRAIA.
+
+ .macro bsria, space:req, offset:req
+ bsr 27742f
+ bra 27743f
+27742:
+ braia (\space), (\offset)
+27743:
+ .endm
+
+
+////////////////////////////////////////////////////////////////////////////
+// Extended Mnemonics, Macros and Special Cases
+////////////////////////////////////////////////////////////////////////////
+
+ //////////////////////////////////////////////////////////////////////
+ // TFB<c> - Test flags and branch conditionally
+ //////////////////////////////////////////////////////////////////////'
+
+ .macro ..tfb, dest, target, flags
+ ..data (\dest)
+ mr (\dest), IFR
+ andi (\dest), (\dest), (\flags)
+ branz (\dest), (\target)
+ .endm
+
+ .macro ..tfbn dest, target, flags
+ ..data (\dest)
+ mr (\dest), IFR
+ andi (\dest), (\dest), (\flags)
+ braz (\dest), (\target)
+ .endm
+
+ .macro tfbcs, dest:req, target:req
+ ..tfb (\dest), (\target), CC_C
+ .endm
+
+ .macro tfbcc, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_C
+ .endm
+
+ .macro tfbvs, dest:req, target:req
+ ..tfb (\dest), (\target), CC_V
+ .endm
+
+ .macro tfbvc, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_V
+ .endm
+
+ .macro tfbns, dest:req, target:req
+ ..tfb (\dest), (\target), CC_N
+ .endm
+
+ .macro tfbnc, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_N
+ .endm
+
+ .macro tfbeq, dest:req, target:req
+ ..tfb (\dest), (\target), CC_Z
+ .endm
+
+ .macro tfbne, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_Z
+ .endm
+
+ .macro tfbult, dest:req, target:req
+ ..tfb (\dest), (\target), CC_ULT
+ .endm
+
+ .macro tfbule, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_UGT
+ .endm
+
+ .macro tfbuge, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_ULT
+ .endm
+
+ .macro tfbugt, dest:req, target:req
+ ..tfb (\dest), (\target), CC_UGT
+ .endm
+
+ .macro tfbslt, dest:req, target:req
+ ..tfb (\dest), (\target), CC_SLT
+ .endm
+
+ .macro tfbsle, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_SGT
+ .endm
+
+ .macro tfbsge, dest:req, target:req
+ ..tfbn (\dest), (\target), CC_SLT
+ .endm
+
+ .macro tfbsgt, dest:req, target:req
+ ..tfb (\dest), (\target), CC_SGT
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // TEB<eng> - Test Engine and branch if engine.
+ //////////////////////////////////////////////////////////////////////
+ //
+ // All but GPE0 use a 1-hot code.
+
+ .macro tebgpe0, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), 0xf
+ braz (\dest), (\target)
+ .endm
+
+ .macro tebgpe1, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_GPE1
+ branz (\dest), (\target)
+ .endm
+
+ .macro tebslw, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_SLW
+ branz (\dest), (\target)
+ .endm
+
+ .macro tebsbe, dest:req, target:req
+ mr (\dest), IFR
+ andi (\dest), (\dest), PORE_ID_SBE
+ branz (\dest), (\target)
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // LPCS - Load Pervasive Chiplet from Scom address
+ //////////////////////////////////////////////////////////////////////
+
+ .macro lpcs, dest:req, scom:req
+ ..pervasive_chiplet_id (\dest)
+ ..check_scom (\scom)
+ ls (\dest), (((\scom) >> 24) & 0x7f)
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // Shift/Mask extended mnemonics
+ //////////////////////////////////////////////////////////////////////
+
+ // All of the 'dot-dot' macros assume that error and identity
+ // checking has been done on the arguments already.
+
+ // The initial register-register rotate. If the incoming shift amount
+ // is 0 then the instruction generated is a simple MR.
+
+ .macro ..rotlrr, ra, rs, sh
+
+ .if (\sh) >= 32
+ rols (\ra), (\rs), 32
+ ..rotlr (\ra), ((\sh) - 32)
+ .elseif (\sh) >= 16
+ rols (\ra), (\rs), 16
+ ..rotlr (\ra), ((\sh) - 16)
+ .elseif (\sh) >= 8
+ rols (\ra), (\rs), 8
+ ..rotlr (\ra), ((\sh) - 8)
+ .elseif (\sh) >= 4
+ rols (\ra), (\rs), 4
+ ..rotlr (\ra), ((\sh) - 4)
+ .elseif (\sh) >= 1
+ rols (\ra), (\rs), 1
+ ..rotlr (\ra), ((\sh) - 1)
+ .else
+ mr (\ra), (\rs)
+ .endif
+
+ .endm
+
+
+ // Subsequent rotation of the same register. The SH should never be 0
+ // here.
+
+ .macro ..rotlr, ra, sh
+
+ .if (\sh) >= 32
+ rols (\ra), (\ra), 32
+ ..rotlr (\ra), ((\sh) - 32)
+ .elseif (\sh) >= 16
+ rols (\ra), (\ra), 16
+ ..rotlr (\ra), ((\sh) - 16)
+ .elseif (\sh) >= 8
+ rols (\ra), (\ra), 8
+ ..rotlr (\ra), ((\sh) - 8)
+ .elseif (\sh) >= 4
+ rols (\ra), (\ra), 4
+ ..rotlr (\ra), ((\sh) - 4)
+ .elseif (\sh) >= 1
+ rols (\ra), (\ra), 1
+ ..rotlr (\ra), ((\sh) - 1)
+
+ .endif
+
+ .endm
+
+
+ // RLDINM RA, RS, SH, MB, ME
+ //
+ // Defined as if there were an equivalent PowerPC instruction. The
+ // 'word' forms of the PowerPC instructions and extended mnemonics are
+ // undefined in order to catch programming typos.
+
+ .undefppc rlwinm, extrwi, rotlwi, rotrwi
+ .undefppc slwi, srwi
+
+ .macro rldinm, ra:req, rs:req, sh:req, mb:req, me:req
+
+ .if ((\sh) < 0) || ((\sh) > 63)
+ .error "SH must be in the range 0..63"
+ .endif
+ .if ((\mb) < 0) || ((\mb) > 63)
+ .error "MB must be in the range 0..63"
+ .endif
+ .if ((\me) < 0) || ((\me) > 63)
+ .error "ME must be in the range 0..63"
+ .endif
+
+ .if (((\mb) == 0) && ((\me) == 63) || ((\me) == ((\mb) - 1)))
+
+ // The mask is effectively 0..63, i.e., no mask. This is a
+ // simple rotate.
+
+ ..rotlrr (\ra), (\rs), (\sh)
+
+ .else
+
+ // We need a mask step. However if SH == 0 and RA == RS we can
+ // bypass the rotate step.
+
+ .if ((\sh) != 0) || ((\ra) != (\rs))
+ ..rotlrr (\ra), (\rs), (\sh)
+ .endif
+ .if ((\mb) <= (\me))
+
+ // This is a straightforward masking operation with a
+ // single mask.
+
+ andi (\ra), (\ra), ((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - (\me))))
+ .else
+
+ // This is a wrapped mask.
+ // It is created as 2 masks OR-ed together - 0-ME and MB-63
+
+ andi (\ra), (\ra), (((0xffffffffffffffff >> 0) & (0xffffffffffffffff << (63 - (\me)))) | ((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - 63))))
+ .endif
+
+ .endif
+
+ .endm
+
+ // RLDINM Extended Mnemonics
+ //
+ // Defined as if they were equivalent to PowerPC 32-bit extended
+ // mnemonics
+
+ .macro extldi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "EXTLDI requires N > 0"
+ .endif
+ rldinm (\ra), (\rs), (\b), 0, ((\n) - 1)
+ .endm
+
+ .macro extrdi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "EXTRDI requires N > 0"
+ .endif
+ rldinm (\ra), (\rs), (((\b) + (\n)) % 64), (64 - (\n)), 63
+ .endm
+
+ .macro rotldi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (\n), 0, 63
+ .endm
+
+
+ .macro rotrdi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (64 - (\n)), 0, 63
+ .endm
+
+
+ .macro sldi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (\n), 0, (63 - (\n))
+ .endm
+
+
+ .macro srdi, ra:req, rs:req, n:req
+ rldinm (\ra), (\rs), (64 - (\n)), (\n), 63
+ .endm
+
+
+ // RLDIMI RA, RS, SH, MB, ME
+ //
+ // Defined as if there were an equivalent PowerPC instruction. The
+ // 'word' forms of the PowerPC instructions and extended mnemonics are
+ // undefined in order to catch programming typos.
+ //
+ // Note that unlike the PowerPC instructions, here RLDIMI must destroy
+ // RS by masking and shifting it, and RA and RS may not be the same
+ // register.
+
+ .undefppc rlwimi, inslwi, insrwi
+
+ .macro rldimi, ra:req, rs:req, sh:req, mb:req, me:req
+
+ ..dxdy (\ra), (\rs)
+
+ // SH error checks are done by rldinm
+
+ .if (((\mb) == 0) && ((\me) == 63) || ((\me) == ((\mb) - 1)))
+
+ // The mask is effectively 0..63, i.e., no mask. This is a
+ // simple rotate of RS into RA
+
+ rotldi (\ra), (\rs), (\sh)
+
+ .else
+
+ // Rotate RS and AND with mask
+
+ rldinm (\rs), (\rs), (\sh), (\mb), (\me)
+
+ // Mask out the significant bits of RS, clear that section of
+ // RA, and logical OR RS into RA
+
+ .if ((\mb) <= (\me))
+
+ // This is a straightforward masking operation with a
+ // single mask.
+
+ andi (\ra), (\ra), \
+ (~((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - (\me)))))
+ .else
+
+ // This is a wrapped mask.
+ // It is created as 2 masks OR-ed together - 0-ME and MB-63
+
+ andi (\ra), (\ra), \
+ (~(((0xffffffffffffffff >> 0) & (0xffffffffffffffff << (63 - (\me)))) | \
+ ((0xffffffffffffffff >> (\mb)) & (0xffffffffffffffff << (63 - 63)))))
+ .endif
+
+ or (\ra), D0, D1
+
+ .endif
+
+ .endm
+
+ // RLDIMI Extended Mnemonics
+ //
+ // Defined as if they were equivalent to PowerPC 32-bit extended
+ // mnemonics
+
+ .macro insldi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "INSLDI requires N > 0"
+ .endif
+ rldimi (\ra), (\rs), (64 - (\b)), (\b), ((\b) + (\n) - 1)
+ .endm
+
+ .macro insrdi, ra:req, rs:req, n:req, b:req
+ .if ((\n) < 0)
+ .error "INSRDI requires N > 0"
+ .endif
+ rldimi (\ra), (\rs), (64 - (\b) - (\n)), (\b), ((\b) + (\n) - 1)
+ .endm
+
+
+ //////////////////////////////////////////////////////////////////////
+ // .HOOK
+ //////////////////////////////////////////////////////////////////////
+
+ // The PoreVe (PORE Virtual Environment) is a PORE simulation
+ // environment that allows the programmer to embed C/C++ code into the
+ // PORE assembler source code, and arranges for the C/C++ code to be
+ // executed in-line with the PORE assembly code. Instances of the
+ // .hook macro are inserted into the assembler input by the
+ // hook_extractor script, to mark the locations where hooks are
+ // present. The hook reference is a string that combines the source
+ // file name with an index number to uniquely identify the hook.
+ //
+ // .hook <file name>_<sequence number>
+ //
+ // The .hook macro marks the location of each hook in the relocatable
+ // binaries with special symbols. The symbol name includes the hook
+ // reference, which is used to locate the hook in the HookManager
+ // symbol table. Because hooks can be defined in macros, a hook that
+ // appears once in a source file may appear multiple times in the
+ // final binary. For this reason each hook must also be tagged with a
+ // unique index number to avoid symbol name collisions. The
+ // complexity of the .hook macro is due to the necessity to decode a
+ // dynamic symbol value (_PGAS_HOOK_INDEX) into its binary string form
+ // to create the unique symbol name. The final hook symbol has the
+ // form:
+ //
+ // __hook__<unique>_<reference>
+ //
+ // where <unique> is a binary string. It is then straightforward to
+ // locate these symbols in the 'nm' output of the final link and
+ // create a map of final addresses to the hook routine to call (the
+ // <reference>) before executing the instruction at that address.
+ //
+ // Note: The maximum nesting depth of the recursive ..hook_helper
+ // macro is log2(index), and the assembler supports nesting of at
+ // least 32 which is much more than sufficient.
+
+ .set _PGAS_HOOK_INDEX, 0
+
+ .macro .hook, reference:req
+ .set _PGAS_HOOK_INDEX, (_PGAS_HOOK_INDEX + 1)
+ ..hook_helper _PGAS_HOOK_INDEX, "", \reference
+ .endm
+
+ .macro ..hook_helper, index, unique, reference
+ .ifeq \index
+ __hook__\unique\()_\reference\():
+ .elseif (\index % 2)
+ ..hook_helper (\index / 2), 1\unique, \reference
+ .else
+ ..hook_helper (\index / 2), 0\unique, \reference
+ .endif
+ .endm
+
+
+////////////////////////////////////////////////////////////////////////////
+// Help for Conversion from Old to New PGAS syntax
+////////////////////////////////////////////////////////////////////////////
+
+ .macro loadp, arg:vararg
+ .error "PGAS now implements 'lpcs' rather then 'loadp'"
+ .endm
+
+ .macro loadx, arg:vararg
+ .error "PGAS now implements 'la' rather than 'loadx'"
+ .endm
+
+#endif // __ASSEMBLER__
+
+#ifdef PGAS_PPC
+#include "pgas_ppc.h"
+#endif
+
+#endif // __PGAS_H__
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_bitmanip.H b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_bitmanip.H
new file mode 100644
index 000000000..b9ba60424
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_bitmanip.H
@@ -0,0 +1,526 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_bitmanip.H $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+#ifndef __PORE_BITMANIP_H
+#define __PORE_BITMANIP_H
+
+/// \file pore_bitmanip.H
+/// \brief Standard bit-manipulation macros (C and Assembler) for PORE code
+
+#ifdef __ASSEMBLER__
+#include "pgas.h"
+#endif
+
+#include "fapi_sbe_common.H"
+
+/// \defgroup be64_bits Bit manipulation for 64-bit Big-Endian values
+///
+/// \note These macros only work in the assembler context because we build our
+/// assemblers to do 64-bit arithmetic, which is required for PORE assembly.
+///
+/// @{
+
+/// Create a multi-bit mask of \a n bits starting at bit \a b
+#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b))
+
+/// Create a single bit mask at bit \a b
+#define BIT(b) BITS((b), 1)
+
+#ifdef __ASSEMBLER__
+
+/// Check b, n for legality
+
+ .macro ..checkbits, b:req, n=1
+ .if (((\b) < 0) || ((\b) > 63))
+ .error "Illegal bit number, must be 0,...,63"
+ .endif
+ .if (((\n) < 1) || ((\n) > 64))
+ .error "Illegal number of bits, must be 1,...,64"
+ .endif
+ .if (((\b) + (\n)) > 64)
+ .error "Illegal (b + n), must be <= 64"
+ .endif
+ .endm
+
+
+/// Set a single bit in a data register
+///
+/// \param[in,out] data A Data register (D0/D1), modified by setting bit \a b
+/// to 1.
+///
+/// \param[in] b The bit position (64-bit, big-endian) to set
+
+ .macro setbit, data:req, b:req
+ ..checkbits (\b)
+ ori (\data), (\data), BIT(\b)
+ .endm
+
+
+/// Set multiple contiguous bits in a data register
+///
+/// \param[in,out] data A Data register (D0/D1), modified by setting \a n bits
+/// starting at bit \a b to 1.
+///
+/// \param[in] b The bit position (64-bit, big-endian) to begin
+///
+/// \param[in] n The number of contiguous bits to set
+
+ .macro setbits, data:req, b:req, n:req
+ ..checkbits (\b), (\n)
+ ori (\data), (\data), BITS((\b), (\n))
+ .endm
+
+
+/// Read-modify-write a SCOM register by setting a bit
+///
+/// \param[in,out] data A Data register (D0/D1), first loaded with the value
+/// of the SCOM register, then modified by setting bit \a b to 1. The final
+/// value of \a data is then stored back to the SCOM register.
+///
+/// \param[in] address A 32-bit SCOM address
+///
+/// \param[in] prv A pervasive base register (P0/P1) which contains the
+/// chiplet ID + multicast bit to use with \a address
+///
+/// \param[in] b The bit position (64-bit, big-endian) to set
+
+ .macro setbitscom data:req, address:req, prv:req, b:req
+ ..checkbits (\b)
+ .if ((\data) == D0)
+ bsi D0, (\address), (\prv), BIT(\b)
+ .else
+ ld (\data), (\address), (\prv)
+ setbit (\data), (\b)
+ std (\data), (\address), (\prv)
+ .endif
+ .endm
+
+
+/// Read-modify-write a SCOM register by setting a range of contiguous bits
+///
+/// \param[in,out] data A Data register (D0/D1), first loaded with the value
+/// of the SCOM register, then modified by setting \a n bits starting at bit
+/// \a b to 1. The final value of \a data is then stored back to the SCOM
+/// register.
+///
+/// \param[in] address A 32-bit SCOM address
+///
+/// \param[in] prv A pervasive base register (P0/P1) which contains the
+/// chiplet ID + multicast bit to use with \a address
+///
+/// \param[in] b The bit position (64-bit, big-endian) to set
+///
+/// \param[in] n The number of contiguous bits to set
+
+ .macro setbitsscom data:req, address:req, prv:req, b:req, n:req
+ ..checkbits (\b), (\n)
+ .if ((\data) == D0)
+ bsi D0, (\address), (\prv), BITS((\b),(\n))
+ .else
+ ld (\data), (\address), (\prv)
+ setbits (\data), (\b), (\n)
+ std (\data), (\address), (\prv)
+ .endif
+ .endm
+
+/// Set any number of individual bits in a data register
+///
+/// \param[in] data The Data register (D0/D1) to modify
+///
+/// \param[in] ...bits 1 or more bit positions (64-bit, big-endian) to set
+///
+/// For example:
+///
+/// - setbitmult D0, 1, 3, 13
+///
+/// sets bits 1, 3 and 13 of D0.
+
+ .macro setbitmult, data:req, bits:vararg
+ ..setbitmult 0, (\data), \bits
+ .endm
+
+ // The best I can come up with to implement this macro currently is to
+ // use a special symbol to accumulate the bit masks. I don't know of a
+ // way to do this recursively.
+
+ .macro ..accumulate_bitmask, symbol:req, bits:vararg
+ .ifb \bits
+ .error "At least 1 bit position must be specified"
+ .endif
+ .set \symbol, 0
+ .irp b, \bits
+ .if (((\b) < 0) || ((\b) > 63))
+ .error "Illegal bit position, must be 0 <= b < 63"
+ .endif
+ .set \symbol, (BIT(\b) | \symbol)
+ .endr
+ .endm
+
+ .macro ..setbitmult, invert:req, data:req, bits:vararg
+ ..accumulate_bitmask __SETBITMULT__, \bits
+ .if (\invert)
+ andi (\data), (\data), ~__SETBITMULT__
+ .else
+ ori (\data), (\data), __SETBITMULT__
+ .endif
+ .endm
+
+
+/// Read-modify-write a SCOM register by setting any number of individual bits
+///
+/// \param[in,out] data A Data register (D0/D1), first loaded with the value
+/// of the SCOM register, then modified by setting any number (> 0) of
+/// individual bits.
+///
+/// \param[in] address A 32-bit SCOM address
+///
+/// \param[in] prv A pervasive base register (P0/P1) which contains the
+/// chiplet ID + multicast bit to use with \a address
+///
+/// \param[in] ...bits 1 or more bit positions (64-bit, big-endian) to set
+///
+/// For example:
+///
+/// - setbitmultscom D0, OCC_CONTROL_0x0006B000, P0, 1, 3, 13
+///
+/// sets bits 1, 3 and 13 of OCC_CONTROL.
+
+ .macro setbitmultscom, data:req, address:req, prv:req, bits:vararg
+ ..setbitmultscom 0, (\data), (\address), (\prv), \bits
+ .endm
+
+ .macro ..setbitmultscom, \
+ invert:req, data:req, address:req, prv:req, bits:vararg
+ ..accumulate_bitmask __SETBITMULTSCOM__, \bits
+ .if ((\data) == D0)
+
+ .if (\invert)
+ bci D0, (\address), (\prv), __SETBITMULTSCOM__
+ .else
+ bsi D0, (\address), (\prv), __SETBITMULTSCOM__
+ .endif
+
+ .else
+
+ .if (\invert)
+ ldandi (\data), (\address), (\prv), ~__SETBITMULTSCOM__
+ .else
+ ld (\data), (\address), (\prv)
+ ori (\data), (\data), __SETBITMULTSCOM__
+ .endif
+ std (\data), (\address), (\prv)
+
+ .endif
+ .endm
+
+
+/// Clear a single bit in a data register
+///
+/// This macro is the bit-clearing analogue of the \c setbit macro
+
+ .macro clrbit, data:req, b:req
+ ..checkbits (\b)
+ andi (\data), (\data), ~BIT(\b)
+ .endm
+
+
+/// Clear multiple contiguous bits in a data register
+///
+/// This macro is the bit-clearing analogue of the \c setbits macro
+
+
+ .macro clrbits, data:req, b:req, n:req
+ ..checkbits (\b), (\n)
+ andi (\data), (\data), ~BITS((\b), (\n))
+ .endm
+
+
+/// Read-modify-write a SCOM register by clearing a bit
+///
+/// This macro is the bit-clearing analogue of the \c setbitscom macro
+
+ .macro clrbitscom data:req, address:req, prv:req, b:req
+ ..checkbits (\b)
+ .if ((\data) == D0)
+ bci D0, (\address), (\prv), BIT(\b)
+ .else
+ ld (\data), (\address), (\prv)
+ clrbit (\data), (\b)
+ std (\data), (\address), (\prv)
+ .endif
+ .endm
+
+
+/// Read-modify-write a SCOM register by clearing a range of contiguous bits
+///
+/// This macro is the bit-clearing analogue of the \c setbitsscom macro
+
+ .macro clrbitsscom, data:req, address:req, prv:req, b:req, n:req
+ ..checkbits (\b), (\n)
+ .if ((\data) == D0)
+ bci D0, (\address), (\prv), BITS((\b), (\n))
+ .else
+ ld (\data), (\address), (\prv)
+ clrbits (\data), (\b), (\n)
+ std (\data), (\address), (\prv)
+ .endif
+ .endm
+
+
+/// Clear any number of individual bits in a data register
+///
+/// This macro is the bit-clearing analogue of the \c setbitmult macro
+
+ .macro clrbitmult, data:req, bits:vararg
+ ..setbitmult 1, (\data), \bits
+ .endm
+
+
+/// Read-modify-write a SCOM register by clearing any number of individual bits
+///
+/// This macro is the bit-clearing analogue of the \c setbitmultscom macro
+
+ .macro clrbitmultscom, data:req, address:req, prv:req, bits:vararg
+ ..setbitmultscom 1, (\data), (\address), (\prv), \bits
+ .endm
+
+
+/// Extract and right-justify an unsigned bit field
+///
+/// \param[out] dest The destination Data register (D0/D1) to receive the
+/// right-justified unsigned bit field.
+///
+/// \param[in] src The source Data register (D0/D1) that contains the unsigned
+/// bit field to extract.
+///
+/// \param[in] b The bit positon (64-bit, big-endian) where the bit field
+/// begins.
+///
+/// \param[in] n The number of contiguous bits beginning at bit \a b to
+/// extract.
+///
+/// The execution of this macro computes:
+///
+/// - dest[64-n:63] <- src[b:b+n-1]
+/// - dest[0:64-n] <- 0
+///
+/// Note that the \a dest and \a src registers may be the same Data register.
+
+ .macro extractbits, dest:req, src:req, b:req, n:req
+ ..checkbits (\b), (\n)
+ extrdi (\dest), (\src), (\n), (\b)
+ .endm
+
+
+/// Destructively insert a right-justified immediate value into a bit field
+///
+/// \param[out] dest The destination Data register (D0/D1) to be modified.
+///
+/// \param[in] b The bit positon (64-bit, big-endian) where the bit field
+/// begins.
+///
+/// \param[in] n The number of contiguous bits beginning at bit \a b to
+/// modify
+///
+/// The execution of this macro computes:
+///
+/// - dest <- (dest & ~BITS(b, n)) | ((imm & BITS(64 - n, n)) << (64 - n - b))
+
+ .macro insertbits, dest:req, b:req, n:req, imm:req
+ ..checkbits (\b), (\n)
+ andi (\dest), (\dest), ~BITS((\b), (\n))
+ ori (\dest), (\dest), \
+ (((\imm) & BITS(64 - (\n), (\n))) << ((64 - (\n) - (\b))))
+ .endm
+
+
+/// Poll for a bit to be set in a SCOM register with timeout
+///
+/// \param[in] dest A Data register (D0/D1) to use for the polling
+///
+/// \param[in] address A 32-bit SCOM address
+///
+/// \param[in] prv A Pervasive Chiplet Id register (P0/P1) containing the
+/// chiplet ID and multicast bit to use with the \a address
+///
+/// \param[in] b The bit number of the bit to poll
+///
+/// \param[in] count The number (count > 0) of times to poll for the bit. If
+/// the bit is not set the \a count-th time the SCOM is read then the error
+/// action occurs (see below). The maximum legal value is 0x1000000.
+///
+/// \param[in] delay The number of PORE clock cycles (delay >= 0) to wait
+/// between polls of the SCOM register. Specify a delay of 0 to avoid waiting
+/// between polls. There is no waiting before the first poll, therefore the
+/// WAIT is only executed \a count - 1 times in the worst case. The maximum
+/// legal value is 0xffffff. The PORE engines run at nest / 4 normally, but at
+/// the reference frequency during the early IPL.
+///
+/// \param[in] error A branch target (symbol) in the event of error (see
+/// below).
+///
+/// This macro polls a SCOM register for a single set bit with a programmable
+/// timeout, branching to an error handler in the event of a timeout. This
+/// macro always uses the \c CTR register for the poll count. Therefore if
+/// the CTR is currently in use the caller will need to save the current
+/// contents of CTR to another register prior to invoking this macro.
+///
+/// In the event of a polling timeout the code will branch to the \a
+/// error target. Prior to the branch, the \a dest register will be loaded
+/// with the PC to help diagnose the error.
+
+ .macro pollbitset, dest:req, address:req, prv:req, b:req \
+ count:req, delay:req, error:req
+ ..pollbit branz, (\dest), (\address), (\prv), (\b), \
+ (\count), (\delay), (\error)
+ .endm
+
+
+/// Poll for a bit to be clear in a SCOM register with timeout
+///
+/// This macro is analogous to the pollbitset macro
+
+ .macro pollbitclr, dest:req, address:req, prv:req, b:req \
+ count:req, delay:req, error:req
+ ..pollbit braz, (\dest), (\address), (\prv), (\b), \
+ (\count), (\delay), (\error)
+ .endm
+
+
+// Implements pollbitset and pollbitclr - the only difference is 'branz' vs
+// 'braz'.
+
+ .macro ..pollbit, instr:req, dest:req, address:req, prv:req, b:req \
+ count:req, delay:req, error:req
+
+ .if (((\count) <= 0) || ((\count) > 0x1000000))
+ .error "The poll count must satisfy 0 < count <= 0x1000000"
+ .endif
+ .if (((\delay) < 0) || ((\delay) >= 0x1000000))
+ .error "The wait delay must satisfy 0 <= delay < 0x1000000"
+ .endif
+
+ ls CTR, ((\count) - 1)
+ bra 7665249f
+7665248:
+ .if ((\delay) != 0)
+ waits (\delay)
+ .endif
+7665249:
+ ldandi (\dest), (\address), (\prv), BIT(\b)
+ \instr (\dest), 7665250f
+ loop 7665248b
+ mr (\dest), PC
+ braa (\error)
+7665250:
+
+ .endm
+
+
+/// Test and branch if a bit is set in a data register
+///
+/// \param[out] scratch This Data register (D0/D1) is destroyed to perform the
+/// comparison. This may be the same as the \a data register if the \a data is
+/// no longer needed after the comparison.
+///
+/// \param[in] data This Data register (D0/D1) contains the data to be tested.
+///
+/// \param[in] b The bit number (64-bit, big-endian) to test
+///
+/// \param[in] target The branch target in the event that bit \a b is set in
+/// \a data.
+
+ .macro ifbitset, scratch:req, data:req, b:req, target:req
+ ..checkbits (\b)
+ andi (\scratch), (\data), BIT(\b)
+ branz (\scratch), (\target)
+ .endm
+
+
+/// Test and branch is a bit is clear in a data register
+///
+/// This macro is the bit-clear-test analogue of the ifbitset macro
+
+ .macro ifbitclr, scratch:req, data:req, b:req, target:req
+ ..checkbits (\b)
+ andi (\scratch), (\data), BIT(\b)
+ braz (\scratch), (\target)
+ .endm
+
+
+/// Read a SCOM register and branch if a bit is set
+///
+/// \param[out] scratch This Data register (D0/D1) is destroyed to perform the
+/// comparison. This may be the same as the \a data register if the \a data is
+/// no longer needed after the comparison.
+///
+/// \param[in] data This Data register (D0/D1) is first loaded from the SCOM
+/// \a address, then tested for the bit being set. If \a scratch and \a data
+/// are different register then this register will hold the original SCOM data
+/// after the execution of the macro.
+///
+/// \param[in] address A 32-bit SCOM address
+///
+/// \param[in] prv A Pervasive Chiplet Id register (P0/P1) containing the
+/// chiplet ID and multicast bit to use with the \a address
+///
+/// \param[in] b The bit number (64-bit, big-endian) to test
+///
+/// \param[in] target The branch target in the event that bit \a b is set in
+/// \a data.
+
+ .macro ifbitsetscom, scratch:req, data:req, address:req, prv:req, \
+ b:req, target:req
+ ..checkbits (\b)
+ .if ((\scratch) == (\data))
+ ldandi (\scratch), (\address), (\prv), BIT(\b)
+ .else
+ ld (\data), (\address), (\prv)
+ andi (\scratch), (\data), BIT(\b)
+ .endif
+ branz (\scratch), (\target)
+ .endm
+
+
+/// Read a SCOM register and branch if a bit is clear
+///
+/// This is the bit-clear-test analogue of the ifbitsetscom macro
+
+ .macro ifbitclrscom, scratch:req, data:req, address:req, prv:req, \
+ b:req, target:req
+ ..checkbits (\b)
+ .if ((\scratch) == (\data))
+ ldandi (\scratch), (\address), (\prv), BIT(\b)
+ .else
+ ld (\data), (\address), (\prv)
+ andi (\scratch), (\data), BIT(\b)
+ .endif
+ braz (\scratch), (\target)
+ .endm
+
+
+/// @}
+
+#endif // __ASSEMBLER__
+
+#endif // __PORE_BITMANIP_H
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline.h
new file mode 100644
index 000000000..a8436d69f
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline.h
@@ -0,0 +1,814 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+#ifndef __PORE_INLINE_H__
+#define __PORE_INLINE_H__
+
+// $Id: pore_inline.h,v 1.15 2012/05/23 19:03:42 bcbrock Exp $
+
+// ** WARNING : This file is maintained as part of the OCC firmware. Do **
+// ** not edit this file in the PMX area or the hardware procedure area **
+// ** as any changes will be lost. **
+
+/// \file pore_inline.h
+/// \brief Inline assembler for PORE code
+///
+/// Note that this file defines several short macro symbols for register names
+/// and other mnemonics used by inline assembly. For this reason it would
+/// probably be best to only include this header when it was absolutely
+/// necessary, i.e., only in C files that explicitly use inline assembly and
+/// disassembly.
+
+#include <ctype.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "pgas.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+} /* So __cplusplus doesn't mess w/auto-indent */
+#endif
+
+
+#ifndef __ASSEMBLER__
+
+/// Error code strings from the PORE inline assembler/disassembler
+///
+/// The PoreInlineContext object stores error codes that occur during
+/// assembly as small integers. The '0' code indicates success. This is a
+/// table of strings that describe the codes. It will be instantiated in
+/// pore_inline.c
+
+extern const char *pore_inline_error_strings[];
+
+#ifdef __PORE_INLINE_ASSEMBLER_C__
+const char *pore_inline_error_strings[] = {
+ "No error",
+ "The inline assembler memory is full, or disassembly has reached the end of the memory area",
+ "The instruction requires an ImD24 operand",
+ "The LC is not aligned or the instruction requires an aligned operand",
+ "The branch target is unreachable (too distant)",
+ "A register operand is illegal for the given instruction",
+ "The instruction form requires a signed 16-bit immediate",
+ "Valid rotate lengths are 1, 4, 8, 16 and 32",
+ "The instruction requires a 20-bit signed immediate",
+ "The instruction requires a 24-bit unsigned immediate",
+ "A parameter to pore_inline_context_create() is invalid",
+ "The instruction form requires an unsigned 22-bit immediate",
+ "This error is due to a bug in the PORE inline assembler (Please report)",
+ "The 'source' label for pore_inline_branch_fixup() is illegal",
+ "The 'source' instruction for pore_inline_branch_fixup() is not a branch",
+ "The disassembler does not recognize the instruction as a PORE opcode",
+ "Instruction parity error during disassembly",
+ "The string form of the disassembly is too long to represent (Please report)`",
+ "Use HALT instead of WAIT 0 if the intention is to halt.",
+ "A putative SCOM address is illegal (has non-0 bits where 0s are expected)."
+};
+#endif /* __PORE_INLINE_ASSEMBLER_C__ */
+
+#endif /* __ASSEMBLER__ */
+
+#define PORE_INLINE_SUCCESS 0
+#define PORE_INLINE_NO_MEMORY 1
+#define PORE_INLINE_IMD24_ERROR 2
+#define PORE_INLINE_ALIGNMENT_ERROR 3
+#define PORE_INLINE_UNREACHABLE_TARGET 4
+#define PORE_INLINE_ILLEGAL_REGISTER 5
+#define PORE_INLINE_INT16_REQUIRED 6
+#define PORE_INLINE_ILLEGAL_ROTATE 7
+#define PORE_INLINE_INT20_REQUIRED 8
+#define PORE_INLINE_UINT24_REQUIRED 9
+#define PORE_INLINE_INVALID_PARAMETER 10
+#define PORE_INLINE_UINT22_REQUIRED 11
+#define PORE_INLINE_BUG 12
+#define PORE_INLINE_ILLEGAL_SOURCE_LC 13
+#define PORE_INLINE_NOT_A_BRANCH 14
+#define PORE_INLINE_UNKNOWN_OPCODE 15
+#define PORE_INLINE_PARITY_ERROR 16
+#define PORE_INLINE_DISASSEMBLY_OVERFLOW 17
+#define PORE_INLINE_USE_HALT 18
+#define PORE_INLINE_ILLEGAL_SCOM_ADDRESS 19
+
+
+/// Register name strings for the PORE inline assembler/disassembler
+
+extern const char *pore_inline_register_strings[16];
+
+// C++ requires that these arrays of strings be declared 'const' to avoid
+// warnings. But then you get warnings when the strings get stored into
+// non-const variables. The solution is to rename these arrays inside the
+// disassembler. If anyone has a better solution please let me know - Bishop
+
+#ifdef __PORE_INLINE_ASSEMBLER_C__
+const char* pore_inline_register_strings[16] = {
+ "P0", "P1", "A0", "A1", "CTR", "D0", "D1", "EMR",
+ "?", "ETR", "SPRG0", "?", "?", "?", "PC", "IFR"
+};
+#endif /* __PORE_INLINE_ASSEMBLER_C__ */
+
+
+// Shorthand forms of constants defined in pgas.h, defined for consistency
+// using the assembler-supported names. These constants are defined as an
+// enum to avoid name conflicts with some firmware symbols when the PORE
+// inline facility is used to create Host Boot procedures.
+
+enum {
+
+ // Shorthand register mnemonics, defined as an enum to avoid name clashes.
+
+ P0 = PORE_REGISTER_PRV_BASE_ADDR0,
+ P1 = PORE_REGISTER_PRV_BASE_ADDR1,
+ A0 = PORE_REGISTER_OCI_BASE_ADDR0,
+ A1 = PORE_REGISTER_OCI_BASE_ADDR1,
+ CTR = PORE_REGISTER_SCRATCH0,
+ D0 = PORE_REGISTER_SCRATCH1,
+ D1 = PORE_REGISTER_SCRATCH2,
+ EMR = PORE_REGISTER_ERROR_MASK,
+ ETR = PORE_REGISTER_EXE_TRIGGER,
+ SPRG0 = PORE_REGISTER_DATA0,
+ PC = PORE_REGISTER_PC,
+ IFR = PORE_REGISTER_IBUF_ID,
+
+ // PgP IBUF_ID values
+
+ PORE_GPE0 = PORE_ID_GPE0,
+ PORE_GPE1 = PORE_ID_GPE1,
+ PORE_SLW = PORE_ID_SLW,
+ PORE_SBE = PORE_ID_SBE,
+
+ // Condition Codes
+
+ CC_UGT = PORE_CC_UGT,
+ CC_ULT = PORE_CC_ULT,
+ CC_SGT = PORE_CC_SGT,
+ CC_SLT = PORE_CC_SLT,
+ CC_C = PORE_CC_C,
+ CC_V = PORE_CC_V,
+ CC_N = PORE_CC_N,
+ CC_Z = PORE_CC_Z,
+};
+
+// Pseudo-opcodes for LD/LDANDI/STD
+
+#define PORE_INLINE_PSEUDO_LD 0
+#define PORE_INLINE_PSEUDO_LDANDI 1
+#define PORE_INLINE_PSEUDO_STD 2
+
+
+// Private version of _BIG_ENDIAN
+
+#ifndef _BIG_ENDIAN
+#define PORE_BIG_ENDIAN 0
+#else
+#define PORE_BIG_ENDIAN _BIG_ENDIAN
+#endif
+
+
+/// Maximum size of disassembly strings
+///
+/// This is currently sufficient for PORE_INLINE_LISTING_MODE. We don't want
+/// to make this too long since the PoreInlineDisassembly object may be on the
+/// stack in embedded applications.
+#define PORE_INLINE_DISASSEMBLER_STRING_SIZE 128
+
+
+/// Generate PORE instruction parity
+///
+/// This flag is an option to pore_inline_context_create(). If set, PORE
+/// inline assembly sets the instruction parity bit for each assembled
+/// instruction; otherwise the instruction parity bit is always 0.
+#define PORE_INLINE_GENERATE_PARITY 0x01
+
+/// Check PORE instruction parity
+///
+/// This flag is an option to pore_inline_context_create(). If set, PORE
+/// inline disassembly checks the instruction parity bit for each disassembled
+/// instruction, failing with PORE_INLINE_PARITY_ERROR if the parify is not
+/// correct. Otherwise the instruction parity bit is ignored during
+/// disassembly.
+#define PORE_INLINE_CHECK_PARITY 0x02
+
+/// Disassemble in listing mode
+///
+/// This flag is an option to pore_inline_context_create(). If set, then
+/// generate disassembly strings in the form of a listing that contains
+/// location counters and encoded instructions as well as their diassembly.
+/// By default the disassembly strings do not contain this information and can
+/// be fed back in as source code to a PORE assembler.
+#define PORE_INLINE_LISTING_MODE 0x04
+
+/// Disassemble in data mode
+///
+/// This flag is an option to pore_inline_context_create(). If set, then
+/// generate disassembly assuming that the context contains data rather than
+/// text. Normally data is disassembled as .long directives, however if the
+/// context is unaligned or of an odd length then .byte directives may be used
+/// as well. This option can be used in conjunction with
+/// PORE_INLINE_LISTING_MODE and PORE_INLINE_8_BYTE_DATA.
+///
+/// Note: An intelligent application can switch between the default text
+/// disassembly and data disassembly by manipulating the \a options field of
+/// the PoreInlineContext between calls of pore_inline_disassemble().
+#define PORE_INLINE_DISASSEMBLE_DATA 0x08
+
+/// Disassemble data in 8-byte format
+///
+/// This flag is an option to pore_inline_context_create(). If set, then if
+/// PORE_INLINE_DISASSEMBLE_DATA is also set then generate data disassembly as
+/// 8-byte values rather then the default 4-byte values. Normally data is
+/// disassembled as .quad directives under this option, however if the context
+/// is unaligned or of an odd length then .long and .byte directives may be
+/// used as well. This option can be used in conjunction with
+/// PORE_INLINE_LISTING_MODE.
+///
+/// Note: An intelligent application can switch between the default text
+/// disassembly and data disassembly by manipulating the \a options field of
+/// the PoreInlineContext between calls of pore_inline_disassemble().
+#define PORE_INLINE_8_BYTE_DATA 0x10
+
+
+#ifndef __ASSEMBLER__
+
+/// The type of location counters for the PORE inline assembler
+
+typedef uint32_t PoreInlineLocation;
+
+/// PORE inline assembler context
+///
+/// See the documentation page \ref pore_inline_assembler and the function
+/// pore_inline_context_create() for futher details.
+
+typedef struct {
+
+ /// The memory area to receive the inline assembly
+ ///
+ /// This field is never modified, allowing the *reset* APIs to function.
+ ///
+ /// Note: C++ does not allow arithmetic on void* objects, so we use the
+ /// Linux convention of storing memory addresses as type 'unsigned long'.
+ unsigned long memory;
+
+ /// The original size of the memory area to receive the inline assembly
+ ///
+ /// This field is never modified, allowing the *reset* APIs to function.
+ size_t size;
+
+ /// The original Location Counter (associated with \a memory)
+ ///
+ /// This field is never modified, allowing the *reset* APIs to function.
+ PoreInlineLocation original_lc;
+
+ /// The memory address associated with the current LC
+ ///
+ /// Note: C++ does not allow arithmetic on void* objects, so we use the
+ /// Linux convention of storing memory addresses as type 'unsigned long'.
+ unsigned long lc_address;
+
+ /// The remaining size of the memory area to receive the inline assembly
+ size_t remaining;
+
+ /// The bytewise Location Counter of the assembled code
+ PoreInlineLocation lc;
+
+ /// Inline assembly options
+ ///
+ /// This field is never modified, allowing the *reset* APIs to function.
+ int options;
+
+ /// The last error code generated by the inline assembler
+ int error;
+
+} PoreInlineContext;
+
+
+/// PORE inline disassembler result
+///
+/// This object holds the disassembly produced by pore_inline_disassemble().
+/// See documentation for that function for complete details.
+
+typedef struct {
+
+ /// The context as it existed when the instruction was assembled
+ ///
+ /// Disassembling an instruction modifies the context provided to
+ /// pore_inline_disassemble() to point to the next instruction. This
+ /// structure stores a copy of the context at the initial call of
+ /// pore_inline_disassemble(), that is, the context in effect when the
+ /// dissassembled instruction was assembled.
+ PoreInlineContext ctx;
+
+ /// The first 32 bits of every instruction
+ uint32_t instruction;
+
+ /// The opcode; bits 0..6 of the instruction
+ int opcode;
+
+ /// A flag - If set the opcode is for a 12-byte instruction
+ int long_instruction;
+
+ /// The parity bit; bit 7 of the instruction
+ int parity;
+
+ /// The register specifier at bits 8..11 of the instruction
+ ///
+ /// This register is sometimes called the source, sometimes the target,
+ /// depending on the opcode.
+ int r0;
+
+ /// The register specifier at bits 12..15 of the instruction
+ ///
+ /// This register is always called the 'source' but is named generically
+ /// here since sometimes the specifier at bits 8..11 is also called a
+ /// 'source'.
+ int r1;
+
+ /// 'ImD16' is the signed 16-bit immediate for short immediate adds and
+ /// subtracts. For the rotate instruction this field also contains the
+ /// rotate count which is either 1, 4, 8, 16 or 32.
+ int16_t imd16;
+
+ /// 'ImD20' is the 20-bit signed immediate for the LOAD20 instruction
+ int32_t imd20;
+
+ /// 'ImD24' is the 24-bit unsigned immediate for the WAIT instruction
+ uint32_t imd24;
+
+ /// 'ImD64' is the 64-bit immediate for data immediates and BRAI. This
+ /// field is only set for 3-word instructions.
+ uint64_t imd64;
+
+ /// 'ImPCO20' is a signed, 20-bit word offset for branch instructions
+ int32_t impco20;
+
+ /// 'ImPCO24' is a signed, 24-bit word offset for branch instructions
+ int32_t impco24;
+
+ /// For imA24 opcodes, this indicates memory/pib (1/0) addressing..
+ int memory_space;
+
+ /// This is the base register specifier - either a memory (OCI) base
+ /// register or a pervasive base register - for Read/Write operations.
+ /// Note that this is a PORE register index, not simply 0/1.
+ int base_register;
+
+ /// This is the 22-bit signed offset for memory (OCI) addressing. This
+ /// unsigned offset is added to a memory base register (A0/A1) to form the
+ /// final 32-bit address.
+ uint32_t memory_offset;
+
+ /// This field contains the port number and local address portions of the
+ /// PIB/PCB address for load/store operations that target the PIB/PCB.
+ /// Note that bits 0..11 will always be 0 in this address. Bits 1..7 (the
+ /// multicast bit and chiplet id) are sourced from the associated
+ /// pervasive base register when the instruction executes.
+ uint32_t pib_offset;
+
+ /// The update bit of the SCAND instruction
+ int update;
+
+ /// The capture bit of the SCAND instruction
+ int capture;
+
+ /// The scan length from a SCAND instruction
+ int scan_length;
+
+ /// The scan select from a SCAND instruction
+ uint32_t scan_select;
+
+ /// The address offset from a SCAND instruction
+ uint32_t scan_offset;
+
+ /// The string form of the disassembly.
+ ///
+ /// The disassembly string is \e not terminated by a newline. In listing
+ /// mode the disassembly string \e will contain embedded newlines for long
+ /// instructions.
+ char s[PORE_INLINE_DISASSEMBLER_STRING_SIZE];
+
+ /// The data (for data disassembly)
+ ///
+ /// This is either 1 or 8 bytes in host byte order.
+ uint64_t data;
+
+ /// The size of the disassembled \a data field (for data disassembly)
+ size_t data_size;
+
+} PoreInlineDisassembly;
+
+
+// These are internal APIs - they are not needed by application code.
+
+void
+pore_inline_be32(unsigned long p, uint32_t x);
+
+void
+pore_inline_be64(unsigned long p, uint64_t x);
+
+uint32_t
+pore_inline_host32(unsigned long p);
+
+uint64_t
+pore_inline_host64(unsigned long p);
+
+int
+pore_inline_parity(uint32_t instruction, uint64_t imd64);
+
+void
+pore_inline_context_bump(PoreInlineContext *ctx, size_t bytes);
+
+int
+pore_inline_instruction1(PoreInlineContext *ctx, int opcode, uint32_t operand);
+
+int
+pore_inline_instruction3(PoreInlineContext *ctx, int opcode, uint32_t operand,
+ uint64_t imm);
+
+int
+pore_inline_bra(PoreInlineContext *ctx,
+ int opcode, PoreInlineLocation target);
+
+int
+pore_inline_brac(PoreInlineContext *ctx,
+ int opcode, int reg, PoreInlineLocation target);
+
+int
+pore_inline_cmpibra(PoreInlineContext *ctx,
+ int opcode, int reg,
+ PoreInlineLocation target, uint64_t imm);
+
+int
+pore_inline_brad(PoreInlineContext *ctx, int opcode, int reg);
+
+int
+pore_inline_ilogic(PoreInlineContext *ctx,
+ int opcode, int dest, int src, uint64_t imm);
+int
+pore_inline_alurr(PoreInlineContext *ctx,
+ int opcode, int dest, int src1, int src2);
+
+int
+pore_inline_adds(PoreInlineContext *ctx,
+ int opcode, int dest, int src, int imm);
+
+int
+pore_inline_load_store(PoreInlineContext *ctx,
+ int opcode, int src_dest, int32_t offset, int base,
+ uint64_t imm);
+
+
+// These are utility APIs that may be required by special-purpose code that
+// uses the pore_inline library.
+
+void
+pore_inline_decode_instruction(PoreInlineDisassembly* dis,
+ uint32_t instruction);
+
+void
+pore_inline_decode_imd64(PoreInlineDisassembly* dis, uint64_t imd64);
+
+
+// These are the inline PORE instructions, extended mnemonics and pseudo-ops
+// to be used by application code.
+
+/// Set a location counter variable from a context
+///
+/// This is a macro that sets the \a var (of type PoreInlineLocation) to the
+/// current location counter of the \a ctx. The macro produces an expression
+/// that evaluates to 0 so that it can be used in the logical-OR expressions
+/// used to define inline assembly sequences.
+
+#define PORE_LOCATION(ctx, var) (((var) = (ctx)->lc), 0)
+
+int
+pore_inline_context_create(PoreInlineContext *context,
+ void *memory,
+ size_t size,
+ PoreInlineLocation lc,
+ int options);
+
+void
+pore_inline_context_reset(PoreInlineContext *context);
+
+void
+pore_inline_context_reset_excursion(PoreInlineContext *context);
+
+void
+pore_inline_context_copy(PoreInlineContext *dest, PoreInlineContext *src);
+
+
+int
+pore_inline_branch_fixup(PoreInlineContext *ctx,
+ PoreInlineLocation source,
+ PoreInlineLocation target);
+
+
+int
+pore_inline_disassemble(PoreInlineContext *ctx, PoreInlineDisassembly *dis);
+
+
+// Native PORE instruction assembly, using PGAS opcode names and operand
+// ordering rules.
+
+// NOP, TRAP, RET
+
+static inline int
+pore_NOP(PoreInlineContext *ctx)
+{
+ return pore_inline_instruction1(ctx, PGAS_OPCODE_NOP, 0);
+}
+
+
+static inline int
+pore_TRAP(PoreInlineContext *ctx)
+{
+ return pore_inline_instruction1(ctx, PGAS_OPCODE_TRAP, 0);
+}
+
+
+static inline int
+pore_RET(PoreInlineContext *ctx)
+{
+ return pore_inline_instruction1(ctx, PGAS_OPCODE_RET, 0);
+}
+
+
+// WAITS, HALT, HOOKI
+
+int
+pore_WAITS(PoreInlineContext *ctx, uint32_t cycles);
+
+static inline int
+pore_HALT(PoreInlineContext *ctx)
+{
+ return pore_inline_instruction1(ctx, PGAS_OPCODE_WAITS, 0);
+}
+
+int
+pore_HOOKI(PoreInlineContext *ctx, uint32_t index, uint64_t imm);
+
+
+// BRA, BSR, LOOP
+
+static inline int
+pore_BRA(PoreInlineContext *ctx, PoreInlineLocation target)
+{
+ return pore_inline_bra(ctx, PGAS_OPCODE_BRA, target);
+}
+
+static inline int
+pore_BSR(PoreInlineContext *ctx, PoreInlineLocation target)
+{
+ return pore_inline_bra(ctx, PGAS_OPCODE_BSR, target);
+}
+
+static inline int
+pore_LOOP(PoreInlineContext *ctx, PoreInlineLocation target)
+{
+ return pore_inline_bra(ctx, PGAS_OPCODE_LOOP, target);
+}
+
+
+// BRAZ, BRANZ
+
+static inline int
+pore_BRAZ(PoreInlineContext *ctx, int reg, PoreInlineLocation target)
+{
+ return pore_inline_brac(ctx, PGAS_OPCODE_BRAZ, reg, target);
+}
+
+
+static inline int
+pore_BRANZ(PoreInlineContext *ctx, int reg, PoreInlineLocation target)
+{
+ return pore_inline_brac(ctx, PGAS_OPCODE_BRANZ, reg, target);
+}
+
+
+// CMPIBRAEQ, CMPIBRANE, CMPIBSREQ
+
+static inline int
+pore_CMPIBRAEQ(PoreInlineContext *ctx,
+ int reg, PoreInlineLocation target, uint64_t imm)
+{
+ return pore_inline_cmpibra(ctx, PGAS_OPCODE_CMPIBRAEQ, reg, target, imm);
+}
+
+
+static inline int
+pore_CMPIBRANE(PoreInlineContext *ctx,
+ int reg, PoreInlineLocation target, uint64_t imm)
+{
+ return pore_inline_cmpibra(ctx, PGAS_OPCODE_CMPIBRANE, reg, target, imm);
+}
+
+
+static inline int
+pore_CMPIBSREQ(PoreInlineContext *ctx,
+ int reg, PoreInlineLocation target, uint64_t imm)
+{
+ return pore_inline_cmpibra(ctx, PGAS_OPCODE_CMPIBSREQ, reg, target, imm);
+}
+
+
+// BRAD, BSRD
+
+static inline int
+pore_BRAD(PoreInlineContext *ctx, int reg) {
+ return pore_inline_brad(ctx, PGAS_OPCODE_BRAD, reg);
+}
+
+static inline int
+pore_BSRD(PoreInlineContext *ctx, int reg) {
+ return pore_inline_brad(ctx, PGAS_OPCODE_BSRD, reg);
+}
+
+
+// ANDI, ORI, XORI
+
+static inline int
+pore_ANDI(PoreInlineContext *ctx, int dest, int src, uint64_t imm)
+{
+ return pore_inline_ilogic(ctx, PGAS_OPCODE_ANDI, dest, src, imm);
+}
+
+static inline int
+pore_ORI(PoreInlineContext *ctx, int dest, int src, uint64_t imm)
+{
+ return pore_inline_ilogic(ctx, PGAS_OPCODE_ORI, dest, src, imm);
+}
+
+static inline int
+pore_XORI(PoreInlineContext *ctx, int dest, int src, uint64_t imm)
+{
+ return pore_inline_ilogic(ctx, PGAS_OPCODE_XORI, dest, src, imm);
+}
+
+
+// AND, OR, XOR, ADD, SUB
+
+static inline int
+pore_AND(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_AND, dest, src1, src2);
+}
+
+static inline int
+pore_OR(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_OR, dest, src1, src2);
+}
+
+static inline int
+pore_XOR(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_XOR, dest, src1, src2);
+}
+
+static inline int
+pore_ADD(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_ADD, dest, src1, src2);
+}
+
+static inline int
+pore_SUB(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_SUB, dest, src1, src2);
+}
+
+
+// ADDS, SUBS
+
+static inline int
+pore_ADDS(PoreInlineContext *ctx, int dest, int src, int imm)
+{
+ return pore_inline_adds(ctx, PGAS_OPCODE_ADDS, dest, src, imm);
+}
+
+static inline int
+pore_SUBS(PoreInlineContext *ctx, int dest, int src, int imm)
+{
+ return pore_inline_adds(ctx, PGAS_OPCODE_SUBS, dest, src, imm);
+}
+
+
+// NEG, MR, ROLS, LS, LI
+
+int
+pore_NEG(PoreInlineContext *ctx, int dest, int src);
+
+int
+pore_MR(PoreInlineContext *ctx, int dest, int src);
+
+int
+pore_ROLS(PoreInlineContext *ctx, int dest, int src, int imm);
+
+int
+pore_LS(PoreInlineContext *ctx, int dest, int imm);
+
+int
+pore_LI(PoreInlineContext *ctx, int dest, uint64_t imm);
+
+
+// LD, LDANDI, STD, STI, BSI, BCI
+
+static inline int
+pore_LD(PoreInlineContext *ctx, int dest, int32_t offset, int base)
+{
+ return
+ pore_inline_load_store(ctx,
+ PORE_INLINE_PSEUDO_LD, dest, offset, base, 0);
+}
+
+static inline int
+pore_LDANDI(PoreInlineContext *ctx,
+ int dest, int32_t offset, int base, uint64_t imm)
+{
+ return
+ pore_inline_load_store(ctx,
+ PORE_INLINE_PSEUDO_LDANDI,
+ dest, offset, base, imm);
+}
+
+static inline int
+pore_STD(PoreInlineContext *ctx, int src, int32_t offset, int base)
+{
+ return
+ pore_inline_load_store(ctx,
+ PORE_INLINE_PSEUDO_STD, src, offset, base, 0);
+}
+
+static inline int
+pore_STI(PoreInlineContext *ctx, int32_t offset, int base, uint64_t imm)
+{
+ return
+ pore_inline_load_store(ctx,
+ PGAS_OPCODE_STI, 0, offset, base, imm);
+}
+
+static inline int
+pore_BSI(PoreInlineContext *ctx,
+ int src, int32_t offset, int base, uint64_t imm)
+{
+ return
+ pore_inline_load_store(ctx,
+ PGAS_OPCODE_BSI, src, offset, base, imm);
+}
+
+static inline int
+pore_BCI(PoreInlineContext *ctx,
+ int src, int32_t offset, int base, uint64_t imm)
+{
+ return
+ pore_inline_load_store(ctx,
+ PGAS_OPCODE_BCI, src, offset, base, imm);
+}
+
+
+// BRAIA
+
+int
+pore_BRAIA(PoreInlineContext *ctx,
+ uint16_t address_space, uint32_t offset);
+
+
+// SCAND
+
+int
+pore_SCAND(PoreInlineContext *ctx,
+ int update, int capture, uint16_t length,
+ uint32_t select, uint32_t offset);
+
+#endif /* __ASSEMBLER__ */
+
+#if 0
+{ /* So __cplusplus doesn't mess w/auto-indent */
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PORE_INLINE_H__ */
+
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline_assembler.c b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline_assembler.c
new file mode 100644
index 000000000..ec4f0abbf
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline_assembler.c
@@ -0,0 +1,1487 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/pore_inline_assembler.c $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+// $Id: pore_inline_assembler.c,v 1.14 2012/05/23 19:03:42 bcbrock Exp $
+
+// ** WARNING : This file is maintained as part of the OCC firmware. Do **
+// ** not edit this file in the PMX area or the hardware procedure area **
+// ** as any changes will be lost. **
+
+/// \file pore_inline_assembler.c
+/// \brief Inline PGAS assembler for PgP/Stage1 PORE
+///
+/// \page pore_inline_assembler PORE Inline Assembler and Disassembler
+///
+/// Several procedures targeting the PORE engine require inline assembly and
+/// disassembly of PORE code, that is, they require that PORE instructions be
+/// assembled/disassembled directly into/from a host memory buffer. This page
+/// describes these facilities. The APIs described here are implemented in
+/// the files pore_inline.h, pore_inline_assembler.c and
+/// pore_inline_disassembler.c. Both the inline assembelr and disassembler
+/// conform to the PGAS assembly format for PORE.
+///
+/// Both inline assembly and disassembly make use of a PoreInlineContext
+/// structure. This structure represents the state of a memory area being
+/// targeted for inline assembly and disassembly. The context is initialized
+/// with the pore_inline_context_create() API, and a pointer to an instance of
+/// this structure appears as the first argument of all assembler/disassembler
+/// APIs. As assembly/disassembly progresses the PoreInlineContext keeps
+/// track of how much host memory area has been filled by assembled code or
+/// scanned by the disassebler.
+///
+/// Assembler/disassembler APIs are predicates that return 0 for success and a
+/// non-zero error code for failure. In the event of failure, the error code
+/// (a small integer) is also stored in the \a error field of the context
+/// structure. String forms of the error codes are also available in the
+/// global array pore_inline_error_strings[].
+///
+/// The assembler always produces PORE code in the PORE-native big-endian
+/// format. Likewise, the diassembler assumes the host memory to be
+/// disassembled contains PORE code in big-endian format.
+///
+/// \section Initialization
+///
+/// Before invoking inline assembly/disassembly APIs, an instance of a
+/// PoreInlineContext structure must be initialized using the
+/// pore_inline_context_create() API. For assembly, the context describes the
+/// host memory buffer that will contain the assembled code. For disassembly,
+/// the context describes the host memory area that contains the code to be
+/// disassembled. Full documentation is available for
+/// pore_inline_context_create(), including documentation for options that
+/// control assembly and disassembly. The implementation also provides a
+/// 'copy operator' for the context, pore_inline_context_copy().
+///
+/// An example of initializing a context for inline assembly with parity
+/// checking appears below.
+///
+/// \code
+///
+/// PoreInlineContext ctx;
+/// uint32_t buf[BUFSIZE];
+///
+/// rc = pore_inline_context_create(&ctx, buf, BUFSIZE * 4, 0,
+/// PORE_INLINE_CHECK_PARITY);
+/// if (rc) . . . Handle Error
+///
+/// \endcode
+///
+/// Applications that reuse the same memory buffer for assembling and
+/// processing multiple PORE programs can 'reset' the context between uses by
+/// using the pore_inline_context_reset() API. pore_inline_context_reset()
+/// resets the location counter and memory extent to their initial (creation)
+/// values, and the context error code is cleared. Any options specified at
+/// creation remain as they were.
+///
+/// \section Assembler
+///
+/// The inline assembler implements each PORE/PGAS instruction as individual
+/// function calls. The APIs are consistently named \c pore_<OPCODE>, where
+/// \c <OPCODE> is a PGAS mnemonic in upper case. The arguments to each
+/// opcode appear in the same order that they appear in the source-level
+/// assembler, with appropriate C-language types. The supported opcode APIs
+/// are defined in pore_inline.h
+///
+/// Since the PORE instruction APIs are effectivly predicates, linear code
+/// sequences are easily assembled using the C-language logical OR construct.
+/// Any non-0 return code will immediatly break the sequence and set the
+/// expression value to 1. The failure code can then be recovered from the \a
+/// error field of the context. This coding technique is illustrated in the
+/// following example of assembling a memory-memory copy sequence.
+///
+/// \code
+///
+/// PoreInlineContext ctx;
+/// int error;
+///
+/// . . . // Initialize context
+///
+/// error =
+/// pore_LD(&ctx, D0, 0, A0) ||
+/// pore_STD(&ctx, D0, 0, A1);
+///
+/// if (error) <. . . Handle error based on ctx.error>
+///
+/// \endcode
+///
+/// The above example generates code equivalent to
+///
+/// \code
+///
+/// ld D0, 0, A0
+/// std D0, 0, A1
+///
+/// \endcode
+///
+/// Again, if an error were to occur during assembly, inline assembly would
+/// stop (and the logical OR would terminate) at the point of failure. In
+/// particular, the inline assembler will never allow assembled code to exceed
+/// the bounds of the memory area defined by the initial call of
+/// pore_inline_context_create() that defines the assembler memory space.
+///
+///
+/// \subsection Register Names and Other Mnemonics
+///
+/// The header file pore_inline.h defines macros for the register mnemonics.
+///
+/// - D0, D1 : 64-bit data registers
+/// - A0, A1 : 32-bit address registers
+/// - P0, P1 : 7-bit Pervasive chiplet id registers
+/// - CTR : 24-bit ounter register
+/// - PC : 48-bit Program Counter
+/// - ETR : 64-bit EXE-Trigger Register (Low-order 32 bits are writable)
+/// - EMR : The Error Mask Register
+/// - IFR : ID/Flags Register
+/// - SPRG0 : 32-bit Special-Purpose General Register 0
+///
+/// Mnemonics for the condition code bits are also defined by pore_inline.h
+/// using the PGAS mnemonics.
+///
+///
+/// \subsection Assembling Branches
+///
+/// Opcodes that implement relative branches require that the branch target be
+/// specified as a <em> location counter <\em>. Once initialized, the current
+/// location counter is available as the \a lc field of the PoreInlineContext
+/// object controlling the assembly. The \a lc field is the only field
+/// (besides the error code held in the \a error field) that application code
+/// should ever reference. The inline assembler also provides a typedef
+/// PoreInlineLocation to use for location counters, as well as the macro
+/// PORE_LOCATION() to define a location variable inline with the code flow.
+///
+/// \subsubsection Backward Branches
+///
+/// Backward branches are straightforward. For example, the memory-memory
+/// copy example from earlier can be converted into a loop as shown below. The
+/// \a loop_target variable is initialized with the location counter of the
+/// first instruction of the loop. The final instruction of the loop then
+/// branches back to the \a loop_target.
+///
+/// \code
+///
+/// PoreInlineContext ctx;
+/// PoreInlineLocation loop_target = 0; // See ** below the example
+/// int error;
+///
+/// . . . // Initialize context
+///
+/// error =
+/// PORE_LOCATION(&ctx, loop_target) ||
+/// pore_LD(&ctx, D0, 0, A0) ||
+/// pore_STD(&ctx, D0, 0, A1) ||
+/// pore_ADDS(&ctx, A0, A0, 8) ||
+/// pore_ADDS(&ctx, A1, A1, 8) ||
+/// pore_LOOP(&ctx, loop_target);
+///
+/// if (error) <. . . Handle error based on ctx.error>
+///
+/// \endcode
+///
+/// The above inline assembler sequence is equivalent to the PGAS code
+/// sequence:
+///
+/// \code
+///
+/// loop_target:
+/// ld D0, 0, A0
+/// std D0, 0, A1
+/// adds A0, A0, 8
+/// adds A1, A1, 8
+/// loop loop_target
+///
+/// \endcode
+///
+/// ** Location counters used as loop targets may need to be initialized,
+/// otherwise the compiler may issue a warning that the variable "may be used
+/// uninitialized", although in well-written code this would never happen.
+///
+///
+/// \subsubsection Forward Branches
+///
+/// Forward branches are more complex. Since the target location counter is
+/// not known until the target has been assembled, the inline assembler
+/// provides the API pore_inline_branch_fixup() to fix up forward branches
+/// once the actual target is known. This is illustrated in the simple code
+/// sequence below, where an instruction is conditionally skipped.
+///
+/// \code
+///
+/// PoreInlineContext ctx;
+/// PoreInlineLocation source = 0, target = 0;
+/// int error, rc;
+///
+/// . . . // Initialize context
+///
+/// error =
+/// PORE_LOCATION(&ctx, source) ||
+/// pore_BRANZ(&ctx, D0, source) ||
+/// pore_ADDS(&ctx, D1, D1, 1) ||
+/// PORE_LOCATION(&ctx, target) ||
+/// pore_LD(&ctx, D0, 0, A0);
+///
+/// if (error) <. . . Handle assembly error based on ctx->error>
+/// rc = pore_inline_branch_fixup(&ctx, source, target);
+/// if (rc) <. . . Handle branch fixup error>
+///
+/// \endcode
+///
+/// In the above code, the branch instruction is initially assembled as a
+/// branch-to-self - the recommended idiom for forward branch source
+/// instructions. Once the entire sequence has been assembled,
+/// pore_inline_branch_fixup() reassembles the \c source instruction as a
+/// branch to the \target instruction. The above instruction sequence is
+/// equivalent to the PGAS code below:
+///
+/// \code
+///
+/// source:
+/// branz D0, target
+/// adds D1, D1, 1
+/// target:
+/// ld D0, 0, A0
+///
+/// \endcode
+///
+///
+/// \subsubsection Absolute Branches
+///
+/// It is unlikely that a typical application of the PORE inline assembler
+/// would ever need to include an absolute branch, since the branch target in
+/// this case is a fixed absolute address that must be known at assembly
+/// time. However the inline assembler does provide the pore_BRAIA() API for
+/// this purpose. This opcode requires a 16-bit address space constant and a
+/// 32-bit absoulte address (offset) within the memory space to specify the
+/// branch.
+///
+///
+/// \section Disassembly
+///
+/// Inline disassembly is implemented by a single API,
+/// pore_inline_disassemble(). The idea is similar to assembly: A host memory
+/// context containing PORE code (or data) is described by a PoreInlineContext
+/// structure. Each call of pore_inline_disassemble() disassembles the next
+/// instruction (or datum) in the context into a PoreInlineDisassembly
+/// structure provided by the caller. The disassembly object contains both
+/// binary and string forms of the disassembled instruction (or data). The
+/// next call of pore_inline_disassemble() proceses the next instruction (or
+/// datum) and so on.
+///
+/// \subsection Text (Code) Disassembly
+///
+/// In the example below the inline disassembler is used to completely
+/// disassemble a memory area containing text (code) to \a stdout until an
+/// error occurs, assumed to be either due to disassembling the entire memory
+/// area or finding an illegal instruction.
+///
+/// \code
+///
+/// PoreInlineContext ctx;
+/// PoreInlineDisassembly dis;
+///
+/// . . . // Initialize context
+///
+/// while (pore_inline_disassemble(&ctx, &dis) == 0) {
+/// printf("%s\n", dis.s);
+/// }
+///
+/// \endcode
+///
+/// To illustrate binary disassembly, the following example uses the
+/// disassembler to search for a RET statement in a block of PORE code, in
+/// order to extend an inline subroutine with more code. Note that the field
+/// \a dis->ctx contains the context that existed at the time the instruction
+/// was assembled. By copying this context back into the global context,
+/// inline assembly will continue by overwriting the RET with new
+/// instructions. If the copy had \e not been done, then newly assembled code
+/// would have \e followed the RET.
+///
+/// \code
+///
+/// PoreInlineContext ctx;
+/// PoreInlineDisassembly dis;
+///
+/// . . . // Initialize context
+///
+/// while ((pore_inline_disassemble(&ctx, &dis) == 0) &&
+/// (dis.opcode != PORE_OPCODE_RET));
+/// if (ctx.error != 0) {
+/// . . . // Handle error
+/// } else {
+/// pore_inline_context_copy(&ctx, &dis.ctx);
+/// . . . // Continue assembly by overwriting the RET
+/// }
+///
+/// \endcode
+///
+/// A special type of context reset is available to simplify applications that
+/// need to disassemble a just-assembled code sequence, e.g. for debugging.
+/// pore_inline_context_reset_excursion() resets the context such that the
+/// effective size of the context only covers the just-assembled code,
+/// allowing a dissassembly loop to cleanly stop once all code has been
+/// disassembled. The use is illustrated below - note that the disassembly
+/// stops on the expected error code PORE_INLINE_NO_MEMORY once the
+/// (effective) end of the buffer is reached.
+///
+/// \code
+///
+/// PoreInlineContext ctx;
+/// PoreInlineDisassembly dis;
+///
+/// . . . // Initialize context
+/// . . . // Assemble code into context
+///
+/// pore_inline_context_reset_excursion(&ctx);
+///
+/// while (pore_inline_disassemble(&ctx, &dis) == 0) {
+/// printf("%s\n", dis.s);
+/// }
+/// if (ctx.error != PORE_INLINE_NO_MEMORY) {
+/// . . . // Handle error
+/// }
+///
+/// \endcode
+///
+/// \subsection Data Disassembly
+///
+/// If the PoreInlineContext is created with the flag
+/// PORE_INLINE_DISASSEMBLE_DATA, then the context is disassembled as
+/// data. For complete information see the documentation for
+/// pore_inline_disassemble().
+
+
+#define __PORE_INLINE_ASSEMBLER_C__
+#include "pore_inline.h"
+#undef __PORE_INLINE_ASSEMBLER_C__
+
+// Definitions of PORE register classes. These are predicates that return
+// 1 if the register is a member of the class, else 0.
+
+static int
+pore_data(int reg)
+{
+ return
+ (reg == D0) ||
+ (reg == D1);
+}
+
+
+static int
+pore_address(int reg)
+{
+ return
+ (reg == A0) ||
+ (reg == A1);
+}
+
+
+static int
+pore_pervasive_chiplet_id(int reg)
+{
+ return
+ (reg == P0) ||
+ (reg == P1);
+}
+
+
+static int
+pore_branch_compare_data(int reg)
+{
+ return
+ (reg == D0) ||
+ (reg == D1) ||
+ (reg == CTR);
+}
+
+
+static int
+pore_ls_destination(int reg)
+{
+ return
+ (reg == D0) ||
+ (reg == D1) ||
+ (reg == A0) ||
+ (reg == A1) ||
+ (reg == P0) ||
+ (reg == P1) ||
+ (reg == CTR);
+}
+
+
+static int
+pore_li_destination(int reg)
+{
+ return
+ (reg == D0) ||
+ (reg == D1) ||
+ (reg == A0) ||
+ (reg == A1) ||
+ (reg == P0) ||
+ (reg == P1) ||
+ (reg == CTR);
+}
+
+
+static int
+pore_mr_source(int reg)
+{
+ return
+ (reg == D0) ||
+ (reg == D1) ||
+ (reg == A0) ||
+ (reg == A1) ||
+ (reg == P0) ||
+ (reg == P1) ||
+ (reg == CTR) ||
+ (reg == PC) ||
+ (reg == ETR) ||
+ (reg == SPRG0) ||
+ (reg == IFR) ||
+ (reg == EMR);
+}
+
+static int
+pore_mr_destination(int reg)
+{
+ return
+ (reg == D0) ||
+ (reg == D1) ||
+ (reg == A0) ||
+ (reg == A1) ||
+ (reg == P0) ||
+ (reg == P1) ||
+ (reg == CTR) ||
+ (reg == PC) ||
+ (reg == SPRG0)||
+ (reg == EMR);
+}
+
+
+/// Portable store of a 32-bit integer in big-endian format
+///
+/// The address \a p to receive the data is in the form of an unsigned long.
+
+void
+pore_inline_be32(unsigned long p, uint32_t x)
+{
+ uint8_t *p8 = (uint8_t *)p;
+ uint8_t *px = (uint8_t *)(&x);
+ int i, j;
+
+ if (!PORE_BIG_ENDIAN) {
+ for (i = 0, j = 3; i < 4; i++, j--) {
+ p8[i] = px[j];
+ }
+ } else {
+ *((uint32_t *)p) = x;
+ }
+}
+
+
+/// Portable store of a 64-bit integer in big-endian format
+///
+/// The address \a p to receive the data is in the form of an unsigned long.
+
+void
+pore_inline_be64(unsigned long p, uint64_t x)
+{
+ uint8_t *p8 = (uint8_t *)p;
+ uint8_t *px = (uint8_t *)(&x);
+ int i, j;
+
+ if (!PORE_BIG_ENDIAN) {
+ for (i = 0, j = 7; i < 8; i++, j--) {
+ p8[i] = px[j];
+ }
+ } else {
+ *((uint64_t *)p) = x;
+ }
+}
+
+
+// Portable load of a 32-bit integer in big-endian format
+
+uint32_t
+pore_inline_host32(unsigned long p)
+{
+ uint32_t x;
+ uint8_t *p8 = (uint8_t *)p;
+ uint8_t *px = (uint8_t *)(&x);
+ int i, j;
+
+ if (!PORE_BIG_ENDIAN) {
+ for (i = 0, j = 3; i < 4; i++, j--) {
+ px[j] = p8[i];
+ }
+ } else {
+ x = *((uint32_t *)p);
+ }
+
+ return x;
+}
+
+
+// Portable load of a 64-bit integer in big-endian format
+
+uint64_t
+pore_inline_host64(unsigned long p)
+{
+ uint64_t x;
+ uint8_t *p8 = (uint8_t *)p;
+ uint8_t *px = (uint8_t *)(&x);
+ int i, j;
+
+ if (!PORE_BIG_ENDIAN) {
+ for (i = 0, j = 7; i < 8; i++, j--) {
+ px[j] = p8[i];
+ }
+ } else {
+ x = *((uint64_t *)p);
+ }
+
+ return x;
+}
+
+
+// 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.
+
+static int
+popcount32(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
+
+static int
+popcount64(uint64_t x)
+{
+ return popcount32(x & 0xffffffff) + popcount32(x >> 32);
+}
+
+
+// Compute the parity of a PORE instruction as 0 or 1
+
+int
+pore_inline_parity(uint32_t instruction, uint64_t imd64)
+{
+ return (popcount32(instruction) + popcount64(imd64)) % 2;
+}
+
+
+/// Reset a PORE inline assembler context to its creation state
+///
+/// \param ctx A pointer to an initialized (and likely 'used')
+/// PoreInlineContext object.
+///
+/// This API resets a PoreInlineContext object to it's \e creation state, that
+/// is, the state it was in after the call of pore_inline_context_create().
+/// This API is designed for applications that reuse a memory buffer to
+/// assemble multiple PORE code sequences. After each sequence has been fully
+/// assembled and processed, calling pore_inline_context_reset() sets the
+/// context back as it was when the context was initially created so that the
+/// memory area can be reused. In particular, this API resets the location
+/// counter and memory extent to their initial values, and the error code is
+/// cleared. Any options specified at creation remain as they were.
+///
+/// For a slightly different type of reset, see
+/// pore_inline_context_reset_excursion().
+
+void
+pore_inline_context_reset(PoreInlineContext *ctx)
+{
+ ctx->lc_address = ctx->memory;
+ ctx->remaining = ctx->size;
+ ctx->lc = ctx->original_lc;
+ ctx->error = 0;
+}
+
+
+
+/// Reset a PORE inline assembler context to a special state for disassembly
+///
+/// \param ctx A pointer to an initialized (and almost certainly 'used')
+/// PoreInlineContext object.
+///
+/// This API resets a PoreInlineContext object to it's \e creation state, that
+/// is, the state it was in after the call of pore_inline_context_create(), \e
+/// except that the effective size of the memory area has been reduced to the
+/// size that was actually used during assembly. This API is designed for
+/// applications that assemble into a memory buffer and then want to easily
+/// disassemble the code (e.g., for debugging). After a code sequence has
+/// been assembled, calling pore_inline_context_reset_excursion() sets the
+/// context back as it was when the context was initially created, but with a
+/// (typically) shorter effective length, so that the disassembly will cleanly
+/// stop once the entire sequence has been disassembled. Once disassembled,
+/// the buffer can be fully resued after a subsequent call of
+/// pore_inline_context_reset(). In particular, this API resets the location
+/// counter to its initial value, clears the error code, and sets the
+/// effective size of the context to the amount of memory currently used. Any
+/// options specified at creation remain as they were.
+///
+/// For a full context reset see pore_inline_context_reset(). For an example
+/// see the \b Disassembly section of \ref pore_inline_assembler.
+
+void
+pore_inline_context_reset_excursion(PoreInlineContext *ctx)
+{
+ ctx->lc_address = ctx->memory;
+ ctx->remaining = ctx->size - ctx->remaining;
+ ctx->lc = ctx->original_lc;
+ ctx->error = 0;
+}
+
+
+/// Create a PORE inline assembler context
+///
+/// \param ctx A pointer to a PoreInlineContext object to be initialized
+/// and used for inline assembly. or disassembly.
+///
+/// \param memory A pointer to the host memory area to receive the assembled
+/// code, or contain the code to disassemble. In general the inline assembler
+/// will expect this memory area to be 4-byte aligned. This pointer may be
+/// NULL (0) only if the associated \a size is also 0.
+///
+/// \param size The size (in bytes) of the host memory area. The inline
+/// assembler will generate the PORE_INLINE_NO_MEMORY error if an attempt is
+/// made to assemble an instruction that would overflow the buffer, or
+/// disassemble past the end of the buffer. A 0 size is valid.
+///
+/// \param lc The initial, bytewise, target location counter for the assembled
+/// or disassembled code. This paramater will normally be initialized to 0 for
+/// assembling relocatable programs. The parameter would only need to be
+/// specified as non-0 for special cases, such as creating a context for
+/// disassembly.
+///
+/// \param options Option flags. Option flags are OR-ed together to create
+/// the final set of options. Valid options are
+///
+/// - PORE_INLINE_GENERATE_PARITY : Generate the proper parity bit for each
+/// instruction during assembly.
+///
+/// - PORE_INLINE_CHECK_PARITY : Check for correct instruction parity during
+/// disassembly.
+///
+/// - PORE_INLINE_LISTING_MODE : Generate disassembly strings in the form of a
+/// listing that contains location counters and encoded instructions as well
+/// as their diassembly. By default the disassembly strings do not contain
+/// this information and can be fed back in as source code to a PORE
+/// assembler.
+///
+/// - PORE_INLINE_DISASSEMBLE_DATA : generate disassembly assuming that the
+/// context contains data rather than text. Normally data is disassembled as
+/// .long directives, however if the context is unaligned or of an odd length
+/// then .byte directives may be used as well. This option can be used in
+/// conjunction with PORE_INLINE_LISTING_MODE.
+///
+/// - PORE_INLINE_8_BYTE_DATA : generate data disassembly using 8-byte values
+/// rather than the default 4-byte values. text. Normally data is
+/// disassembled as .quad directives, however if the context is unaligned or
+/// of an odd length then .long and .byte directives may be used as well.
+/// This option can be used in conjunction with PORE_INLINE_LISTING_MODE.
+///
+/// A PoreInlineContext describes a memory area and assembler context for
+/// inline assembly and disassembly. Assembly/disassembly begins at the host
+/// memory location and virtual location counter described in the parameters.
+/// As instructions are assembled/disassembled the PoreInlineContext keeps
+/// track of where in the host memory and virtual PORE memory areas to place
+/// new instructions during assembly, or from where to fetch the next
+/// instruction to disassemble.
+///
+/// \retval 0 Success
+///
+/// \retval PORE_INLINE_INVALID_PARAMETER Either the \a context pointer is
+/// NULL (0), the \a memory pointer is NULL (0) with a non-0 size, or the \a
+/// options include invalid options. The error code is also stored as the
+/// value of ctx->error, and in the event of an error the ctx->size field is
+/// set to 0, effectively preventing the context from being used.
+
+int
+pore_inline_context_create(PoreInlineContext *ctx,
+ void *memory, size_t size,
+ PoreInlineLocation lc, int options)
+{
+ int rc;
+
+ int valid_options =
+ PORE_INLINE_GENERATE_PARITY |
+ PORE_INLINE_CHECK_PARITY |
+ PORE_INLINE_LISTING_MODE |
+ PORE_INLINE_DISASSEMBLE_DATA;
+
+ if ((ctx == 0) || ((memory == 0) && (size != 0)) ||
+ ((options & ~valid_options) != 0)) {
+ rc = PORE_INLINE_INVALID_PARAMETER;
+ ctx->size = 0; /* Effectively prevents using the ctx */
+ } else {
+ rc = 0;
+ ctx->memory = (unsigned long)memory;
+ ctx->size = size;
+ ctx->original_lc = lc;
+ ctx->options = options;
+ pore_inline_context_reset(ctx);
+ }
+
+ ctx->error = rc;
+ return rc;
+}
+
+
+/// Copy a PORE inline assembler context
+///
+/// \param dest A pointer to a PoreInlineContext object to be initialized
+/// as a copy of the \a src context.
+///
+/// \param src A pointer to a PoreInlineContext object to be used as the
+/// source of the copy.
+///
+/// This API copies one PoreInlineContext structure to another. An example
+/// use appears in \ref pore_inline_assembly in the section discussing
+/// disassembly.
+
+void
+pore_inline_context_copy(PoreInlineContext *dest, PoreInlineContext *src)
+{
+ *dest = *src;
+}
+
+
+// 'Bump' a context forward by a given number of bytes. This an internal API
+// and the bump is always known to be legal.
+
+void
+pore_inline_context_bump(PoreInlineContext *ctx, size_t bytes)
+{
+ ctx->remaining -= bytes;
+ ctx->lc += bytes;
+ ctx->lc_address += bytes;
+}
+
+
+// Allocate space in the inline assembler context
+//
+// Allocation is specified and implemented in bytes. Both the physical
+// memory and the virtual LC are required to be 4-byte aligned. The allocator
+// returns a pointer to the memory area, or 0 if allocation fails.
+// Allocation failure sets the context error code to either
+// PORE_INLINE_NO_MEMORY or PORE_INLINE_ALIGNMENT_ERROR.
+
+static unsigned long
+pore_inline_allocate(PoreInlineContext *ctx, size_t bytes)
+{
+ unsigned long p = 0;
+
+ if (((ctx->lc % 4) != 0) ||
+ ((ctx->lc_address % 4) != 0)) {
+ ctx->error = PORE_INLINE_ALIGNMENT_ERROR;
+
+ } else if (bytes > ctx->remaining) {
+ ctx->error = PORE_INLINE_NO_MEMORY;
+
+ } else {
+ p = ctx->lc_address;
+ pore_inline_context_bump(ctx, bytes);
+ }
+ return p;
+}
+
+
+// Assemble a 1-word instruction
+//
+// The opcode and operand are assumed to be legal, having come from
+// abstractions that check their arguments. This call may fail with
+// PORE_INLINE_NO_MEMORY if there is no more room in the memory buffer. A
+// non-zero return indicates failure.
+
+int
+pore_inline_instruction1(PoreInlineContext *ctx, int opcode, uint32_t operand)
+{
+ uint32_t instruction;
+ unsigned long p;
+
+ p = pore_inline_allocate(ctx, 4);
+ if (p != 0) {
+
+ instruction = (opcode << 25) | operand;
+ if (ctx->options & PORE_INLINE_GENERATE_PARITY) {
+ instruction |= (1 - pore_inline_parity(instruction, 0)) << 24;
+ }
+
+ pore_inline_be32(p, instruction);
+ ctx->error = 0;
+ }
+ return p == 0;
+}
+
+
+// Assemble a 3-word instruction
+//
+// The opcode and operand are assumed to be legal, having come from
+// abstractions that check their arguments. This call may fail with
+// PORE_INLINE_NO_MEMORY if there is no more room in the memory buffer. A
+// non-zero return indicates failure.
+
+int
+pore_inline_instruction3(PoreInlineContext *ctx, int opcode, uint32_t operand,
+ uint64_t immediate)
+{
+ uint32_t instruction;
+ unsigned long p;
+
+ p = pore_inline_allocate(ctx, 12);
+ if (p != 0) {
+
+ instruction = (opcode << 25) | operand;
+ if (ctx->options & PORE_INLINE_GENERATE_PARITY) {
+ instruction |= (1 - pore_inline_parity(instruction, immediate)) << 24;
+ }
+
+ pore_inline_be32(p, instruction);
+ pore_inline_be64(p + 4, immediate);
+ ctx->error = 0;
+ }
+ return p == 0;
+}
+
+
+// Assemble WAIT
+//
+// The cycle count must be an unsigned 24-bit immediate otherwise the error
+// PORE_INLINE_UINT24_REQUIRED is signalled. PGAS requires that HALT be used
+// if the intention is to halt
+
+int
+pore_WAITS(PoreInlineContext *ctx, uint32_t cycles)
+{
+ uint32_t operand;
+ int opcode = PGAS_OPCODE_WAITS;
+
+ if (cycles == 0) {
+ ctx->error = PORE_INLINE_USE_HALT;
+ } else if ((cycles & 0xffffff) != cycles) {
+ ctx->error = PORE_INLINE_UINT24_REQUIRED;
+ } else {
+ operand = cycles;
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ return ctx->error;
+}
+
+
+// Assemble HOOKI
+//
+// The hook index must be an unsigned 24-bit immediate otherwise the error
+// PORE_INLINE_UINT24_REQUIRED is signalled.
+
+int
+pore_HOOKI(PoreInlineContext *ctx, uint32_t index, uint64_t imm)
+{
+ uint32_t operand;
+ int opcode = PGAS_OPCODE_HOOKI;
+
+ if ((index & 0xffffff) != index) {
+ ctx->error = PORE_INLINE_UINT24_REQUIRED;
+ } else {
+ operand = index;
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+ }
+ return ctx->error;
+}
+
+
+// Assemble BRA, BSR and LOOP
+//
+// The branch target here is a bytewise location counter. The target must be
+// 4-byte aligned and must be within the legal signed 24-bit word offset of
+// the current LC. Unaligned targets cause PORE_INLINE_ALIGNMENT_ERROR.
+// Unreachable targets cause PORE_INLINE_UNREACHABLE_TARGET.
+
+int
+pore_inline_bra(PoreInlineContext *ctx, int opcode, PoreInlineLocation target)
+{
+ int32_t offset;
+ uint32_t operand;
+
+ if (target % 4) {
+ ctx->error = PORE_INLINE_ALIGNMENT_ERROR;
+ } else {
+ offset = (int32_t)(target - ctx->lc) / 4;
+ if ((offset >= (1 << 23)) ||
+ (offset < -(1 << 23))) {
+ ctx->error = PORE_INLINE_UNREACHABLE_TARGET;
+ } else {
+ operand = offset & 0xffffff;
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ }
+ return ctx->error;
+}
+
+
+// Assemble BRAZ and BRANZ
+//
+// The branch target here is a bytewise location counter. The target must be
+// 4-byte aligned and must be within the legal signed 20-bit word offset of
+// the current LC. Unaligned targets cause PORE_INLINE_ALIGNMENT_ERROR.
+// Unreachable targets cause PORE_INLINE_UNREACHABLE_TARGET. Illegal
+// operands cause PORE_INLINE_ILLEGAL_REGISTER.
+
+int
+pore_inline_brac(PoreInlineContext *ctx, int opcode, int reg,
+ PoreInlineLocation target)
+{
+ int32_t offset;
+ uint32_t operand;
+
+ if (target % 4) {
+ ctx->error = PORE_INLINE_ALIGNMENT_ERROR;
+ } else if (!pore_branch_compare_data(reg)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ offset = (int32_t)(target - ctx->lc) / 4;
+ if ((offset >= (1 << 20)) ||
+ (offset < -(1 << 20))) {
+ ctx->error = PORE_INLINE_UNREACHABLE_TARGET;
+ } else {
+ operand = (offset & 0xfffff) | (reg << 20);
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ }
+ return ctx->error;
+}
+
+
+// Assemble CMPIBRAEQ, CMPIBRANE, CMPIBSREQ
+//
+// The branch target here is a bytewise location counter. The target must be
+// 4-byte aligned and must be within the legal signed 24-bit word offset of
+// the current LC. Unaligned targets cause PORE_INLINE_ALIGNMENT_ERROR.
+// Unreachable targets cause PORE_INLINE_UNREACHABLE_TARGET. Illegal
+// operands cause PORE_INLINE_ILLEGAL_REGISTER.
+
+int
+pore_inline_cmpibra(PoreInlineContext *ctx, int opcode, int reg,
+ PoreInlineLocation target, uint64_t imm)
+{
+ int32_t offset;
+ uint32_t operand;
+
+ if (target % 4) {
+ ctx->error = PORE_INLINE_ALIGNMENT_ERROR;
+ } else if (reg != D0) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ offset = (int32_t)(target - ctx->lc) / 4;
+ if ((offset >= (1 << 23)) ||
+ (offset < -(1 << 23))) {
+ ctx->error = PORE_INLINE_UNREACHABLE_TARGET;
+ } else {
+ operand = offset & 0xffffff;
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+ }
+ }
+ return ctx->error;
+}
+
+
+// Assemble BRAD and BSRD
+//
+// Illegal operands cause PORE_INLINE_ILLEGAL_REGISTER.
+
+int
+pore_inline_brad(PoreInlineContext *ctx, int opcode, int reg)
+{
+ uint32_t operand;
+
+ if (!pore_data(reg)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ operand = reg << 20;
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ return ctx->error;
+}
+
+
+// Assemble ANDI, ORI, XORI
+//
+// Source and destination must be of class 'data' otherwise the
+// PORE_INLINE_ILLEGAL_REGISTER error is generated.
+
+int
+pore_inline_ilogic(PoreInlineContext *ctx, int opcode,
+ int dest, int src, uint64_t imm)
+{
+ uint32_t operand;
+
+ if (!pore_data(dest) || !pore_data(src)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ operand = (dest << 20) | (src << 16);
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+ }
+ return ctx->error;
+}
+
+
+// Assemble AND, OR, XOR, ADD, SUB
+//
+// Destination must be of class 'data' otherwise the
+// PORE_INLINE_ILLEGAL_REGISTER error is generated. src1 and src2 must be D0,
+// D1 respectively otherwise the PORE_INLINE_ILLEGAL_REGISTER error is
+// generated.
+
+int
+pore_inline_alurr(PoreInlineContext *ctx,
+ int opcode, int dest, int src1, int src2)
+{
+ uint32_t operand;
+
+ if (!pore_data(dest) || (src1 != D0) || (src2 != D1)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ operand = (dest << 20);
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ return ctx->error;
+}
+
+
+// Assemble ADDS and SUBS
+//
+// Destination must be of class 'ls_destination' and must be equal to source,
+// otherwise the PORE_INLINE_ILLEGAL_REGISTER error is generated. If the
+// immediate is not a signed 16-bit immediate then the
+// PORE_INLINE_INT16_REQUIRED error is generated.
+
+int
+pore_inline_adds(PoreInlineContext *ctx,
+ int opcode, int dest, int src, int imm)
+{
+ uint32_t operand;
+
+ if (!pore_ls_destination(dest) || (dest != src)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ if ((imm >= (1 << 15)) ||
+ (imm < -(1 << 15))) {
+ ctx->error = PORE_INLINE_INT16_REQUIRED;
+ } else {
+ operand = (dest << 20) | (imm & 0xffff);
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ }
+ return ctx->error;
+}
+
+
+// Assemble NEG
+//
+// Source and destination must be of class 'data' otherwise the
+// PORE_INLINE_ILLEGAL_REGISTER error is generated.
+
+int
+pore_NEG(PoreInlineContext *ctx, int dest, int src)
+{
+ uint32_t operand;
+ int opcode = PGAS_OPCODE_NEG;
+
+ if (!pore_data(dest) || !pore_data(src)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ operand = (dest << 20) | (src << 16);
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ return ctx->error;
+}
+
+
+// Assemble MR
+//
+// The source must be an 'mr_source' and the destination must be an
+// 'mr_destination' otherwise the PORE_INLINE_ILLEGAL_REGISTER error is
+// generated.
+
+int
+pore_MR(PoreInlineContext *ctx, int dest, int src)
+{
+ uint32_t operand;
+ int opcode = PGAS_OPCODE_MR;
+
+ if (!pore_mr_destination(dest) || !pore_mr_source(src)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ operand = (dest << 20) | (src << 16);
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ return ctx->error;
+}
+
+
+
+// Assemble ROLS
+//
+// Source and destination must be of class 'data' otherwise the
+// PORE_INLINE_ILLEGAL_REGISTER error is generated. Illegal shifts yield the
+// PORE_INLINE_ILLEGAL_ROTATE error.
+
+int
+pore_ROLS(PoreInlineContext *ctx, int dest, int src, int imm)
+{
+ uint32_t operand;
+ int opcode = PGAS_OPCODE_ROLS;
+
+ if (!pore_data(dest) || !pore_data(src)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else if ((imm != 1) &&
+ (imm != 4) &&
+ (imm != 8) &&
+ (imm != 16) &&
+ (imm != 32)) {
+ ctx->error = PORE_INLINE_ILLEGAL_ROTATE;
+ } else {
+ operand = (dest << 20) | (src << 16) | imm;
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ return ctx->error;
+}
+
+
+// Assemble LS
+//
+// The destination must be an 'ls_destination' otherwise the
+// PORE_INLINE_ILLEGAL_REGISTER error is generated. If the immediate is not
+// a signed 20-bit immediate then the PORE_INLINE_INT20_REQUIRED error is
+// generated.
+
+int
+pore_LS(PoreInlineContext *ctx, int dest, int imm)
+{
+ uint32_t operand;
+ int opcode = PGAS_OPCODE_LS;
+
+ if (!pore_ls_destination(dest)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else if ((imm >= (1 << 19)) ||
+ (imm < -(1 << 19))) {
+ ctx->error = PORE_INLINE_INT20_REQUIRED;
+ } else {
+ operand = (dest << 20) | (imm & 0xfffff);
+ pore_inline_instruction1(ctx, opcode, operand);
+ }
+ return ctx->error;
+}
+
+
+// Assemble LI
+//
+// The destination must be an 'li destination' otherwise the
+// PORE_INLINE_ILLEGAL_REGISTER error is generated.
+
+int
+pore_LI(PoreInlineContext *ctx, int dest, uint64_t imm)
+{
+ uint32_t operand;
+ int opcode = PGAS_OPCODE_LI;
+
+ if (!pore_li_destination(dest)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ operand = dest << 20;
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+ }
+ return ctx->error;
+}
+
+
+// LD, LDANDI, STD, STI, BSI, BCI
+
+static void
+pervasive_ima24(PoreInlineContext *ctx,
+ int opcode, uint32_t offset, int base, uint64_t imm)
+{
+ uint32_t operand;
+
+ if ((offset & 0x80f00000) != 0) {
+ ctx->error = PORE_INLINE_ILLEGAL_SCOM_ADDRESS;
+ } else {
+ operand = ((base % 2) << 22) | (offset & 0xfffff);
+ switch (opcode) {
+ case PGAS_OPCODE_LD0:
+ case PGAS_OPCODE_LD1:
+ case PGAS_OPCODE_STD0:
+ case PGAS_OPCODE_STD1:
+ pore_inline_instruction1(ctx, opcode, operand);
+ break;
+ default:
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+ break;
+ }
+ }
+}
+
+
+static void
+memory_ima24(PoreInlineContext *ctx,
+ int opcode, uint32_t offset, int base, uint64_t imm)
+{
+ uint32_t operand;
+
+ if ((offset & 0x3fffff) != offset) {
+ ctx->error = PORE_INLINE_UINT22_REQUIRED;
+ } else if ((offset % 8) != 0) {
+ ctx->error = PORE_INLINE_ALIGNMENT_ERROR;
+ } else {
+ operand = 0x800000 | ((base % 2) << 22) | (offset & 0x3fffff);
+ switch (opcode) {
+ case PGAS_OPCODE_LD0:
+ case PGAS_OPCODE_LD1:
+ case PGAS_OPCODE_STD0:
+ case PGAS_OPCODE_STD1:
+ pore_inline_instruction1(ctx, opcode, operand);
+ break;
+ default:
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+ break;
+ }
+ }
+}
+
+
+static void
+ima24(PoreInlineContext *ctx,
+ int opcode, uint32_t offset, int base, uint64_t imm)
+{
+ if (pore_pervasive_chiplet_id(base)) {
+ pervasive_ima24(ctx, opcode, offset, base, imm);
+ } else if (pore_address(base)) {
+ memory_ima24(ctx, opcode, offset, base, imm);
+ } else {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ }
+}
+
+#include <stdio.h>
+
+int
+pore_inline_load_store(PoreInlineContext *ctx,
+ int opcode, int src_dest, int32_t offset, int base,
+ uint64_t imm)
+{
+ switch (opcode) {
+
+ case PORE_INLINE_PSEUDO_LD:
+ case PORE_INLINE_PSEUDO_LDANDI:
+ case PORE_INLINE_PSEUDO_STD:
+
+ // These three pick the real opcode based on the dest. register
+
+ if (!pore_data(src_dest)) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ } else {
+ switch (opcode) {
+ case PORE_INLINE_PSEUDO_LD:
+ opcode = (src_dest == D0) ?
+ PGAS_OPCODE_LD0 : PGAS_OPCODE_LD1;
+ break;
+ case PORE_INLINE_PSEUDO_LDANDI:
+ opcode = (src_dest == D0) ?
+ PGAS_OPCODE_LD0ANDI : PGAS_OPCODE_LD1ANDI;
+ break;
+ case PORE_INLINE_PSEUDO_STD:
+ opcode = (src_dest == D0) ?
+ PGAS_OPCODE_STD0 : PGAS_OPCODE_STD1;
+ break;
+ }
+ }
+ break;
+
+ case PGAS_OPCODE_BSI:
+ case PGAS_OPCODE_BCI:
+
+ if (src_dest != D0) {
+ ctx->error = PORE_INLINE_ILLEGAL_REGISTER;
+ }
+ break;
+
+ case PGAS_OPCODE_STI:
+ break;
+
+ default:
+ ctx->error = PORE_INLINE_BUG;
+ }
+
+ if (ctx->error == 0) {
+ ima24(ctx, opcode, offset, base, imm);
+ }
+
+ return ctx->error;
+}
+
+
+// Assemble BRAIA
+
+int
+pore_BRAIA(PoreInlineContext *ctx,
+ uint16_t address_space, uint32_t offset)
+{
+ int opcode = PGAS_OPCODE_BRAI;
+ uint32_t operand = 0;
+ uint64_t imm = ((uint64_t)address_space << 32) | offset;
+
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+
+ return ctx->error;
+}
+
+
+// Assemble SCAND
+
+int
+pore_SCAND(PoreInlineContext *ctx,
+ int update, int capture, uint16_t length,
+ uint32_t select, uint32_t offset)
+{
+ int opcode = PGAS_OPCODE_SCAND;
+ uint32_t operand;
+ uint64_t imm = ((uint64_t)select << 32) | offset;
+
+ if ((update < 0) ||
+ (update > 1) ||
+ (capture < 0) ||
+ (capture > 1)) {
+ ctx->error = PORE_INLINE_INVALID_PARAMETER;
+ } else {
+ opcode = PGAS_OPCODE_SCAND;
+ operand = (update << 23) | (capture << 22) | length;
+ pore_inline_instruction3(ctx, opcode, operand, imm);
+ }
+ return ctx->error;
+}
+
+
+/// Fix up a PORE inline assembler forward branch instruction
+///
+/// \param ctx A pointer to the initialized PoreInlineContext object
+/// controlling inline assembly.
+///
+/// \param source The PORE inline location counter associated with the source
+/// instruction of the forward branch.
+///
+/// \param target The PORE inline location counter associated with the target
+/// instruction of the forward branch.
+///
+/// For usage examples, see the documentation \ref pore_inline_assembler.
+/// Although intended for forward branches, this API could be used to create
+/// backward branches as well. Note however the limitation that the \a source
+/// must be in the current context, since the source instruction needs to be
+/// reassembled with the branch target. In theory the \a target could be
+/// anywhere, as long as the location counter of the target is known.
+///
+/// \retval 0 Success
+///
+/// \retval code Failure. Any non-zero return is the PORE inline assmebler
+/// error code. The failure code is also stored in the PoreInlineContext
+/// object \a error field. The most likely causes of failure include a source
+/// location that is not in the current context or not associated with a
+/// branch instruction.
+
+int
+pore_inline_branch_fixup(PoreInlineContext *ctx,
+ PoreInlineLocation source,
+ PoreInlineLocation target)
+{
+ uint32_t instruction;
+ int32_t distance;
+ uint64_t imm;
+ int opcode, reg;
+ PoreInlineContext source_ctx;
+
+ if ((source < ctx->original_lc) ||
+ (source > ctx->lc)) {
+ ctx->error = PORE_INLINE_ILLEGAL_SOURCE_LC;
+ } else {
+
+ // Create a context as it existed when the source instruction was
+ // initially assembled, and then reassemble the instruction in that
+ // context with the actual target.
+
+ distance = ctx->lc - source;
+
+ source_ctx = *ctx;
+ source_ctx.lc = source;
+ source_ctx.remaining += distance;
+ source_ctx.lc_address -= distance;
+ source_ctx.error = 0;
+
+ instruction = pore_inline_host32(source_ctx.lc_address);
+ opcode = (instruction >> 25);
+ reg = (instruction >> 20) & 0xf;
+
+ switch (opcode) {
+ case PGAS_OPCODE_BRA:
+ pore_BRA(&source_ctx, target);
+ break;
+ case PGAS_OPCODE_BSR:
+ pore_BSR(&source_ctx, target);
+ break;
+ case PGAS_OPCODE_LOOP:
+ pore_LOOP(&source_ctx, target);
+ break;
+ case PGAS_OPCODE_BRAZ:
+ pore_BRAZ(&source_ctx, reg, target);
+ break;
+ case PGAS_OPCODE_BRANZ:
+ pore_BRANZ(&source_ctx, reg, target);
+ break;
+ case PGAS_OPCODE_CMPIBRAEQ:
+ imm = pore_inline_host64(source_ctx.lc_address + 4);
+ pore_CMPIBRAEQ(&source_ctx, D0, target, imm);
+ break;
+ case PGAS_OPCODE_CMPIBRANE:
+ imm = pore_inline_host64(source_ctx.lc_address + 4);
+ pore_CMPIBRANE(&source_ctx, D0, target, imm);
+ break;
+ case PGAS_OPCODE_CMPIBSREQ:
+ imm = pore_inline_host64(source_ctx.lc_address + 4);
+ pore_CMPIBSREQ(&source_ctx, D0, target, imm);
+ break;
+ default:
+ source_ctx.error = PORE_INLINE_NOT_A_BRANCH;
+ break;
+ }
+
+ ctx->error = source_ctx.error;
+ }
+ return ctx->error;
+}
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C
new file mode 100644
index 000000000..3744f1fea
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C
@@ -0,0 +1,419 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.C $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+/*------------------------------------------------------------------------------*/
+/* *! TITLE : proc_slw_build */
+/* *! DESCRIPTION : Extracts and decompresses delta ring states from EPROM */
+// image. Utilizes the linked list approach (LLA) to extract
+// and position wiggle-flip programs in .rings according to
+// back pointer, DD level, phase and override settings.
+/* *! OWNER NAME : Michael Olsen cmolsen@us.ibm.com */
+//
+/* *! EXTENDED DESCRIPTION : */
+//
+/* *! USAGE : To build (for Hostboot) - */
+// buildfapiprcd -r ver-12-5 -C "p8_image_help.C,p8_scan_compression.C" -c "sbe_xip_image.c,pore_inline_assembler.c,pore_inline_disassembler.c,p8_pore_static_data.c" -e "../../xml/error_info/proc_slw_build_errors.xml" proc_slw_build.C
+// Parameter list -
+// See function definition below.
+// Alternative usages -
+// To build for scanning by EPM team:
+// buildfapiprcd_cmo -u "SLW_BUILD_WF_P0_FIX,SLW_BUILD_SYSPHASE_ZERO_MODE,SLW_COMMAND_LINE" -r ...
+//
+/* *! ASSUMPTIONS : */
+// - For proc_slw_build, sysPhase=1 is assumed during real hostboot.
+//
+/* *! COMMENTS : */
+// - All image content, incl .initf content and ring layout, is handled
+// in BE format. No matter which platform.
+// - A ring may only be requested with the sysPhase=0 or 1. Any other
+// sysPhase value, incl sysPhase=2, will cause no rings to be found.
+//
+/*------------------------------------------------------------------------------*/
+
+#include "proc_slw_build.H"
+
+extern "C" {
+
+using namespace fapi;
+
+// Parameter list:
+// fapi::Target &i_target: Hardware target
+// void *i_imageIn: Pointer to memory mapped input SBE-XIP EPROM image
+// uint32_t i_sizeImageIn: Size of input image.
+// void *i_imageOut: Pointer to where to put SLW mainstore image
+// uint32_t *io_sizeImageOut: Size of output image. Initial upper limit supplied by HB. Final size returned.
+//
+ReturnCode proc_slw_build( const fapi::Target &i_target,
+ const void *i_imageIn,
+ uint32_t i_sizeImageIn,
+ void *i_imageOut,
+ uint32_t *io_sizeImageOut)
+{
+ ReturnCode rc;
+ uint8_t l_uint8 = 0;
+ uint32_t ddLevel=0;
+#ifdef SLW_BUILD_SYSPHASE_ZERO_MODE
+ uint8_t sysPhase=0;
+#else
+ uint8_t sysPhase=1;
+#endif
+
+ uint32_t rcLoc=0, rcSearch=0, i, countWF=0;
+ uint32_t sizeImage=0, sizeImageOutMax, sizeImageTmp, sizeImageOld;
+ uint8_t *deltaRingDxed=NULL;
+ CompressedScanData *deltaRingRS4=NULL;
+ DeltaRingLayout rs4RingLayout;
+ void *nextRing=NULL;
+
+ uint32_t ringBitLen=0, ringByteLen=0, ringTrailBits=0;
+
+ uint32_t *wfInline=NULL;
+ uint32_t wfInlineLenInWords;
+
+ sizeImageOutMax = *io_sizeImageOut;
+
+ if (sizeImageOutMax<i_sizeImageIn) {
+ FAPI_ERR("Inp image size (from caller): %i",i_sizeImageIn);
+ FAPI_ERR("Max image size (from caller): %i",*io_sizeImageOut);
+ uint32_t & DATA_IMG_SIZE_INP = i_sizeImageIn;
+ uint32_t & DATA_IMG_SIZE_MAX = *io_sizeImageOut;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_INPUT_IMAGE_SIZE_MESS);
+ return rc;
+ }
+
+
+ // ==========================================================================
+ // Check and copy image to mainstore and clean it up.
+ // ==========================================================================
+ // ToDo:
+ // - Eventually, automate emptying sections in proper order (last section goes first).
+ // - For 5/15, assume following order of removal: rings, pibmem0, and halt.
+ //
+ // First, check supplied size and validation of input EPROM image.
+ //
+ sbe_xip_image_size((void*)i_imageIn, &sizeImage);
+ rcLoc = sbe_xip_validate((void*)i_imageIn, sizeImage);
+ if (rcLoc) {
+ FAPI_ERR("xip_validate() failed w/rcLoc=%i",rcLoc);
+ uint32_t & RC_LOCAL = rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_INTERNAL_IMAGE_ERR);
+ return rc;
+ }
+ if (sizeImage!=i_sizeImageIn) {
+ FAPI_ERR("Size obtained from image's header (=%i) differs from supplied size (=%i).",
+ sizeImage,i_sizeImageIn);
+ uint32_t & DATA_IMG_SIZE_INP = i_sizeImageIn;
+ uint32_t & DATA_IMG_SIZE = sizeImage;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_IMAGE_SIZE_MISMATCH);
+ return rc;
+ }
+ FAPI_DBG("Image size (in EPROM): %i",i_sizeImageIn);
+
+ // Second, copy input image to supplied mainstore location.
+ //
+ memcpy( i_imageOut, i_imageIn, i_sizeImageIn);
+ sbe_xip_image_size(i_imageOut, &sizeImage);
+ rcLoc = sbe_xip_validate(i_imageOut, sizeImage);
+ if (rcLoc) {
+ FAPI_ERR("xip_validate() failed w/rcLoc=%i",rcLoc);
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_MS_INTERNAL_IMAGE_ERR);
+ return rc;
+ }
+ if (sizeImage!=i_sizeImageIn) {
+ FAPI_ERR("Size obtained from image's header (=%i) differs from supplied size (=%i).",
+ sizeImage,i_sizeImageIn);
+ uint32_t & DATA_IMG_SIZE_INP = i_sizeImageIn;
+ uint32_t & DATA_IMG_SIZE = sizeImage;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_MS_IMAGE_SIZE_MISMATCH);
+ return rc;
+ }
+
+ // Third, delete .rings and .pibmem0 sections (but keep .halt)
+ //
+ rcLoc = sbe_xip_delete_section( i_imageOut, SBE_XIP_SECTION_RINGS);
+ if (rcLoc) {
+ FAPI_ERR("xip_delete_section(.rings) failed w/rcLoc=%i",rcLoc);
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_DELETE_IMAGE_SECTION_ERROR);
+ return rc;
+ }
+ sbe_xip_image_size(i_imageOut, &sizeImage);
+ rcLoc = sbe_xip_validate(i_imageOut, sizeImage);
+ if (rcLoc) {
+ FAPI_ERR("xip_validate() failed w/rcLoc=%i",rcLoc);
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_MS_INTERNAL_IMAGE_ERR);
+ return rc;
+ }
+ FAPI_DBG("Image size (after .rings delete): %i",sizeImage);
+
+ rcLoc = sbe_xip_delete_section( i_imageOut, SBE_XIP_SECTION_PIBMEM0);
+ if (rcLoc) {
+ FAPI_ERR("xip_delete_section(.pibmem0) failed w/rcLoc=%i",rcLoc);
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_DELETE_IMAGE_SECTION_ERROR);
+ return rc;
+ }
+ sbe_xip_image_size(i_imageOut, &sizeImage);
+ rcLoc = sbe_xip_validate(i_imageOut, sizeImage);
+ if (rcLoc) {
+ FAPI_ERR("xip_validate() failed w/rcLoc=%i",rcLoc);
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_MS_INTERNAL_IMAGE_ERR);
+ return rc;
+ }
+ FAPI_DBG("Image size (after .pibmem0 delete): %i",sizeImage);
+
+ // ==========================================================================
+ // Get DD level from FAPI attributes.
+ // ==========================================================================
+ // $$rc = FAPI_ATTR_GET(ATTR_EC, &i_target, l_uint8);
+ rc = FAPI_ATTR_GET_PRIVILEGED(ATTR_EC, &i_target, l_uint8);
+ ddLevel = (uint32_t)l_uint8;
+ if (rc) {
+ FAPI_ERR("FAPI_ATTR_GET() failed w/rc=%i and ddLevel=0x%02x",(uint32_t)rc,l_uint8);
+ return rc;
+ }
+
+ /***************************************************************************
+ * SEARCH LOOP - Begin *
+ ***************************************************************************/
+ do {
+
+ FAPI_DBG("nextRing (at top)=0x%016llx",(uint64_t)nextRing);
+
+
+ // ==========================================================================
+ // Get ring layout from image
+ // ==========================================================================
+ FAPI_DBG("--> Reading RS4 delta ring info from SBE-XIP Image.");
+ rcLoc = get_ring_layout_from_image( i_imageIn,
+ ddLevel,
+ sysPhase,
+ &rs4RingLayout,
+ &nextRing);
+ rcSearch = rcLoc;
+ if (rcSearch!=DSLWB_RING_SEARCH_MATCH &&
+ rcSearch!=DSLWB_RING_SEARCH_EXHAUST_MATCH &&
+ rcSearch!=DSLWB_RING_SEARCH_NO_MATCH) {
+ FAPI_ERR("\tERROR : Getting delta ring from image was unsuccessful (rcSearch=%i).",rcSearch);
+ FAPI_ERR("\tNo wiggle-flip programs will be stored in .rings section.");
+ FAPI_ERR("\tThe following ELF sections have been emptied: .rings, .pibmem0, .ipl_text.");
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_RING_RETRIEVAL_ERROR);
+ return rc;
+ }
+ if (rcSearch==DSLWB_RING_SEARCH_MATCH ||
+ rcSearch==DSLWB_RING_SEARCH_EXHAUST_MATCH)
+ FAPI_DBG("\tRetrieving RS4 delta ring was successful.");
+
+ // Check if we're done at this point.
+ //
+ if (rcSearch==DSLWB_RING_SEARCH_NO_MATCH) {
+ FAPI_INF("Wiggle-flip programming done.");
+ FAPI_INF("Number of wf programs appended: %i", countWF);
+ if (countWF==0)
+ FAPI_INF("ZERO WF programs appended to .rings section.");
+ sizeImageTmp = sizeImageOutMax;
+ rcLoc = append_empty_section( i_imageOut,
+ &sizeImageTmp,
+ SBE_XIP_SECTION_SLW,
+ SLW_SLW_SECTION_SIZE);
+ if (rcLoc) {
+ if (rcLoc==IMGBUILD_ERR_IMAGE_TOO_LARGE) {
+ uint32_t & DATA_IMG_SIZE_OLD=sizeImageOld;
+ uint32_t & DATA_IMG_SIZE_EST=sizeImageTmp;
+ uint32_t & DATA_IMG_SIZE_MAX=sizeImageOutMax;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_MAX_IMAGE_SIZE_EXCEEDED);
+ }
+ else {
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_APPEND_SLW_SECTION_ERROR);
+ }
+ return rc;
+ }
+ FAPI_INF("SLW section allocated for Ramming table.");
+ sbe_xip_image_size( i_imageOut, io_sizeImageOut);
+ FAPI_INF("Final SLW image size: %i", *io_sizeImageOut);
+ return FAPI_RC_SUCCESS;
+ }
+
+ deltaRingRS4 = (CompressedScanData*)rs4RingLayout.rs4Delta;
+
+ FAPI_DBG("Dumping ring layout:");
+ FAPI_DBG("\tentryOffset = %i",(uint32_t)myRev64(rs4RingLayout.entryOffset));
+ FAPI_DBG("\tbackItemPtr = 0x%016llx",myRev64(rs4RingLayout.backItemPtr));
+ FAPI_DBG("\tsizeOfThis = %i",myRev32(rs4RingLayout.sizeOfThis));
+ FAPI_DBG("\tsizeOfMeta = %i",myRev32(rs4RingLayout.sizeOfMeta));
+ FAPI_DBG("\tddLevel = %i",myRev32(rs4RingLayout.ddLevel));
+ FAPI_DBG("\tsysPhase = %i",rs4RingLayout.sysPhase);
+ FAPI_DBG("\toverride = %i",rs4RingLayout.override);
+ FAPI_DBG("\treserved1+2 = %i",rs4RingLayout.reserved1|rs4RingLayout.reserved2);
+ FAPI_DBG("\tRS4 magic # = 0x%08x",myRev32(deltaRingRS4->iv_magic));
+ FAPI_DBG("\tRS4 total size = %i",myRev32(deltaRingRS4->iv_size));
+ FAPI_DBG("\tUnXed data size = %i",myRev32(deltaRingRS4->iv_length));
+ FAPI_DBG("\tScan select = 0x%08x",myRev32(deltaRingRS4->iv_scanSelect));
+ FAPI_DBG("\tHeader version = 0x%02x",deltaRingRS4->iv_headerVersion);
+ FAPI_DBG("\tFlush optimize = 0x%02x (reverse of override)",deltaRingRS4->iv_flushOptimization);
+ FAPI_DBG("\tReserved = 0x%02x",deltaRingRS4->iv_reserved);
+ FAPI_DBG("\tChiplet ID = 0x%02x",deltaRingRS4->iv_chipletId);
+ FAPI_DBG("Dumping meta data:");
+ FAPI_DBG("\tsizeOfData = %i",myRev32(rs4RingLayout.sizeOfMeta));
+ FAPI_DBG("\tMeta data = ");
+ for (i=0; i<myRev32(rs4RingLayout.sizeOfMeta); i++) { // String may not be null terminated.
+ FAPI_DBG("%c",rs4RingLayout.metaData[i]);
+ }
+
+
+ // ==========================================================================
+ // Decompress RS4 delta state.
+ // ==========================================================================
+ FAPI_DBG("--> Decompressing RS4 delta ring.");
+ // Note: deltaRingDxed is left-aligned. If converting to uint32_t, do BE->LE flip.
+ deltaRingDxed = NULL;
+ rcLoc = rs4_decompress( &deltaRingDxed,
+ &ringBitLen,
+ deltaRingRS4);
+ if (rcLoc) {
+ FAPI_ERR("\tERROR : rs4_decompress() failed: rc=%i",rcLoc);
+ if (deltaRingDxed) free(deltaRingDxed);
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_RS4_DECOMPRESSION_ERROR);
+ return rc;
+ }
+ FAPI_DBG("\tDecompression successful.\n");
+
+ ringByteLen = (ringBitLen-1)/8+1;
+ ringTrailBits = ringBitLen - 8*(ringByteLen-1);
+
+
+ // ==========================================================================
+ // Create Wiggle-Flip Programs
+ // ==========================================================================
+ FAPI_DBG("--> Creating Wiggle-Flip Program.");
+ rcLoc = create_wiggle_flip_prg( (uint32_t*)deltaRingDxed,
+ ringBitLen,
+ myRev32(deltaRingRS4->iv_scanSelect),
+ (uint32_t)deltaRingRS4->iv_chipletId,
+ &wfInline,
+ &wfInlineLenInWords);
+ if (rcLoc) {
+ FAPI_ERR("ERROR : create_wiggle_flip_prg() failed w/rcLoc=%i",rcLoc);
+ if (deltaRingDxed) free(deltaRingDxed);
+ if (wfInline) free(wfInline);
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_WF_CREATION_ERROR);
+ return rc;
+ }
+ FAPI_DBG("\tWiggle-flip programming successful.");
+
+
+ // ==========================================================================
+ // Append Wiggle-Flip programs to .rings section.
+ // ==========================================================================
+ FAPI_DBG("--> Appending wiggle-flip and layout header to .rings section.");
+ sizeImageTmp = sizeImageOutMax;
+ rcLoc = write_wiggle_flip_to_image( i_imageOut,
+ &sizeImageTmp,
+ &rs4RingLayout,
+ wfInline,
+ wfInlineLenInWords);
+ if (rcLoc) {
+ FAPI_ERR("ERROR : write_wiggle_flip_to_image() failed w/rcLoc=%i",rcLoc);
+ if (deltaRingDxed) free(deltaRingDxed);
+ if (wfInline) free(wfInline);
+ if (rcLoc==IMGBUILD_ERR_IMAGE_TOO_LARGE) {
+ uint32_t & DATA_IMG_SIZE_OLD=sizeImageOld;
+ uint32_t & DATA_IMG_SIZE_EST=sizeImageTmp;
+ uint32_t & DATA_IMG_SIZE_MAX=sizeImageOutMax;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_MAX_IMAGE_SIZE_EXCEEDED);
+ }
+ else {
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_IMAGE_UPDATE_ERROR);
+ }
+ return rc;
+ }
+ FAPI_DBG("\tUpdating image w/wiggle-flip program + header was successful.");
+
+ // Update some variables for debugging and error reporting.
+ sizeImageOld = sizeImageTmp;
+ countWF++;
+
+
+ // ==========================================================================
+ // Clean up
+ // ==========================================================================
+ if (deltaRingDxed) free(deltaRingDxed);
+ if (wfInline) free(wfInline);
+
+
+ // ==========================================================================
+ // Are we done?
+ // ==========================================================================
+ if (rcSearch==DSLWB_RING_SEARCH_EXHAUST_MATCH) {
+ FAPI_INF("Wiggle-flip programming done.");
+ FAPI_INF("Number of wf programs appended: %i", countWF);
+ if (countWF==0)
+ FAPI_INF("ZERO WF programs appended to .rings section.");
+ sizeImageTmp = sizeImageOutMax;
+ rcLoc = append_empty_section( i_imageOut,
+ &sizeImageTmp,
+ SBE_XIP_SECTION_SLW,
+ SLW_SLW_SECTION_SIZE);
+ if (rcLoc) {
+ if (rcLoc==IMGBUILD_ERR_IMAGE_TOO_LARGE) {
+ uint32_t & DATA_IMG_SIZE_OLD=sizeImageOld;
+ uint32_t & DATA_IMG_SIZE_EST=sizeImageTmp;
+ uint32_t & DATA_IMG_SIZE_MAX=sizeImageOutMax;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_MAX_IMAGE_SIZE_EXCEEDED);
+ }
+ else {
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_APPEND_SLW_SECTION_ERROR);
+ }
+ return rc;
+ }
+ FAPI_INF("SLW section allocated for Ramming table.");
+ sbe_xip_image_size( i_imageOut, io_sizeImageOut);
+ FAPI_INF("Final SLW image size: %i", *io_sizeImageOut);
+ return FAPI_RC_SUCCESS;
+ }
+
+ FAPI_DBG("nextRing (at bottom)=0x%016llx",(uint64_t)nextRing);
+
+ } while (nextRing!=NULL);
+ /***************************************************************************
+ * SEARCH LOOP - End *
+ ***************************************************************************/
+
+ FAPI_ERR("ERROR : Shouldn't be in this code section. Check code.");
+ rcLoc = IMGBUILD_ERR_CHECK_CODE;
+ uint32_t & RC_LOCAL=rcLoc;
+ FAPI_SET_HWP_ERROR(rc, RC_PROC_SLWB_UNKOWN_ERROR);
+ return rc;
+
+}
+
+} // End of extern C
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H
new file mode 100644
index 000000000..7db527191
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H
@@ -0,0 +1,52 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build.H $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+
+#include <fapi.H>
+#include "p8_delta_scan_rw.h"
+#include "p8_pore_table_gen_api.H"
+
+typedef fapi::ReturnCode (*proc_slw_build_FP_t) ( const fapi::Target&,
+ const void*,
+ uint32_t,
+ void*,
+ uint32_t*);
+
+extern "C"
+{
+ // Description: FAPI HWP entry point. proc_slw_build() constructs the
+ // Sleep-Winkle (SLW) image in mainstore during Hostboot
+ // IPL.
+ // Parameters: i_target: Processor chip target.
+ // *i_imageIn: Pointer to location of input SBE-XIP image.
+ // i_sizeImageIn: Size of input image.
+ // *i_imageOut: Pointer to location of output SLW image in
+ // mainstore.
+ // *io_sizeImageOut: On input, upper limit of size of output
+ // image. On output, final size of output image.
+ fapi::ReturnCode proc_slw_build( const fapi::Target &i_target,
+ const void *i_imageIn,
+ uint32_t i_sizeImageIn,
+ void *i_imageOut,
+ uint32_t *io_sizeImageOut);
+}
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml
new file mode 100644
index 000000000..e579245df
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml
@@ -0,0 +1,108 @@
+<!-- IBM_PROLOG_BEGIN_TAG
+ This is an automatically generated prolog.
+
+ $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml $
+
+ IBM CONFIDENTIAL
+
+ COPYRIGHT International Business Machines Corp. 2012
+
+ p1
+
+ Object Code Only (OCO) source materials
+ Licensed Internal Code Source Materials
+ IBM HostBoot Licensed Internal Code
+
+ The source code for this program is not published or other-
+ wise divested of its trade secrets, irrespective of what has
+ been deposited with the U.S. Copyright Office.
+
+ Origin: 30
+
+ IBM_PROLOG_END_TAG -->
+<!-- Error definitions for proc_slw_build procedure -->
+<hwpErrors>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_INPUT_IMAGE_SIZE_MESS</rc>
+ <description>Supplied max image size is too small or image too large.</description>
+ <ffdc>DATA_IMG_SIZE_INP</ffdc>
+ <ffdc>DATA_IMG_SIZE_MAX</ffdc>
+</hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_IMAGE_SIZE_MISMATCH</rc>
+ <description>Supplied image size differs from size in image header.</description>
+ <ffdc>DATA_IMG_SIZE_INP</ffdc>
+ <ffdc>DATA_IMG_SIZE</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_MS_IMAGE_SIZE_MISMATCH</rc>
+ <description>Supplied image size differs from size in mainstore image header.</description>
+ <ffdc>DATA_IMG_SIZE_INP</ffdc>
+ <ffdc>DATA_IMG_SIZE</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_MAX_IMAGE_SIZE_EXCEEDED</rc>
+ <description>Estimated image size exceeds max allowed size.</description>
+ <ffdc>DATA_IMG_SIZE_OLD</ffdc>
+ <ffdc>DATA_IMG_SIZE_EST</ffdc>
+ <ffdc>DATA_IMG_SIZE_MAX</ffdc>
+</hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_INTERNAL_IMAGE_ERR</rc>
+ <description>Unable to obtain either image size or to validate image.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_MS_INTERNAL_IMAGE_ERR</rc>
+ <description>Unable to obtain either image size or to validate image in mainstore.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_DELETE_IMAGE_SECTION_ERROR</rc>
+ <description>Error associated with deleting an image section.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_RING_RETRIEVAL_ERROR</rc>
+ <description>Error associated with retrieving RS4 ring from image.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_RS4_DECOMPRESSION_ERROR</rc>
+ <description>RS4 decompression failed.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_WF_CREATION_ERROR</rc>
+ <description>Wiggle-flip programming failed.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_IMAGE_UPDATE_ERROR</rc>
+ <description>Error associated with updating mainstore image.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_APPEND_SLW_SECTION_ERROR</rc>
+ <description>Error associated with adding empty SLW section for ramming table.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+ <!-- *********************************************************************** -->
+ <hwpError>
+ <rc>RC_PROC_SLWB_UNKOWN_ERROR</rc>
+ <description>Unknown error, shouldn't be in this code section.</description>
+ <ffdc>RC_LOCAL</ffdc>
+ </hwpError>
+</hwpErrors>
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c
new file mode 100644
index 000000000..722e8fdb7
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c
@@ -0,0 +1,2008 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.c $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+// $Id: sbe_xip_image.c,v 1.17 2012/05/22 22:59:05 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/sbe/sbe_xip_image.c,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+// *! OWNER NAME: Bishop Brock Email: bcbrock@us.ibm.com
+//------------------------------------------------------------------------------
+
+/// \file sbe_xip_image.c
+/// \brief APIs for validating, normalizing, searching and manipulating
+/// SBE-XIP images.
+///
+/// The background, APIs and implementation details are documented in the
+/// document "SBE-XIP Binary format" currently available at this link:
+///
+/// - https://mcdoc.boeblingen.de.ibm.com/out/out.ViewDocument.php?documentid=2678
+///
+/// \bug The sbe_xip_validate() API should be carefully reviewed to ensure
+/// that validating even a corrupt image can not lead to a segfault, i.e., to
+/// ensure that no memory outside of the putative bounds of the image is ever
+/// referenced during validation.
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include "sbe_xip_image.h"
+
+
+////////////////////////////////////////////////////////////////////////////
+// Local Functions
+////////////////////////////////////////////////////////////////////////////
+
+#ifdef DEBUG_SBE_XIP_IMAGE
+
+// Debugging support, normally disabled. All of the formatted I/O you see in
+// the code is effectively under this switch.
+
+#ifdef __FAPI
+
+#include "fapi.H"
+#define fprintf(stream, ...) FAPI_ERR(__VA_ARGS__)
+#define printf(...) FAPI_INF(__VA_ARGS__)
+#define TRACE_NEWLINE ""
+
+#else // __FAPI
+
+#include <stdio.h>
+#define TRACE_NEWLINE "\n"
+
+#endif // __FAPI
+
+// Portable formatting of uint64_t. The ISO C99 standard requires
+// __STDC_FORMAT_MACROS to be defined in order for PRIx64 etc. to be defined.
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#define F0x016llx "0x%016" PRIx64
+#define F0x012llx "0x%012" PRIx64
+
+static SBE_XIP_ERROR_STRINGS(sbe_xip_error_strings);
+
+#define TRACE_ERROR(x) \
+ ({ \
+ fprintf(stderr, "%s:%d : Returning error code %d : %s" TRACE_NEWLINE, \
+ __FILE__, __LINE__, (x), \
+ SBE_XIP_ERROR_STRING(sbe_xip_error_strings, (x))); \
+ (x); \
+ })
+
+#define TRACE_ERRORX(x, ...) \
+ ({ \
+ TRACE_ERROR(x); \
+ fprintf(stderr, ##__VA_ARGS__); \
+ (x); \
+ })
+
+
+// Uncomment these if required for debugging, otherwise we get warnings from
+// GCC as they are not otherwise used.
+
+#if 0
+
+static uint32_t revle32(const uint32_t i_x);
+
+static SBE_XIP_TYPE_STRINGS(type_strings);
+
+static void
+dumpToc(int index, SbeXipToc* toc)
+{
+ printf("TOC entry %d @ %p\n"
+ " iv_id = 0x%08x\n"
+ " iv_data = 0x%08x\n"
+ " iv_type = %s\n"
+ " iv_section = 0x%02x\n"
+ " iv_elements = %d\n",
+ index, toc,
+ revle32(toc->iv_id),
+ revle32(toc->iv_data),
+ SBE_XIP_TYPE_STRING(type_strings, toc->iv_type),
+ toc->iv_section,
+ toc->iv_elements);
+}
+
+#endif
+
+#if 0
+
+static void
+dumpItem(SbeXipItem* item)
+{
+ printf("SbeXipItem @ %p\n"
+ " iv_toc = %p\n"
+ " iv_address = " F0x016llx "\n"
+ " iv_imageData = %p\n"
+ " iv_id = %s\n"
+ " iv_type = %s\n"
+ " iv_elements = %d\n",
+ item,
+ item->iv_toc,
+ item->iv_address,
+ item->iv_imageData,
+ item->iv_id,
+ SBE_XIP_TYPE_STRING(type_strings, item->iv_type),
+ item->iv_elements);
+ dumpToc(-1, item->iv_toc);
+}
+
+#endif /* 0 */
+
+static void
+dumpSectionTable(const void* i_image)
+{
+ int i, rc;
+ SbeXipSection section;
+
+ printf("Section table dump of image @ %p\n"
+ " Entry Offset Size\n"
+ "-------------------------------\n",
+ i_image);
+
+ for (i = 0; i < SBE_XIP_SECTIONS; i++) {
+ rc = sbe_xip_get_section(i_image, i, &section);
+ if (rc) {
+ printf(">>> dumpSectionTable got error at entry %d : %s\n",
+ i, SBE_XIP_ERROR_STRING(sbe_xip_error_strings, rc));
+ break;
+ }
+ printf("%7d 0x%08x 0x%08x\n",
+ i, section.iv_offset, section.iv_size);
+ }
+}
+
+#else
+
+#define TRACE_ERROR(x) (x)
+#define TRACE_ERRORX(x, ...) (x)
+#define dumpToc(...)
+#define dumpItem(...)
+#define dumpSectionTable(...)
+
+#endif
+
+
+// Note: For maximum flexibility we provide private versions of
+// endian-conversion routines rather than counting on a system-specific header
+// to provide these.
+
+/// Byte-reverse a 32-bit integer if on a little-endian machine
+
+static uint32_t
+revle32(const uint32_t i_x)
+{
+ uint32_t rx;
+
+#ifndef _BIG_ENDIAN
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[3];
+ prx[1] = pix[2];
+ prx[2] = pix[1];
+ prx[3] = pix[0];
+#else
+ rx = i_x;
+#endif
+
+ return rx;
+}
+
+
+/// Byte-reverse a 64-bit integer if on a little-endian machine
+
+static uint64_t
+revle64(const uint64_t i_x)
+{
+ uint64_t rx;
+
+#ifndef _BIG_ENDIAN
+ uint8_t *pix = (uint8_t*)(&i_x);
+ uint8_t *prx = (uint8_t*)(&rx);
+
+ prx[0] = pix[7];
+ prx[1] = pix[6];
+ prx[2] = pix[5];
+ prx[3] = pix[4];
+ prx[4] = pix[3];
+ prx[5] = pix[2];
+ prx[6] = pix[1];
+ prx[7] = pix[0];
+#else
+ rx = i_x;
+#endif
+
+ return rx;
+}
+
+
+/// What is the image link address?
+
+static uint64_t
+linkAddress(const void* i_image)
+{
+ return revle64(((SbeXipHeader*)i_image)->iv_linkAddress);
+}
+
+
+/// What is the image size?
+
+static uint32_t
+imageSize(const void* i_image)
+{
+ return revle32(((SbeXipHeader*)i_image)->iv_imageSize);
+}
+
+
+/// Set the image size
+
+static void
+setImageSize(void* io_image, const size_t i_size)
+{
+ ((SbeXipHeader*)io_image)->iv_imageSize = revle32(i_size);
+}
+
+
+/// Re-establish the required final alignment
+
+static void
+finalAlignment(void* io_image)
+{
+ uint32_t size;
+
+ size = imageSize(io_image);
+
+ if ((size % SBE_XIP_FINAL_ALIGNMENT) != 0) {
+ setImageSize(io_image,
+ size + (SBE_XIP_FINAL_ALIGNMENT -
+ (size % SBE_XIP_FINAL_ALIGNMENT)));
+ }
+}
+
+
+/// Compute a host address from an image address and offset
+
+static void*
+hostAddressFromOffset(const void* i_image, const uint32_t offset)
+{
+ return (void*)((unsigned long)i_image + offset);
+}
+
+
+/// Convert a PORE address to a host address
+
+static void*
+pore2Host(const void* i_image, const uint64_t i_poreAddress)
+{
+ return hostAddressFromOffset(i_image,
+ i_poreAddress - linkAddress(i_image));
+}
+
+
+static int
+validatePoreAddress(const void* i_image,
+ const uint64_t i_poreAddress,
+ const uint32_t size)
+{
+ int rc;
+
+ if ((i_poreAddress < linkAddress(i_image)) ||
+ (i_poreAddress > (linkAddress(i_image) + imageSize(i_image) - size))) {
+ rc = TRACE_ERRORX(SBE_XIP_INVALID_ARGUMENT,
+ "The PORE address " F0x012llx " is outside the bounds "
+ "of the image (" F0x012llx ":" F0x012llx ") for %u-byte access.\n",
+ i_poreAddress,
+ linkAddress(i_image),
+ linkAddress(i_image) + imageSize(i_image) - 1,
+ size);
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+
+/// Get the magic number from the image
+
+static uint64_t
+magic(const void* i_image)
+{
+ return revle64(((SbeXipHeader*)i_image)->iv_magic);
+}
+
+
+/// Get the header version from the image
+
+static uint8_t
+headerVersion(const void* i_image)
+{
+ return ((SbeXipHeader*)i_image)->iv_headerVersion;
+}
+
+
+/// Has the image been normalized?
+
+static uint8_t
+normalized(const void* i_image)
+{
+ return ((SbeXipHeader*)i_image)->iv_normalized;
+}
+
+
+/// Has the image TOC been sorted?
+
+static uint8_t
+sorted(const void* i_image)
+{
+ return ((SbeXipHeader*)i_image)->iv_tocSorted;
+}
+
+
+/// A quick check that the image exists, has the correct magic and header
+/// version, and optionally is normalized.
+
+static int
+quickCheck(const void* i_image, const int i_normalizationRequired)
+{
+ int rc;
+
+ do {
+ rc = 0;
+
+ if (i_image == 0) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "Image pointer is NULL (0)\n");
+ break;
+ }
+ if ((magic(i_image) >> 32) != SBE_XIP_MAGIC) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "Magic number mismatch; Found "
+ "" F0x016llx ", expected 0x%08x........\n",
+ magic(i_image), SBE_XIP_MAGIC);
+ break;
+ }
+ if ((headerVersion(i_image)) != SBE_XIP_HEADER_VERSION) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "Header version mismatch; Expecting %d, "
+ "found %d\n",
+ SBE_XIP_HEADER_VERSION, headerVersion(i_image));
+ break;
+ }
+ if (i_normalizationRequired && !normalized(i_image)) {
+ rc = TRACE_ERRORX(SBE_XIP_NOT_NORMALIZED,
+ "Image not normalized\n");
+ break;
+ }
+ } while(0);
+
+ return rc;
+}
+
+
+/// Convert a 32-bit relocatable offset to a full PORE 48-bit address
+
+static uint64_t
+fullAddress(const void* i_image, uint32_t offset)
+{
+ return (linkAddress(i_image) & 0x0000ffff00000000ull) + offset;
+}
+
+
+/// Translate a section table entry
+
+static void
+translateSection(SbeXipSection* o_dest, const SbeXipSection* i_src)
+{
+#ifndef _BIG_ENDIAN
+
+#if SBE_XIP_HEADER_VERSION != 7
+#error This code assumes the SBE-XIP header version 7 layout
+#endif
+
+ o_dest->iv_offset = revle32(i_src->iv_offset);
+ o_dest->iv_size = revle32(i_src->iv_size);
+ o_dest->iv_alignment = i_src->iv_alignment;
+ o_dest->iv_reserved8[0] = 0;
+ o_dest->iv_reserved8[1] = 0;
+ o_dest->iv_reserved8[2] = 0;
+#else
+ if (o_dest != i_src) {
+ *o_dest = *i_src;
+ }
+#endif /* _BIG_ENDIAN */
+}
+
+
+/// Translate a TOC entry
+
+static void
+translateToc(SbeXipToc* o_dest, SbeXipToc* i_src)
+{
+#ifndef _BIG_ENDIAN
+
+#if SBE_XIP_HEADER_VERSION != 7
+#error This code assumes the SBE-XIP header version 7 layout
+#endif
+
+ o_dest->iv_id = revle32(i_src->iv_id);
+ o_dest->iv_data = revle32(i_src->iv_data);
+ o_dest->iv_type = i_src->iv_type;
+ o_dest->iv_section = i_src->iv_section;
+ o_dest->iv_elements = i_src->iv_elements;
+ o_dest->iv_pad = 0;
+#else
+ if (o_dest != i_src) {
+ *o_dest = *i_src;
+ }
+#endif /* _BIG_ENDIAN */
+}
+
+
+/// Find the final (highest-address) section of the image
+
+static int
+finalSection(const void* i_image, int* o_sectionId)
+{
+ int i, rc;
+ uint32_t offset;
+ SbeXipHeader hostHeader;
+
+ sbe_xip_translate_header(&hostHeader, (SbeXipHeader*)i_image);
+
+ offset = 0;
+ for (i = 0; i < SBE_XIP_SECTIONS; i++) {
+ if (hostHeader.iv_section[i].iv_offset > offset) {
+ *o_sectionId = i;
+ offset = hostHeader.iv_section[i].iv_offset;
+ }
+ }
+ if (offset == 0) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR, "The image is empty\n");
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+
+/// Return a pointer to an image-format section table entry
+
+static int
+getSectionPointer(const void* i_image,
+ const int i_sectionId,
+ SbeXipSection** o_imageSection)
+{
+ int rc;
+
+ if ((i_sectionId < 0) || (i_sectionId >= SBE_XIP_SECTIONS)) {
+ rc = TRACE_ERROR(SBE_XIP_INVALID_ARGUMENT);
+ } else {
+ *o_imageSection =
+ &(((SbeXipHeader*)i_image)->iv_section[i_sectionId]);
+ rc = 0;
+ }
+ return rc;
+}
+
+
+/// Restore a section table entry from host format to image format.
+
+static int
+putSection(const void* i_image,
+ const int i_sectionId,
+ SbeXipSection* i_hostSection)
+{
+ int rc;
+ SbeXipSection *imageSection;
+
+ rc = getSectionPointer(i_image, i_sectionId, &imageSection);
+
+ if (!rc) {
+ translateSection(imageSection, i_hostSection);
+ }
+
+ return rc;
+}
+
+
+/// Set the offset of a section
+
+static int
+setSectionOffset(void* io_image, const int i_section, const uint32_t i_offset)
+{
+ SbeXipSection* section;
+ int rc;
+
+ rc = getSectionPointer(io_image, i_section, &section);
+ if (!rc) {
+ section->iv_offset = revle32(i_offset);
+ }
+ return rc;
+}
+
+
+/// Set the size of a section
+
+static int
+setSectionSize(void* io_image, const int i_section, const uint32_t i_size)
+{
+ SbeXipSection* section;
+ int rc;
+
+ rc = getSectionPointer(io_image, i_section, &section);
+ if (!rc) {
+ section->iv_size = revle32(i_size);
+ }
+ return rc;
+}
+
+
+/// Translate a PORE address in the image to a section and offset
+
+// We first check to be sure that the PORE address is contained in the image,
+// using the full 48-bit form. Then we scan the section table to see which
+// section contains the address - if none then the image is corrupted. We can
+// (must) use the 32-bit offset form of the address here.
+
+static int
+pore2Section(const void* i_image,
+ const uint64_t i_poreAddress,
+ int* o_section,
+ uint32_t* o_offset)
+{
+ int rc, sectionId;
+ SbeXipSection section;
+ uint32_t addressOffset;
+
+ do {
+ rc = 0;
+
+ if ((i_poreAddress < linkAddress(i_image)) ||
+ (i_poreAddress > (linkAddress(i_image) + imageSize(i_image)))) {
+ rc = TRACE_ERRORX(SBE_XIP_INVALID_ARGUMENT,
+ "pore2section: The i_poreAddress argument "
+ "(" F0x016llx ")\nis outside the bounds of the "
+ "image (" F0x016llx ":" F0x016llx ")\n",
+ i_poreAddress,
+ linkAddress(i_image),
+ linkAddress(i_image) + imageSize(i_image));
+ break;
+ }
+
+ addressOffset = (i_poreAddress - linkAddress(i_image)) & 0xffffffff;
+
+ for (sectionId = 0; sectionId < SBE_XIP_SECTIONS; sectionId++) {
+ rc = sbe_xip_get_section(i_image, sectionId, &section);
+ if (rc) {
+ rc = TRACE_ERROR(SBE_XIP_BUG); /* Can't happen */
+ break;
+ }
+ if ((section.iv_size != 0) &&
+ (addressOffset >= section.iv_offset) &&
+ (addressOffset < (section.iv_offset + section.iv_size))) {
+ break;
+ }
+ }
+ if (rc) break;
+
+ if (sectionId == SBE_XIP_SECTIONS) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "Error processing PORE address " F0x016llx ". "
+ "The address is not mapped in any section.\n"
+ "A section table dump appears below\n",
+ i_poreAddress);
+ dumpSectionTable(i_image);
+ break;
+ }
+
+ *o_section = sectionId;
+ *o_offset = addressOffset - section.iv_offset;
+
+ } while(0);
+
+ return rc;
+}
+
+
+/// Get the information required to search the TOC.
+///
+/// All return values are optional.
+
+static int
+getToc(void* i_image,
+ SbeXipToc** o_toc,
+ size_t* o_entries,
+ int* o_sorted,
+ char** o_strings)
+{
+ int rc;
+ SbeXipSection tocSection, stringsSection;
+
+ do {
+ rc = sbe_xip_get_section(i_image, SBE_XIP_SECTION_TOC, &tocSection);
+ if (rc) break;
+
+ rc = sbe_xip_get_section(i_image, SBE_XIP_SECTION_STRINGS,
+ &stringsSection);
+ if (rc) break;
+
+ if (o_toc) {
+ *o_toc = (SbeXipToc*)((uint8_t*)i_image + tocSection.iv_offset);
+ }
+ if (o_entries) {
+ *o_entries = tocSection.iv_size / sizeof(SbeXipToc);
+ }
+ if (o_sorted) {
+ *o_sorted = sorted(i_image);
+ }
+ if (o_strings) {
+ *o_strings = (char*)i_image + stringsSection.iv_offset;
+ }
+ } while (0);
+ return rc;
+}
+
+
+/// Compare two normalized TOC entries for sorting.
+
+static int
+compareToc(const SbeXipToc* i_a, const SbeXipToc* i_b,
+ const char* i_strings)
+{
+ return strcmp(i_strings + revle32(i_a->iv_id),
+ i_strings + revle32(i_b->iv_id));
+}
+
+
+/// Iterative quicksort of the TOC
+
+// Note: The stack requirement is limited to 256 bytes + minor local storage.
+
+static void
+quickSort(SbeXipToc* io_toc, int i_left, int i_right,
+ const char* i_strings)
+{
+ int i, j, left, right, sp;
+ SbeXipToc pivot, temp;
+ uint32_t stack[64];
+
+ sp = 0;
+ stack[sp++] = i_left;
+ stack[sp++] = i_right;
+
+ while (sp) {
+
+ right = stack[--sp];
+ left = stack[--sp];
+
+ i = left;
+ j = right;
+
+ pivot = io_toc[(i + j) / 2];
+
+ while (i <= j) {
+ while (compareToc(&(io_toc[i]), &pivot, i_strings) < 0) {
+ i++;
+ }
+ while (compareToc(&(io_toc[j]), &pivot, i_strings) > 0) {
+ j--;
+ }
+ if (i <= j) {
+ temp = io_toc[i];
+ io_toc[i] = io_toc[j];
+ io_toc[j] = temp;
+ i++;
+ j--;
+ }
+ }
+ if (left < j) {
+ stack[sp++] = left;
+ stack[sp++] = j;
+ }
+ if (i < right) {
+ stack[sp++] = i;
+ stack[sp++] = right;
+ }
+ }
+}
+
+
+/// TOC linear search
+
+static int
+linearSearch(void* i_image, const char* i_id, SbeXipToc** o_entry)
+{
+ int rc;
+ SbeXipToc *imageToc, hostToc;
+ size_t entries;
+ char* strings;
+
+ *o_entry = 0;
+ rc = getToc(i_image, &imageToc, &entries, 0, &strings);
+ if (!rc) {
+ for (; entries; entries--, imageToc++) {
+ translateToc(&hostToc, imageToc);
+ if (strcmp(i_id, strings + hostToc.iv_id) == 0) {
+ break;
+ }
+ }
+ if (entries) {
+ *o_entry = imageToc;
+ rc = 0;
+ } else {
+ *o_entry = 0;
+ rc = TRACE_ERROR(SBE_XIP_ITEM_NOT_FOUND);
+ }
+ }
+ return rc;
+}
+
+
+/// A classic binary search of a (presumed) sorted array
+
+static int
+binarySearch(void* i_image, const char* i_id, SbeXipToc** o_entry)
+{
+ int rc;
+ SbeXipToc *imageToc;
+ size_t entries;
+ char* strings;
+ int sorted, left, right, next, sort;
+
+ do {
+ *o_entry = 0;
+
+ rc = getToc(i_image, &imageToc, &entries, &sorted, &strings);
+ if (rc) break;
+
+ if (!sorted) {
+ rc = TRACE_ERROR(SBE_XIP_BUG);
+ break;
+ }
+
+ left = 0;
+ right = entries - 1;
+ while (left <= right) {
+ next = (left + right) / 2;
+ sort = strcmp(i_id, strings + revle32(imageToc[next].iv_id));
+ if (sort == 0) {
+ *o_entry = &(imageToc[next]);
+ break;
+ } else if (sort < 0) {
+ right = next - 1;
+ } else {
+ left = next + 1;
+ }
+ }
+ if (*o_entry == 0) {
+ rc = TRACE_ERROR(SBE_XIP_ITEM_NOT_FOUND);
+ break;
+ }
+ } while (0);
+ return rc;
+}
+
+
+/// Validate a TOC entry as a mapping function
+///
+/// The TOC is validated by searching for the entry, which will uncover
+/// duplicate entries or problems with sorting/searching.
+
+static int
+validateTocEntry(void* io_image, const SbeXipItem* i_item, void* io_arg)
+{
+ int rc;
+ SbeXipItem found;
+
+ do {
+ rc = sbe_xip_find(io_image, i_item->iv_id, &found);
+ if (rc) {
+ rc = TRACE_ERRORX(rc, "TOC entry for %s not found\n",
+ i_item->iv_id);
+ } else if (found.iv_toc != i_item->iv_toc) {
+ rc = TRACE_ERRORX(SBE_XIP_TOC_ERROR,
+ "Duplicate TOC entry for '%s'\n", i_item->iv_id);
+ }
+ break;
+ } while (0);
+ return rc;
+}
+
+
+/// Normalize a TOC entry
+
+// Normalize the TOC entry by converting relocatable pointers into 32-bit
+// offsets from the beginning of the section containing the data. All
+// addresses in the TOC are actually 32-bit offsets in the address space named
+// in bits 16:31 of the link address of the image.
+
+static int
+normalizeToc(void* io_image, SbeXipToc *io_imageToc)
+{
+ SbeXipToc hostToc;
+ int idSection, dataSection;
+ uint32_t idOffset, dataOffset;
+ int rc;
+
+ do {
+
+ // Translate the TOC entry to host format. Then locate the
+ // sections/offsets of the Id string (which must be in .strings) and
+ // the data.
+
+ translateToc(&hostToc, io_imageToc);
+
+ rc = pore2Section(io_image,
+ fullAddress(io_image, hostToc.iv_id),
+ &idSection,
+ &idOffset);
+ if (rc) break;
+
+ if (idSection != SBE_XIP_SECTION_STRINGS) {
+ rc = TRACE_ERROR(SBE_XIP_IMAGE_ERROR);
+ break;
+ }
+
+ rc = pore2Section(io_image,
+ fullAddress(io_image, hostToc.iv_data),
+ &dataSection,
+ &dataOffset);
+ if (rc) break;
+
+ // Now replace the Id and data pointers with their offsets, and update
+ // the data section in the TOC entry.
+
+ hostToc.iv_id = idOffset;
+ hostToc.iv_data = dataOffset;
+ hostToc.iv_section = dataSection;
+
+ // Finally update the TOC entry
+
+ translateToc(io_imageToc, &hostToc);
+
+ } while (0);
+
+ return rc;
+}
+
+
+/// Decode a normalized image-format TOC entry into a host-format SbeXipItem
+/// structure
+
+static int
+decodeToc(void* i_image,
+ SbeXipToc* i_imageToc,
+ SbeXipItem* o_item)
+{
+ int rc;
+ SbeXipToc hostToc;
+ SbeXipSection dataSection, stringsSection;
+
+ do {
+ if (!normalized(i_image)) {
+ rc = TRACE_ERROR(SBE_XIP_NOT_NORMALIZED);
+ break;
+ }
+
+
+ // Translate the TOC entry and set the TOC pointer, data type and
+ // number of elements in the outgoing structure. The Id string is
+ // always located in the TOC_STRINGS section.
+
+ translateToc(&hostToc, i_imageToc);
+
+ o_item->iv_toc = i_imageToc;
+ o_item->iv_type = hostToc.iv_type;
+ o_item->iv_elements = hostToc.iv_elements;
+
+ sbe_xip_get_section(i_image, SBE_XIP_SECTION_STRINGS, &stringsSection);
+ o_item->iv_id =
+ (char*)i_image + stringsSection.iv_offset + hostToc.iv_id;
+
+
+ // The data (or text address) are addressed by relative offsets from
+ // the beginning of their section. The TOC entry may remain in the TOC
+ // even though the section has been removed from the image, so this
+ // case needs to be covered.
+
+ rc = sbe_xip_get_section(i_image, hostToc.iv_section, &dataSection);
+ if (rc) break;
+
+ if (dataSection.iv_size == 0) {
+ rc = TRACE_ERROR(SBE_XIP_DATA_NOT_PRESENT);
+ break;
+ }
+
+ o_item->iv_imageData =
+ (void*)((uint8_t*)i_image +
+ dataSection.iv_offset + hostToc.iv_data);
+
+ o_item->iv_address =
+ linkAddress(i_image) + dataSection.iv_offset + hostToc.iv_data;
+
+ } while (0);
+ return rc;
+}
+
+
+/// Sort the TOC
+
+static int
+sortToc(void* io_image)
+{
+ int rc;
+ SbeXipToc *hostToc;
+ size_t entries;
+ char* strings;
+
+ do {
+ rc = quickCheck(io_image, 1);
+ if (rc) break;
+
+ if (sorted(io_image)) break;
+
+ rc = getToc(io_image, &hostToc, &entries, 0, &strings);
+ if (rc) break;
+
+ quickSort(hostToc, 0, entries - 1, strings);
+
+ ((SbeXipHeader*)io_image)->iv_tocSorted = 1;
+
+ } while (0);
+
+ return rc;
+}
+
+
+// Pad the image with 0 to a given power-of-2 alignment. The image size is
+// modified to reflect the pad, but the caller must modify the section size to
+// reflect the pad.
+
+static int
+padImage(void* io_image, uint32_t i_allocation,
+ uint32_t i_align, uint32_t* pad)
+{
+ int rc;
+
+ do {
+ rc = 0;
+
+ if ((i_align == 0) || ((i_align & (i_align - 1)) != 0)) {
+ rc = TRACE_ERRORX(SBE_XIP_INVALID_ARGUMENT,
+ "Alignment specification (%u) "
+ "not a power-of-2\n",
+ i_align);
+ break;
+ }
+
+ *pad = imageSize(io_image) % i_align;
+ if (*pad != 0) {
+ *pad = i_align - *pad;
+
+ if ((imageSize(io_image) + *pad) > i_allocation) {
+ rc = TRACE_ERROR(SBE_XIP_WOULD_OVERFLOW);
+ break;
+ }
+
+ memset((void*)((unsigned long)io_image + imageSize(io_image)),
+ 0, *pad);
+ setImageSize(io_image, imageSize(io_image) + *pad);
+ }
+ } while (0);
+
+ return rc;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// Published API
+////////////////////////////////////////////////////////////////////////////
+
+int
+sbe_xip_validate(void* i_image, const uint32_t i_size)
+{
+ SbeXipHeader hostHeader;
+ int rc = 0, i;
+ uint32_t linkAddress, imageSize, extent, offset, size;
+ uint8_t alignment;
+
+ sbe_xip_translate_header(&hostHeader, (SbeXipHeader*)i_image);
+
+ do {
+
+ // Validate C/Assembler constraints.
+
+ if (sizeof(SbeXipSection) != SIZE_OF_SBE_XIP_SECTION) {
+ rc = TRACE_ERRORX(SBE_XIP_BUG,
+ "C/Assembler size mismatch(%d/%d) "
+ "for SbeXipSection\n",
+ sizeof(SbeXipSection), SIZE_OF_SBE_XIP_SECTION);
+ break;
+ }
+
+ if (sizeof(SbeXipToc) != SIZE_OF_SBE_XIP_TOC) {
+ rc = TRACE_ERRORX(SBE_XIP_BUG,
+ "C/Assembler size mismatch(%d/%d) "
+ "for SbeXipToc\n",
+ sizeof(SbeXipToc), SIZE_OF_SBE_XIP_TOC);
+ break;
+ }
+
+ // Validate the image pointer and magic number
+
+ rc = quickCheck(i_image, 0);
+ if (rc) break;
+
+ // Validate the image size
+
+ linkAddress = hostHeader.iv_linkAddress;
+ imageSize = hostHeader.iv_imageSize;
+ extent = linkAddress + imageSize;
+
+ if (imageSize < sizeof(SbeXipHeader)) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "sbe_xip_validate(%p, %u) : "
+ "The image size recorded in the image "
+ "(%u) is smaller than the header size.\n",
+ i_image, i_size, imageSize);
+ break;
+ }
+ if (imageSize != i_size) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "sbe_xip_validate(%p, %u) : "
+ "The image size recorded in the image "
+ "(%u) does not match the i_size parameter.\n",
+ i_image, i_size, imageSize);
+ break;
+ }
+ if (extent <= linkAddress) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "sbe_xip_validate(%p, %u) : "
+ "Given the link address (%u) and the "
+ "image size, the image wraps the address space\n",
+ i_image, i_size, linkAddress);
+ break;
+ }
+ if ((imageSize % SBE_XIP_FINAL_ALIGNMENT) != 0) {
+ rc = TRACE_ERRORX(SBE_XIP_ALIGNMENT_ERROR,
+ "sbe_xip_validate(%p, %u) : "
+ "The image size (%u) is not a multiple of %u\n",
+ i_image, i_size, imageSize,
+ SBE_XIP_FINAL_ALIGNMENT);
+ break;
+ }
+
+ // Validate that all sections appear to be within the image
+ // bounds, and are aligned correctly.
+
+ for (i = 0; i < SBE_XIP_SECTIONS; i++) {
+
+ offset = hostHeader.iv_section[i].iv_offset;
+ size = hostHeader.iv_section[i].iv_size;
+ alignment = hostHeader.iv_section[i].iv_alignment;
+
+ if ((offset > imageSize) ||
+ ((offset + size) > imageSize) ||
+ ((offset + size) < offset)) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "Section %d does not appear to be within "
+ "the bounds of the image\n"
+ "offset = %u, size = %u, image size = %u\n",
+ i, offset, size, imageSize);
+ break;
+ }
+ if ((offset % alignment) != 0) {
+ rc = TRACE_ERRORX(SBE_XIP_ALIGNMENT_ERROR,
+ "Section %d requires %d-byte initial "
+ "alignment but the section offset is %u\n",
+ i, alignment, offset);
+ break;
+ }
+ }
+ if (rc) break;
+
+ // If the TOC exists and the image is normalized, validate each TOC
+ // entry.
+
+ size = hostHeader.iv_section[SBE_XIP_SECTION_TOC].iv_size;
+ if (size != 0) {
+ if (normalized(i_image)) {
+ rc = sbe_xip_map_toc(i_image, validateTocEntry, 0);
+ if (rc) break;
+ }
+ }
+ } while (0);
+ return rc;
+}
+
+
+// Normalization:
+//
+// 1. Normalize the TOC, unless the image is already normalized. The image
+// must be marked as normalized before sorting.
+//
+// 2. Sort the TOC.
+//
+// 3. Clear the section offsets of any empty sections to make the section
+// table reports less confusing.
+//
+// 4. Clear normalization status on any failure.
+
+int
+sbe_xip_normalize(void* io_image)
+{
+ int rc, i;
+ SbeXipSection section;
+ SbeXipToc* imageToc;
+ size_t entries;
+
+ do {
+ rc = quickCheck(io_image, 0);
+ if (rc) break;
+
+ if (!normalized(io_image)) {
+ rc = getToc(io_image, &imageToc, &entries, 0, 0);
+ if (rc) break;
+ for (; entries--; imageToc++) {
+ rc = normalizeToc(io_image, imageToc);
+ if (rc) break;
+ }
+ if (rc) break;
+ ((SbeXipHeader*)io_image)->iv_normalized = 1;
+ }
+
+ rc = sortToc(io_image);
+ if (rc) break;
+
+ for (i = 0; i < SBE_XIP_SECTIONS; i++) {
+ rc = sbe_xip_get_section(io_image, i, &section);
+ if (rc) break;
+ if (section.iv_size == 0) {
+ setSectionOffset(io_image, i, 0);
+ }
+ }
+ if (rc) break;
+
+ } while(0);
+
+ ((SbeXipHeader*)io_image)->iv_normalized = (rc == 0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_image_size(void* io_image, uint32_t* o_size)
+{
+ int rc;
+
+ rc = quickCheck(io_image, 0);
+ if (!rc) {
+ *o_size = imageSize(io_image);
+ }
+ return rc;
+}
+
+
+int
+sbe_xip_get_section(const void* i_image,
+ const int i_sectionId,
+ SbeXipSection* o_hostSection)
+{
+ int rc;
+ SbeXipSection *imageSection;
+
+ rc = getSectionPointer(i_image, i_sectionId, &imageSection);
+
+ if (!rc) {
+ translateSection(o_hostSection, imageSection);
+ }
+
+ return rc;
+}
+
+
+int
+sbe_xip_find(void* i_image,
+ const char* i_id,
+ SbeXipItem* o_item)
+{
+ int rc;
+ SbeXipToc* toc;
+ SbeXipItem item, *pitem;
+
+ do {
+ rc = quickCheck(i_image, 1);
+ if (rc) break;
+
+ if (sorted(i_image)) {
+ rc = binarySearch(i_image, i_id, &toc);
+ } else {
+ rc = linearSearch(i_image, i_id, &toc);
+ }
+ if (rc) break;
+
+ if (o_item) {
+ pitem = o_item;
+ } else {
+ pitem = &item;
+ }
+ rc = decodeToc(i_image, toc, pitem);
+ if (rc) break;
+
+ } while (0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_map_halt(void* io_image,
+ int (*i_fn)(void* io_image,
+ const uint64_t i_poreAddress,
+ const char* i_rcString,
+ void* io_arg),
+ void* io_arg)
+{
+ int rc;
+ SbeXipSection haltSection;
+ SbeXipHalt *halt;
+ uint32_t size;
+ uint32_t actualSize;
+
+ do {
+ rc = quickCheck(io_image, 0);
+ if (rc) break;
+
+ rc = sbe_xip_get_section(io_image, SBE_XIP_SECTION_HALT, &haltSection);
+ if (rc) break;
+
+ halt = (SbeXipHalt*)((unsigned long)io_image + haltSection.iv_offset);
+ size = haltSection.iv_size;
+
+ while (size) {
+
+ rc = i_fn(io_image,
+ revle64(halt->iv_address),
+ halt->iv_string,
+ io_arg);
+ if (rc) break;
+
+ // The SbeXipHalt structure claims a 4-character string. The
+ // computation below computes the actual record size based on the
+ // actual length of the string, including the 0-byte termination.
+
+ actualSize = 8 + (((strlen(halt->iv_string) + 4) / 4) * 4);
+
+ if (size < actualSize) {
+ rc = TRACE_ERRORX(SBE_XIP_IMAGE_ERROR,
+ "The .halt section is improperly formed\n");
+ break;
+ }
+
+ size -= actualSize;
+ halt = (SbeXipHalt*)((unsigned long)halt + actualSize);
+ };
+
+ if (rc) break;
+
+ } while (0);
+
+ return rc;
+}
+
+
+typedef struct {
+ uint64_t iv_address;
+ const char* iv_string;
+} GetHaltStruct;
+
+
+static int
+getHaltMap(void* io_image,
+ const uint64_t i_poreAddress,
+ const char* i_rcString,
+ void* io_arg)
+{
+ int rc;
+
+ GetHaltStruct* s = (GetHaltStruct*)io_arg;
+
+ if (i_poreAddress == s->iv_address) {
+ s->iv_string = i_rcString;
+ rc = -1;
+ } else {
+ rc = 0;
+ }
+
+ return rc;
+}
+
+
+int
+sbe_xip_get_halt(void* io_image,
+ const uint64_t i_poreAddress,
+ const char** o_rcString)
+{
+ int rc;
+ GetHaltStruct s;
+
+ s.iv_address = i_poreAddress;
+ do {
+ rc = quickCheck(io_image, 0);
+ if (rc) break;
+
+ rc = sbe_xip_map_halt(io_image, getHaltMap, &s);
+ if (rc == 0) {
+ rc = TRACE_ERRORX(SBE_XIP_ITEM_NOT_FOUND,
+ "sbe_xip_get_halt: No HALT code is associated "
+ "with address " F0x012llx "\n", i_poreAddress);
+ } else if (rc < 0) {
+ *o_rcString = s.iv_string;
+ rc = 0;
+ }
+ } while (0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_get_scalar(void *i_image, const char* i_id, uint64_t* o_data)
+{
+ int rc;
+ SbeXipItem item;
+
+ rc = sbe_xip_find(i_image, i_id, &item);
+ if (!rc) {
+ switch (item.iv_type) {
+ case SBE_XIP_UINT8:
+ *o_data = *((uint8_t*)(item.iv_imageData));
+ break;
+ case SBE_XIP_UINT32:
+ *o_data = revle32(*((uint32_t*)(item.iv_imageData)));
+ break;
+ case SBE_XIP_UINT64:
+ *o_data = revle64(*((uint64_t*)(item.iv_imageData)));
+ break;
+ case SBE_XIP_ADDRESS:
+ *o_data = item.iv_address;
+ break;
+ default:
+ rc = TRACE_ERROR(SBE_XIP_TYPE_ERROR);
+ break;
+ }
+ }
+ return rc;
+}
+
+
+int
+sbe_xip_get_element(void *i_image,
+ const char* i_id,
+ const uint32_t i_index,
+ uint64_t* o_data)
+{
+ int rc;
+ SbeXipItem item;
+
+ do {
+ rc = sbe_xip_find(i_image, i_id, &item);
+ if (rc) break;
+
+ if ((item.iv_elements != 0) && (i_index >= item.iv_elements)) {
+ rc = TRACE_ERROR(SBE_XIP_BOUNDS_ERROR);
+ break;
+ }
+
+ switch (item.iv_type) {
+ case SBE_XIP_UINT8:
+ *o_data = ((uint8_t*)(item.iv_imageData))[i_index];
+ break;
+ case SBE_XIP_UINT32:
+ *o_data = revle32(((uint32_t*)(item.iv_imageData))[i_index]);
+ break;
+ case SBE_XIP_UINT64:
+ *o_data = revle64(((uint64_t*)(item.iv_imageData))[i_index]);
+ break;
+ default:
+ rc = TRACE_ERROR(SBE_XIP_TYPE_ERROR);
+ break;
+ }
+ if (rc) break;
+
+ } while (0);
+ return rc;
+}
+
+
+int
+sbe_xip_get_string(void *i_image, const char* i_id, char** o_data)
+{
+ int rc;
+ SbeXipItem item;
+
+ rc = sbe_xip_find(i_image, i_id, &item);
+ if (!rc) {
+ switch (item.iv_type) {
+ case SBE_XIP_STRING:
+ *o_data = (char*)(item.iv_imageData);
+ break;
+ default:
+ rc = TRACE_ERROR(SBE_XIP_TYPE_ERROR);
+ break;
+ }
+ }
+ return rc;
+}
+
+
+int
+sbe_xip_read_uint64(const void *i_image,
+ const uint64_t i_poreAddress,
+ uint64_t* o_data)
+{
+ int rc;
+
+ do {
+ rc = quickCheck(i_image, 0);
+ if (rc) break;
+
+ rc = validatePoreAddress(i_image, i_poreAddress, 8);
+ if (rc) break;
+
+ if (i_poreAddress % 8) {
+ rc = TRACE_ERROR(SBE_XIP_ALIGNMENT_ERROR);
+ break;
+ }
+
+ *o_data =
+ revle64(*((uint64_t*)pore2Host(i_image, i_poreAddress)));
+
+ } while(0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_set_scalar(void* io_image, const char* i_id, const uint64_t i_data)
+{
+ int rc;
+ SbeXipItem item;
+
+ rc = sbe_xip_find(io_image, i_id, &item);
+ if (!rc) {
+ switch(item.iv_type) {
+ case SBE_XIP_UINT8:
+ *((uint8_t*)(item.iv_imageData)) = (uint8_t)i_data;
+ break;
+ case SBE_XIP_UINT32:
+ *((uint32_t*)(item.iv_imageData)) = revle32((uint32_t)i_data);
+ break;
+ case SBE_XIP_UINT64:
+ *((uint64_t*)(item.iv_imageData)) = revle64((uint64_t)i_data);
+ break;
+ default:
+ rc = TRACE_ERROR(SBE_XIP_TYPE_ERROR);
+ break;
+ }
+ }
+ return rc;
+}
+
+
+int
+sbe_xip_set_element(void *i_image,
+ const char* i_id,
+ const uint32_t i_index,
+ const uint64_t i_data)
+{
+ int rc;
+ SbeXipItem item;
+
+ do {
+ rc = sbe_xip_find(i_image, i_id, &item);
+ if (rc) break;
+
+ if ((item.iv_elements != 0) && (i_index >= item.iv_elements)) {
+ rc = TRACE_ERROR(SBE_XIP_BOUNDS_ERROR);
+ break;
+ }
+
+ switch (item.iv_type) {
+ case SBE_XIP_UINT8:
+ ((uint8_t*)(item.iv_imageData))[i_index] = (uint8_t)i_data;
+ break;
+ case SBE_XIP_UINT32:
+ ((uint32_t*)(item.iv_imageData))[i_index] =
+ revle32((uint32_t)i_data);
+ break;
+ case SBE_XIP_UINT64:
+ ((uint64_t*)(item.iv_imageData))[i_index] =
+ revle64((uint64_t)i_data);
+ break;
+ default:
+ rc = TRACE_ERROR(SBE_XIP_TYPE_ERROR);
+ break;
+ }
+ if (rc) break;
+
+ } while (0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_set_string(void *i_image, const char* i_id, const char* i_data)
+{
+ int rc;
+ SbeXipItem item;
+ char* dest;
+
+ rc = sbe_xip_find(i_image, i_id, &item);
+ if (!rc) {
+ switch (item.iv_type) {
+ case SBE_XIP_STRING:
+ dest = (char*)(item.iv_imageData);
+ if (strlen(dest) < strlen(i_data)) {
+ memcpy(dest, i_data, strlen(dest));
+ } else {
+ strcpy(dest, i_data);
+ }
+ break;
+ default:
+ rc = TRACE_ERROR(SBE_XIP_TYPE_ERROR);
+ break;
+ }
+ }
+ return rc;
+}
+
+
+int
+sbe_xip_write_uint64(void *io_image,
+ const uint64_t i_poreAddress,
+ const uint64_t i_data)
+{
+ int rc;
+
+ do {
+ rc = quickCheck(io_image, 0);
+ if (rc) break;
+
+ rc = validatePoreAddress(io_image, i_poreAddress, 8);
+ if (rc) break;
+
+ if (i_poreAddress % 8) {
+ rc = TRACE_ERROR(SBE_XIP_ALIGNMENT_ERROR);
+ break;
+ }
+
+ *((uint64_t*)pore2Host(io_image, i_poreAddress)) = revle64(i_data);
+
+ } while(0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_delete_section(void* io_image, const int i_sectionId)
+{
+ int rc, final;
+ SbeXipSection section;
+
+ do {
+ rc = quickCheck(io_image, 1);
+ if (rc) break;
+
+ rc = sbe_xip_get_section(io_image, i_sectionId, &section);
+ if (rc) break;
+
+
+ // Deleting an empty section is a NOP. Otherwise the section must be
+ // the final section of the image. Update the sizes and re-establish
+ // the final image alignment.
+
+ if (section.iv_size == 0) break;
+
+ rc = finalSection(io_image, &final);
+ if (rc) break;
+
+ if (final != i_sectionId) {
+ rc = TRACE_ERRORX(SBE_XIP_SECTION_ERROR,
+ "Attempt to delete non-final section %d\n",
+ i_sectionId);
+ break;
+ }
+
+ setImageSize(io_image, section.iv_offset);
+ setSectionOffset(io_image, i_sectionId, 0);
+ setSectionSize(io_image, i_sectionId, 0);
+
+ finalAlignment(io_image);
+
+ } while (0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_duplicate_section(const void* i_image,
+ const int i_sectionId,
+ void** o_duplicate,
+ uint32_t* o_size)
+{
+ SbeXipSection section;
+ int rc;
+
+ *o_duplicate = 0;
+
+ do {
+ rc = quickCheck(i_image, 0);
+ if (rc) break;
+
+ rc = sbe_xip_get_section(i_image, i_sectionId, &section);
+ if (rc) break;
+
+ if (section.iv_size == 0) {
+ rc = TRACE_ERRORX(SBE_XIP_SECTION_ERROR,
+ "Attempt to duplicate empty section %d\n",
+ i_sectionId);
+ break;
+ }
+
+ *o_duplicate = malloc(section.iv_size);
+ *o_size = section.iv_size;
+
+ if (*o_duplicate == 0) {
+ rc = TRACE_ERROR(SBE_XIP_NO_MEMORY);
+ break;
+ }
+
+ memcpy(*o_duplicate,
+ hostAddressFromOffset(i_image, section.iv_offset),
+ section.iv_size);
+
+
+ } while (0);
+
+ if (rc) {
+ free(*o_duplicate);
+ *o_duplicate = 0;
+ *o_size = 0;
+ }
+
+ return rc;
+}
+
+
+int
+sbe_xip_append(void* io_image,
+ const int i_sectionId,
+ const void* i_data,
+ const uint32_t i_size,
+ const uint32_t i_allocation,
+ uint32_t* o_sectionOffset)
+{
+ SbeXipSection section;
+ int rc, final;
+ void* hostAddress;
+ uint32_t pad;
+
+ do {
+ rc = quickCheck(io_image, 1);
+ if (rc) break;
+
+ rc = sbe_xip_get_section(io_image, i_sectionId, &section);
+ if (rc) break;
+
+ if (i_size == 0) break;
+
+ if (section.iv_size == 0) {
+
+ // The section is empty, and now becomes the final section. Pad
+ // the image to the specified section alignment. Note that the
+ // size of the previously final section does not change.
+
+ rc = padImage(io_image, i_allocation, section.iv_alignment, &pad);
+ if (rc) break;
+ section.iv_offset = imageSize(io_image);
+
+ } else {
+
+ // Otherwise, the section must be the final section in order to
+ // continue. Remove any padding from the image.
+
+ rc = finalSection(io_image, &final);
+ if (rc) break;
+
+ if (final != i_sectionId) {
+ rc = TRACE_ERRORX(SBE_XIP_SECTION_ERROR,
+ "Attempt to append to non-final section "
+ "%d\n", i_sectionId);
+ break;
+ }
+ setImageSize(io_image, section.iv_offset + section.iv_size);
+ }
+
+
+ // Make sure the allocated space won't overflow. Set the return
+ // parameter o_sectionOffset and copy the new data into the image (or
+ // simply clear the space).
+
+ if ((imageSize(io_image) + i_size) > i_allocation) {
+ rc = TRACE_ERROR(SBE_XIP_WOULD_OVERFLOW);
+ break;
+ }
+ if (o_sectionOffset != 0) {
+ *o_sectionOffset = section.iv_size;
+ }
+
+ hostAddress = hostAddressFromOffset(io_image, imageSize(io_image));
+ if (i_data == 0) {
+ memset(hostAddress, 0, i_size);
+ } else {
+ memcpy(hostAddress, i_data, i_size);
+ }
+
+
+ // Update the image size and section table.
+
+ setImageSize(io_image, imageSize(io_image) + i_size);
+ finalAlignment(io_image);
+
+ section.iv_size += i_size;
+ rc = putSection(io_image, i_sectionId, &section);
+ if (rc) break;
+
+
+ // Special case
+
+ if (i_sectionId == SBE_XIP_SECTION_TOC) {
+ ((SbeXipHeader*)io_image)->iv_tocSorted = 0;
+ }
+
+ } while (0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_section2pore(const void* i_image,
+ const int i_sectionId,
+ const uint32_t i_offset,
+ uint64_t* o_poreAddress)
+{
+ int rc;
+ SbeXipSection section;
+
+ do {
+ rc = quickCheck(i_image, 0);
+ if (rc) break;
+
+ rc = sbe_xip_get_section(i_image, i_sectionId, &section);
+ if (rc) break;
+
+ if (section.iv_size == 0) {
+ rc = TRACE_ERROR(SBE_XIP_SECTION_ERROR);
+ break;
+ }
+
+ if (i_offset > (section.iv_offset + section.iv_size)) {
+ rc = TRACE_ERROR(SBE_XIP_INVALID_ARGUMENT);
+ break;
+ }
+
+ *o_poreAddress = linkAddress(i_image) + section.iv_offset + i_offset;
+
+ if (*o_poreAddress % 4) {
+ rc = TRACE_ERROR(SBE_XIP_ALIGNMENT_ERROR);
+ break;
+ }
+
+ } while(0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_pore2section(const void* i_image,
+ const uint64_t i_poreAddress,
+ int* i_section,
+ uint32_t* i_offset)
+{
+ int rc;
+
+ do {
+ rc = quickCheck(i_image, 0);
+ if (rc) break;
+
+ rc = pore2Section(i_image, i_poreAddress, i_section, i_offset);
+
+ } while(0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_pore2host(const void* i_image,
+ const uint64_t i_poreAddress,
+ void** o_hostAddress)
+{
+ int rc;
+
+ do {
+ rc = quickCheck(i_image, 0);
+ if (rc) break;
+
+ if ((i_poreAddress < linkAddress(i_image)) ||
+ (i_poreAddress > (linkAddress(i_image) + imageSize(i_image)))) {
+ rc = TRACE_ERROR(SBE_XIP_INVALID_ARGUMENT);
+ break;
+ }
+
+ *o_hostAddress =
+ hostAddressFromOffset(i_image,
+ i_poreAddress - linkAddress(i_image));
+ } while(0);
+
+ return rc;
+}
+
+
+int
+sbe_xip_host2pore(const void* i_image,
+ void* i_hostAddress,
+ uint64_t* o_poreAddress)
+{
+ int rc;
+
+ do {
+ rc = quickCheck(i_image, 0);
+ if (rc) break;
+
+ if ((i_hostAddress < i_image) ||
+ (i_hostAddress > hostAddressFromOffset(i_image, imageSize(i_image)))) {
+ rc = TRACE_ERROR(SBE_XIP_INVALID_ARGUMENT);
+ break;
+ }
+
+ *o_poreAddress = linkAddress(i_image) +
+ ((unsigned long)i_hostAddress - (unsigned long)i_image);
+ if (*o_poreAddress % 4) {
+ rc = TRACE_ERROR(SBE_XIP_ALIGNMENT_ERROR);
+ break;
+ }
+ } while(0);
+
+ return rc;
+}
+
+
+void
+sbe_xip_translate_header(SbeXipHeader* o_dest, const SbeXipHeader* i_src)
+{
+#ifndef _BIG_ENDIAN
+ int i;
+ SbeXipSection* destSection;
+ const SbeXipSection* srcSection;
+
+#if SBE_XIP_HEADER_VERSION != 7
+#error This code assumes the SBE-XIP header version 7 layout
+#endif
+
+ o_dest->iv_magic = revle64(i_src->iv_magic);
+ o_dest->iv_entryOffset = revle64(i_src->iv_entryOffset);
+ o_dest->iv_linkAddress = revle64(i_src->iv_linkAddress);
+
+ for (i = 0; i < 5; i++) {
+ o_dest->iv_reserved64[i] = 0;
+ }
+
+ for (i = 0, destSection = o_dest->iv_section,
+ srcSection = i_src->iv_section;
+ i < SBE_XIP_SECTIONS;
+ i++, destSection++, srcSection++) {
+ translateSection(destSection, srcSection);
+ }
+
+ o_dest->iv_imageSize = revle32(i_src->iv_imageSize);
+ o_dest->iv_buildDate = revle32(i_src->iv_buildDate);
+ o_dest->iv_buildTime = revle32(i_src->iv_buildTime);
+
+ for (i = 0; i < 5; i++) {
+ o_dest->iv_reserved32[i] = 0;
+ }
+
+ o_dest->iv_headerVersion = i_src->iv_headerVersion;
+ o_dest->iv_normalized = i_src->iv_normalized;
+ o_dest->iv_tocSorted = i_src->iv_tocSorted;
+
+ for (i = 0; i < 3; i++) {
+ o_dest->iv_reserved8[i] = 0;
+ }
+
+ memcpy(o_dest->iv_buildUser, i_src->iv_buildUser,
+ sizeof(i_src->iv_buildUser));
+ memcpy(o_dest->iv_buildHost, i_src->iv_buildHost,
+ sizeof(i_src->iv_buildHost));
+ memcpy(o_dest->iv_reservedChar, i_src->iv_reservedChar,
+ sizeof(i_src->iv_reservedChar));
+
+#else
+ if (o_dest != i_src) {
+ *o_dest = *i_src;
+ }
+#endif /* _BIG_ENDIAN */
+}
+
+
+int
+sbe_xip_map_toc(void* io_image,
+ int (*i_fn)(void* io_image,
+ const SbeXipItem* i_item,
+ void* io_arg),
+ void* io_arg)
+{
+ int rc;
+ SbeXipToc *imageToc;
+ SbeXipItem item;
+ size_t entries;
+
+ do {
+ rc = quickCheck(io_image, 0);
+ if (rc) break;
+
+ rc = getToc(io_image, &imageToc, &entries, 0, 0);
+ if (rc) break;
+
+ for (; entries--; imageToc++) {
+ rc = decodeToc(io_image, imageToc, &item);
+ if (rc) break;
+ rc = i_fn(io_image, &item, io_arg);
+ if (rc) break;
+ }
+ } while(0);
+
+ return rc;
+}
+
+
+
+
+
+
+
diff --git a/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h
new file mode 100644
index 000000000..081f368e8
--- /dev/null
+++ b/src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h
@@ -0,0 +1,1679 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/usr/hwpf/hwp/build_winkle_images/proc_slw_build/sbe_xip_image.h $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+#ifndef __SBE_XIP_IMAGE_H
+#define __SBE_XIP_IMAGE_H
+
+// $Id: sbe_xip_image.h,v 1.15 2012/05/22 03:26:27 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/sbe/sbe_xip_image.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+// *! OWNER NAME: Bishop Brock Email: bcbrock@us.ibm.com
+//------------------------------------------------------------------------------
+
+/// \file sbe_xip_image.h
+/// \brief Everything related to creating and manipulating SBE-XIP binary
+/// images.
+
+#include "fapi_sbe_common.H"
+
+/// Current version (fields, layout, sections) of the SBE_XIP header
+///
+/// If any changes are made to this file or to sbe_xip_header.H, please update
+/// the header version and follow-up on all of the error messages.
+
+#define SBE_XIP_HEADER_VERSION 7
+
+/// \defgroup sbe_xip_magic_numbers SBE-XIP magic numbers
+///
+/// An SBE-XIP magic number is a 64-bit constant. The 4 high-order bytes
+/// contain the ASCII characters "XIP " and identify the image as an SBE-XIP
+/// image, while the 4 low-order bytes identify the type of the image.
+///
+/// @{
+
+#define SBE_XIP_MAGIC 0x58495020 // "XIP "
+#define SBE_BASE_MAGIC ULL(0x5849502042415345) // "XIP BASE"
+#define SBE_SEEPROM_MAGIC ULL(0x584950205345504d) // "XIP SEPM"
+#define SBE_CENTAUR_MAGIC ULL(0x58495020434e5452) // "XIP CNTR"
+
+/// @}
+
+
+/// \defgroup sbe_xip_sections SBE-XIP Image Section Indexes
+///
+/// These constants define the order that the SbeXipSection structures appear
+/// in the header, which is not necessarily the order the sections appear in
+/// the binary image. Given that SBE-XIP image contents are tightly
+/// controlled, we use this simple indexing scheme for the allowed sections
+/// rather than a more general approach, e.g., allowing arbitrary sections
+/// identified by their names.
+///
+/// @{
+
+// -*- DO NOT REORDER OR EDIT THIS SET OF CONSTANTS WITHOUT ALSO EDITING -*-
+// -*- THE ASSEMBLER LAYOUT IN sbe_xip_header.S. -*-
+
+#define SBE_XIP_SECTION_HEADER 0
+#define SBE_XIP_SECTION_FIXED 1
+#define SBE_XIP_SECTION_IPL_TEXT 2
+#define SBE_XIP_SECTION_IPL_DATA 3
+#define SBE_XIP_SECTION_TEXT 4
+#define SBE_XIP_SECTION_DATA 5
+#define SBE_XIP_SECTION_TOC 6
+#define SBE_XIP_SECTION_STRINGS 7
+#define SBE_XIP_SECTION_PIBMEM0 8
+#define SBE_XIP_SECTION_PIBMEM1 9
+#define SBE_XIP_SECTION_RINGS 10
+#define SBE_XIP_SECTION_HALT 11
+#define SBE_XIP_SECTION_SLW 12
+#define SBE_XIP_SECTION_RESERVED_2 13
+#define SBE_XIP_SECTION_RESERVED_1 14
+#define SBE_XIP_SECTION_RESERVED_0 15
+
+#define SBE_XIP_SECTIONS 16
+
+/// @}
+
+#ifndef __ASSEMBLER__
+
+/// Applications can expand this macro to create an array of section names.
+#define SBE_XIP_SECTION_NAMES(var) \
+ const char* var[] = { \
+ ".header", \
+ ".fixed", \
+ ".ipl_text", \
+ ".ipl_data", \
+ ".text", \
+ ".data", \
+ ".toc", \
+ ".strings", \
+ ".pibmem0", \
+ ".pibmem1", \
+ ".rings", \
+ ".halt", \
+ ".slw", \
+ ".reserved_2", \
+ ".reserved_1", \
+ ".reserved_0" \
+ }
+
+/// Applications can use this macro to safely index the array of section
+/// names.
+#define SBE_XIP_SECTION_NAME(var, n) \
+ ((((n) < 0) || ((n) > (int)(sizeof(var) / sizeof(char*)))) ? \
+ "Bug : Invalid SBE-XIP section name" : var[n])
+
+
+#endif /* __ASSEMBLER__ */
+
+
+/// Maximum section alignment for SBE-XIP sections
+#define SBE_XIP_MAX_SECTION_ALIGNMENT 128
+
+/// defgroup sbe_xip_toc_types SBE-XIP Table of Contents data types
+///
+/// These are the data types stored in the \a iv_type field of the SbeXipToc
+/// objects. These must be defined as manifest constants because they are
+/// required to be recognized as manifest constants in C (as opposed to C++)
+/// code.
+///
+/// NB: The 0x0 code is purposefully left undefined to catch bugs.
+///
+/// @{
+
+/// Data is a single unsigned byte
+#define SBE_XIP_UINT8 0x01
+
+/// Data is a 32-bit unsigned integer
+#define SBE_XIP_UINT32 0x02
+
+/// Data is a 64-bit unsigned integer
+#define SBE_XIP_UINT64 0x03
+
+/// Data is a 0-byte terminated ASCII string
+#define SBE_XIP_STRING 0x04
+
+/// Data is an address
+#define SBE_XIP_ADDRESS 0x05
+
+/// The maximum type number
+#define SBE_XIP_MAX_TYPE_INDEX 0x05
+
+/// Applications can expand this macro to get access to string forms of the
+/// SBE-XIP data types if desired.
+#define SBE_XIP_TYPE_STRINGS(var) \
+ const char* var[] = { \
+ "Illegal 0 Code", \
+ "SBE_XIP_UINT8", \
+ "SBE_XIP_UINT32", \
+ "SBE_XIP_UINT64", \
+ "SBE_XIP_STRING", \
+ "SBE_XIP_ADDRESS", \
+ }
+
+/// Applications can expand this macro to get access to abbreviated string
+/// forms of the SBE-XIP data types if desired.
+#define SBE_XIP_TYPE_ABBREVS(var) \
+ const char* var[] = { \
+ "Illegal 0 Code", \
+ "u8 ", \
+ "u32", \
+ "u64", \
+ "str", \
+ "adr", \
+ }
+
+/// Applications can use this macro to safely index either array of SBE-XIP
+/// type strings.
+#define SBE_XIP_TYPE_STRING(var, n) \
+ (((n) > (sizeof(var) / sizeof(char*))) ? \
+ "Invalid SBE-XIP type specification" : var[n])
+
+/// @}
+
+
+/// Final alignment constraint for SBE-XIP images.
+///
+/// PORE images are required to be multiples of 8 bytes in length, to
+/// gaurantee that the PoreVe will be able to complete any 8-byte load/store.
+#define SBE_XIP_FINAL_ALIGNMENT 8
+
+
+////////////////////////////////////////////////////////////////////////////
+// C Definitions
+////////////////////////////////////////////////////////////////////////////
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if 0
+} /* So __cplusplus doesn't mess w/auto-indent */
+#endif
+
+/// SBE-XIP Section information
+///
+/// This structure defines the data layout of section table entries in the
+/// SBE-XIP image header.
+
+// -*- DO NOT REORDER OR EDIT THIS STRUCTURE DEFINITION WITHOUT ALSO -*-
+// -*- EDITING THE ASSEMBLER LAYOUT IN sbe_xip_header.H -*-
+
+typedef struct {
+
+ /// The offset (in bytes) of the section from the beginning of the image
+ ///
+ /// In normalized images the section offset will always be 0 if the
+ /// section size is also 0.
+ uint32_t iv_offset;
+
+ /// The size of the section in bytes, exclusive of alignment padding
+ ///
+ /// This is the size of the program-significant data in the section,
+ /// exclusive of any alignment padding or reserved or extra space. The
+ /// alignment padding (reserved space) is not represented explicitly, but
+ /// is only implied by the offset of any subsequent non-empty section, or
+ /// in the case of the final section in the image, the image size.
+ ///
+ /// Regardless of the \a iv_offset, if the \a iv_size of a section is 0 it
+ /// should be considered "not present" in the image. In normalized images
+ /// the section offset will always be 0 if the section size is also 0.
+ uint32_t iv_size;
+
+ /// The required initial alignment for the section offset
+ ///
+ /// The PORE and the applications using SBE-XIP images have strict
+ /// alignment/padding requirements. The PORE does not handle any type of
+ /// unaligned instruction or data fetches. Some sections and subsections
+ /// must also be POWER cache-line aligned. The \a iv_alignment applies to
+ /// the first byte of the section. PORE images are also required to be
+ /// multiples of 8 bytes in length, to gaurantee that the PoreVe will be
+ /// able to complete any 8-byte load/store. These constraints are checked
+ /// by sbe_xip_validate() and enforced by sbe_xip_append(). The alignment
+ /// constraints may force a section to be padded, which may create "holes"
+ /// in the image as explained in the comments for the \a iv_size field.
+ ///
+ /// Note that alignment constraints are always checked relative to the
+ /// first byte of the image for in-memory images, not relative to the host
+ /// address. Alignment specifications are required to be a power-of-2.
+ uint8_t iv_alignment;
+
+ /// Reserved structure alignment padding; Pad to 12 bytes
+ uint8_t iv_reserved8[3];
+
+} SbeXipSection;
+
+/// The SbeXipSection structure is created by assembler code and is expected
+/// to have the same size in C code. This constraint is checked in
+/// sbe_xip_validate().
+#define SIZE_OF_SBE_XIP_SECTION 12
+
+
+/// SBE-XIP binary image header
+///
+/// This header occupies the initial bytes of an SBE-XIP binary image.
+/// The header contents are documented here, however the structure is actually
+/// defined in the file sbe_xip_header.S, and these two definitions must be
+/// kept consistent.
+///
+/// The header is a fixed-format representation of the most critical
+/// information about the image. The large majority of information about the
+/// image and its contents are available through the searchable table of
+/// contents. PORE code itself normally accesses the data directly through
+/// global symbols.
+///
+/// The header only contains information 1) required by OTPROM code (e.g., the
+/// entry point); 2) required by search and updating APIs (e.g., the
+/// locations and sizes of all of the sections.); a few pieces of critical
+/// meta-data (e.g., information about the image build process).
+///
+/// Any entries that are accessed by PORE code are required to be 64 bits, and
+/// will appear at the beginning of the header.
+///
+/// The header also contains bytewise offsets and sizes of all of the sections
+/// that are assembled to complete the image. The offsets are relative to the
+/// start of the image (where the header is loaded). The sizes include any
+/// padding inserted by the link editor to guarantee section alignment.
+///
+/// Every field of the header is also accesssible through the searchable table
+/// of contents as documented in sbe_xip_header.S.
+
+// -*- DO NOT REORDER OR EDIT THIS STRUCTURE DEFINITION WITHOUT ALSO -*-
+// -*- EDITING THE ASSEMBLER LAYOUT IN sbe_xip_header.S, AND WITHOUT -*-
+// -*- UPDATING THE sbe_xip_translate_header() API IN sbe_xip_image.c. -*-
+
+typedef struct {
+
+ //////////////////////////////////////////////////////////////////////
+ // Identification - 8-byte aligned; 8 entries
+ //////////////////////////////////////////////////////////////////////
+
+ /// Contains SBE_XIP_MAGIC to identify an SBE-XIP image
+ uint64_t iv_magic;
+
+ /// The offset of the SBE-XIP entry point from the start of the image
+ uint64_t iv_entryOffset;
+
+ /// The base address used to link the image, as a full relocatable PORE
+ /// address
+ uint64_t iv_linkAddress;
+
+ /// Reserved for future expansion
+ uint64_t iv_reserved64[5];
+
+ //////////////////////////////////////////////////////////////////////
+ // Section Table - 4-byte aligned; 16 entries
+ //////////////////////////////////////////////////////////////////////
+
+ SbeXipSection iv_section[SBE_XIP_SECTIONS];
+
+ //////////////////////////////////////////////////////////////////////
+ // Other information - 4-byte aligned; 8 entries
+ //////////////////////////////////////////////////////////////////////
+
+ /// The size of the image (including padding) in bytes
+ uint32_t iv_imageSize;
+
+ /// Build date generated by `date +%Y%m%d`, e.g., 20110630
+ uint32_t iv_buildDate;
+
+ /// Build time generated by `date +%H%M`, e.g., 0756
+ uint32_t iv_buildTime;
+
+ /// Reserved for future expansion
+ uint32_t iv_reserved32[5];
+
+ //////////////////////////////////////////////////////////////////////
+ // Other Information - 1-byte aligned; 8 entries
+ //////////////////////////////////////////////////////////////////////
+
+ /// Header format version number
+ uint8_t iv_headerVersion;
+
+ /// Indicates whether the image has been normalized (0/1)
+ uint8_t iv_normalized;
+
+ /// Indicates whether the TOC has been sorted to speed searching (0/1)
+ uint8_t iv_tocSorted;
+
+ /// Reserved for future expansion
+ uint8_t iv_reserved8[5];
+
+ //////////////////////////////////////////////////////////////////////
+ // Strings; 64 characters allocated
+ //////////////////////////////////////////////////////////////////////
+
+ /// Build user, generated by `id -un`
+ char iv_buildUser[16];
+
+ /// Build host, generated by `hostname`
+ char iv_buildHost[24];
+
+ /// Reserved for future expansion
+ char iv_reservedChar[24];
+
+} SbeXipHeader;
+
+
+/// A C-structure form of the SBE-XIP Table of Contents (TOC) entries
+///
+/// The .toc section consists entirely of an array of these structures.
+/// TOC entries are never accessed by PORE code.
+///
+/// These structures store indexing information for global data required to be
+/// manipulated by external tools. The actual data is usually allocated in a
+/// data section and manipulated by the SBE code using global or local symbol
+/// names. Each TOC entry contains a pointer to a keyword string naming the
+/// data, the address of the data (or the data itself), the data type,
+/// meta-information about the data, and for vectors the vector size.
+
+// -*- DO NOT REORDER OR EDIT THIS STRUCTURE DEFINITION WITHOUT ALSO -*-
+// -*- EDITING THE ASSEMBLER MACROS (BELOW) THAT CREATE THE TABLE OF -*-
+// -*- CONTENTS ENTRIES. -*-
+
+typedef struct {
+
+ /// A pointer to a 0-byte terminated ASCII string identifying the data.
+ ///
+ /// When allocated by the .xip_toc macro this is a pointer to the string
+ /// form of the symbol name for the global or local symbol associated with
+ /// the data which is allocated in the .strings section. This pointer is
+ /// not aligned.
+ ///
+ /// When the image is normalized this pointer is replaced by the offset of
+ /// the string in the .strings section.
+ uint32_t iv_id;
+
+ /// A 32-bit pointer locating the data
+ ///
+ /// This field is initially populated by the link editor. For scalar,
+ /// vector and string types this is the final relocated address of the
+ /// first byte of the data. For address types, this is the relocated
+ /// address. When the image is normalized, these addresses are converted
+ /// into the equivalent offsets from the beginning of the section holding
+ /// the data.
+ uint32_t iv_data;
+
+ /// The type of the data; See \ref sbe_xip_toc_types.
+ uint8_t iv_type;
+
+ /// The section containing the data; See \ref sbe_xip_sections.
+ uint8_t iv_section;
+
+ /// The number of elements for vector types, otherwise 1 for scalar types
+ /// and addresses.
+ ///
+ /// Vectors are naturally limited in size, e.g. to the number of cores,
+ /// chips in a node, DD-levels etc. If \a iv_elements is 0 then no bounds
+ /// checking is done on get/set accesses of the data.
+ uint8_t iv_elements;
+
+ /// Structure alignment padding; Pad to 12 bytes
+ uint8_t iv_pad;
+
+} SbeXipToc;
+
+/// The SbeXipToc structure is created by assembler code and is expected
+/// to have the same size in C code. This constraint is checked in
+/// sbe_xip_validate().
+#define SIZE_OF_SBE_XIP_TOC 12
+
+
+/// A decoded TOC entry for use by applications
+///
+/// This structure is a decoded form of a normalized TOC entry, filled in by
+/// the sbe_xip_decode_toc() and sbe_xip_find() APIs. This structure is
+/// always returned with data elements in host-endian format.
+///
+/// \note Only special-purpose applications will ever need to use this
+/// structure given that the higher-level APIs sbe_xip_get_*() and
+/// sbe_xip_set_*() are provided and shoudl be used if possible.
+
+typedef struct {
+
+ /// A pointer to the associated TOC entry as it exists in the image
+ SbeXipToc* iv_toc;
+
+ /// The full relocatable PORE address
+ ///
+ /// All relocatable addresses are computed from the \a iv_linkAddress
+ /// stored in the header. For scalar and string data, this is the
+ /// relocatable address of the data. For address-only entries, this is
+ /// the indexed address itself.
+ uint64_t iv_address;
+
+ /// A host pointer to the first byte of text or data within the image
+ ///
+ /// For scalar or string types this is a host pointer to the first byte of
+ /// the data. For code pointers (addresses) this is host pointer to the
+ /// first byte of code. Note that any use of this field requires the
+ /// caller to handle conversion of the data to host endian-ness if
+ /// required. Only 8-bit and string data can be used directly on all
+ /// hosts.
+ void* iv_imageData;
+
+ /// The item name
+ ///
+ /// This is a pointer in host memory to a string that names the TOC entry
+ /// requested. This field is set to a pointer to the ID string of the TOC
+ /// entry inside the image.
+ char* iv_id;
+
+ /// The data type, one of the SBE_XIP_* constants
+ uint8_t iv_type;
+
+ /// The number of elements in a vector
+ ///
+ /// This field is set from the TOC entry when the TOC entry is
+ /// decoded. This value is stored as 1 for scalar declarations, and may be
+ /// set to 0 for vectors with large or undeclared sizes. Otherwise it is
+ /// used to bounds check indexed accesses.
+ uint8_t iv_elements;
+
+} SbeXipItem;
+
+
+/// Prototype entry in the .halt section
+///
+/// The .halt section is generated by the 'reqhalt' macro. This structure
+/// associates the address of each halt with the string form of the FAPI
+/// return code associated with the halt. The string form is used because the
+/// FAPI error return code is not constant. The .halt section is 4-byte
+/// aligned, and each address/string entry is always padded to a multiple of 4
+/// bytes.
+///
+/// In the .halt section the \a iv_string may be any length, thus the size of
+/// each actual record is variable (although guaranteed to always be a
+/// multiple of 4 bytes). Although the C compiler might natuarlly align
+/// instances of this structure on a 64-bit boundary, the APIs that allow
+/// access to the .halt section assume that the underlying machine can do
+/// non-aligned loads from a pointer to this structure.
+
+typedef struct {
+
+ /// The 64-bit relocatable address of the halt
+ ///
+ /// This is the address found in the PC (Status Register bits 16:63) when
+ /// the PORE halts. The full 64-bit form is used rather than the simple
+ /// 32-bit offset to support merging SEEPROM and PIBMEM .halt sections in
+ /// the SEEPROM IPL images.
+ uint64_t iv_address;
+
+ /// A C-prototype for a variable-length 0-terminated ASCII string
+ ///
+ /// This is a prototype only to simplify C programming. The actual string
+ /// may be any length.
+ char iv_string[4];
+
+} SbeXipHalt;
+
+
+/// Validate an SBE-XIP image
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory.
+///
+/// \param[in] i_size The putative size of the image
+///
+/// This API should be called first by all applications that manipulate
+/// SBE-XIP images in host memory. The magic number is validated, and
+/// the image is checked for consistency of the section table and table of
+/// contents. The \a iv_imageSize field of the header must also match the
+/// provided \a i_size parameter. Validation does not modify the image.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_validate(void* i_image, const uint32_t i_size);
+
+
+/// Normalize the SBE-XIP image
+///
+/// \param[in] io_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections.
+///
+/// SBE-XIP images must be normalized before any other APIs are allowed to
+/// operate on the image. Since normalization modifies the image, an explicit
+/// call to normalize the image is required. Briefly, normalization modifies
+/// the TOC entries created by the final link to simplify search, updates,
+/// modification and relocation of the image. Normalization is explained in
+/// the written documentation of the SBE-XIP binary format. Normalization does
+/// not modify the size of the image.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_normalize(void* io_image);
+
+
+/// Return the size of an SBE-XIP image from the image header
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections.
+///
+/// \param[out] o_size A pointer to a variable returned as the size of the
+/// image in bytes, as recorded in the image header.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_image_size(void* i_image, uint32_t* o_size);
+
+
+/// Locate a section table entry and translate into host format
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory.
+///
+/// \param[in] i_sectionId Identifies the section to be queried. See \ref
+/// sbe_xip_sections.
+///
+/// \param[out] o_hostSection Updated to contain the section table entry
+/// translated to host byte order.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_get_section(const void* i_image,
+ const int i_sectionId,
+ SbeXipSection* o_hostSection);
+
+
+/// Endian translation of an SbeXipHeader object
+///
+/// \param[out] o_hostHeader The destination object.
+///
+/// \param[in] i_imageHeader The source object.
+///
+/// Translation of a SbeXipHeader includes translation of all data members
+/// including traslation of the embedded section table. This translation
+/// works even if \a o_src == \a o_dest, i.e., in the destructive case.
+void
+sbe_xip_translate_header(SbeXipHeader* o_hostHeader,
+ const SbeXipHeader* i_imageHeader);
+
+
+/// Get scalar data from an SBE-XIP image
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item
+/// requested.
+///
+/// \param[out] o_data A pointer to an 8-byte integer to receive the scalar
+/// data. Assuming the item is located this variable is assigned by the call.
+/// In the event of an error the final state of \a o_data is not specified.
+///
+/// This API searches the SBE-XIP Table of Contents (TOC) for the item named
+/// \a i_id, assigning \a o_data from the image if the item is found and is a
+/// scalar value. Scalar values include 8- 32- and 64-bit integers and PORE
+/// addresses. Image data smaller than 64 bits are extracted as unsigned
+/// types, and it is the caller's responsibility to cast or convert the
+/// returned data as appropriate.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_get_scalar(void *i_image, const char* i_id, uint64_t* o_data);
+
+
+/// Get an integral element from a vector held in an SBE-XIP image
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item
+/// requested.
+///
+/// \param[in] i_index The index of the vector element to return.
+///
+/// \param[out] o_data A pointer to an 8-byte integer to receive the
+/// data. Assuming the item is located this variable is assigned by the call.
+/// In the event of an error the final state of \a o_data is not specified.
+///
+/// This API searches the SBE-XIP Table of Contents (TOC) for the \a i_index
+/// element of the item named \a i_id, assigning \a o_data from the image if
+/// the item is found, is a vector of an integral type, and the \a i_index is
+/// in bounds. Vector elements smaller than 64 bits are extracted as unsigned
+/// types, and it is the caller's responsibility to cast or convert the
+/// returned data as appropriate.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_get_element(void *i_image,
+ const char* i_id,
+ const uint32_t i_index,
+ uint64_t* o_data);
+
+
+/// Get string data from an SBE-XIP image
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item
+/// requested.
+///
+/// \param[out] o_data A pointer to a character pointer. Assuming the
+/// item is located this variable is assigned by the call to point to the
+/// string as it exists in the \a i_image. In the event of an error the final
+/// state of \a o_data is not specified.
+///
+/// This API searches the SBE-XIP Table of Contents (TOC) for the item named
+/// \a i_id, assigning \a o_data if the item is found and is a string. It is
+/// the caller's responsibility to copy the string from the \a i_image memory
+/// space if necessary.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_get_string(void *i_image, const char* i_id, char** o_data);
+
+
+/// Directly read 64-bit data from the image based on a PORE address
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections.
+///
+/// \param[in] i_poreAddress A relocatable PORE address contained in the
+/// image, presumably of an 8-byte data area. The \a i_poreAddress is
+/// required to be 8-byte aligned, otherwise the SBE_XIP_ALIGNMENT_ERROR code
+/// is returned.
+///
+/// \param[out] o_data The 64 bit data in host format that was found at \a
+/// i_poreAddress.
+///
+/// This API is provided for applications that need to manipulate SBE-XIP
+/// images in terms of their relocatable PORE addresses. The API checks that
+/// the \a i_poreAddress is properly aligned and contained in the image, then
+/// reads the contents of \a i_poreAddress into \a o_data, performing
+/// image-to-host endianess conversion if required.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_read_uint64(const void *i_image,
+ const uint64_t i_poreAddress,
+ uint64_t* o_data);
+
+
+/// Set scalar data in an SBE-XIP image
+///
+/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory.
+/// The image is assumed to be consistent with the information contained in
+/// the header regarding the presence of and sizes of all sections. The image
+/// is also required to have been normalized.
+///
+/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item
+/// to be modified.
+///
+/// \param[in] i_data The new scalar data.
+///
+/// This API searches the SBE-XIP Table of Contents (TOC) for the item named
+/// by \a i_id, updating the image from \a i_data if the item is found, has
+/// a scalar type and can be modified. For this API the scalar types include
+/// 8- 32- and 64-bit integers. Although PORE addresses are considered a
+/// scalar type for sbe_xip_get_scalar(), PORE addresses can not be modified
+/// by this API. The caller is responsible for ensuring that the \a i_data is
+/// of the correct size for the underlying data element in the image.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_set_scalar(void* io_image, const char* i_id, const uint64_t i_data);
+
+
+/// Set an integral element in a vector held in an SBE-XIP image
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item
+/// to be updated.
+///
+/// \param[in] i_index The index of the vector element to update.
+///
+/// \param[out] i_data The new vector element.
+///
+/// This API searches the SBE-XIP Table of Contents (TOC) for the \a i_index
+/// element of the item named \a i_id, update the image from \a i_data if the
+/// item is found, is a vector of an integral type, and the \a i_index is in
+/// bounds. The caller is responsible for ensuring that the \a i_data is of
+/// the correct size for the underlying data element in the image.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_set_element(void *i_image,
+ const char* i_id,
+ const uint32_t i_index,
+ const uint64_t i_data);
+
+
+/// Set string data in an SBE-XIP image
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_id A pointer to a 0-terminated ASCII string naming the item
+/// to be modified.
+///
+/// \param[in] i_data A pointer to the new string data.
+///
+/// This API searches the SBE-XIP Table of Contents (TOC) for the item named
+/// \a i_id, which must be a string variable. If found, then the string data
+/// in the image is overwritten with \a i_data. Strings are held 0-terminated
+/// in the image, and the SBE-XIP format does not maintain a record of the
+/// amount of memory allocated for an individual string. If a string is
+/// overwritten by a shorter string then the 'excess' storage is effectively
+/// lost. If the length of \a i_data is longer that the current strlen() of
+/// the string data then \a i_data is silently truncated to the first
+/// strlen(old_string) characters.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_set_string(void *io_image, const char* i_id, const char* i_data);
+
+
+/// Directly write 64-bit data into the image based on a PORE address
+///
+/// \param[in, out] io_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections.
+///
+/// \param[in] i_poreAddress A relocatable PORE address contained in the
+/// image, presumably of an 8-byte data area. The \a i_poreAddress is
+/// required to be 8-byte aligned, otherwise the SBE_XIP_ALIGNMENT_ERROR code
+/// is returned.
+///
+/// \param[in] i_data The 64 bit data in host format to be written to \a
+/// i_poreAddress.
+///
+/// This API is provided for applications that need to manipulate SBE-XIP
+/// images in terms of their relocatable PORE addresses. The API checks that
+/// the \a i_poreAddress is properly aligned and contained in the image, then
+/// updates the contents of \a i_poreAddress with \a i_data, performing
+/// host-to-image endianess conversion if required.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_write_uint64(void *io_image,
+ const uint64_t i_poreAddress,
+ const uint64_t i_data);
+
+
+/// Map over an SBE-XIP image Table of Contents
+///
+/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_fn A pointer to a function to call on each TOC entry. The
+/// function has the prototype:
+///
+/// \code
+/// int (*i_fn)(void* io_image,
+/// const SbeXipItem* i_item,
+/// void* io_arg)
+/// \endcode
+///
+/// \param[in,out] io_arg The private argument of \a i_fn.
+///
+/// This API iterates over each entry of the TOC, calling \a i_fn with
+/// pointers to the image, an SbeXipItem* pointer, and a private argument. The
+/// iteration terminates either when all TOC entries have been mapped, or \a
+/// i_fn returns a non-zero code.
+///
+/// \retval 0 Success; All TOC entries were mapped, including the case that
+/// the .toc section is empty.
+///
+/// \revtal non-0 May be either one of the SBE-XIP image error codes (see \ref
+/// sbe_xip_image_errors), or a non-zero code from \a i_fn. Since the standard
+/// SBE_XIP return codes are > 0, application-defined codes should be < 0.
+int
+sbe_xip_map_toc(void* io_image,
+ int (*i_fn)(void* io_image,
+ const SbeXipItem* i_item,
+ void* io_arg),
+ void* io_arg);
+
+
+/// Find an SBE-XIP TOC entry
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_id A 0-byte terminated ASCII string naming the item to be
+/// searched for.
+///
+/// \param[out] o_item If the search is successful, then the object
+/// pointed to by \a o_item is filled in with the decoded form of the
+/// TOC entry for \a i_id. If the API returns a non-0 error code then the
+/// final state of the storage at \a o_item is undefined. This parameter may
+/// be suppied as 0, in which case sbe_xip_find() serves as a simple predicate
+/// on whether an item is indexded in the TOC.
+///
+/// This API searches the TOC of a normalized SBE-XIP image for the item named
+/// \a i_id, and if found, fills in the structure pointed to by \a
+/// o_item with a decoded form of the TOC entry. If the item is not found,
+/// the following two return codes may be considered non-error codes:
+///
+/// - SBE_XIP_ITEM_NOT_FOUND : No TOC record for \a i_id was found.
+///
+/// - SBE_XIP_DATA_NOT_PRESENT : The item appears in the TOC, however the
+/// section containing the data is no longer present in the image.
+///
+/// \note This API should not be used unless absolutely necessary. To obtain
+/// data from the image or update data in the image use the sbe_xip_get_*()
+/// and sbe_xip_set_*() APIs respectively whenever possible.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_find(void* i_image,
+ const char* i_id,
+ SbeXipItem* o_item);
+
+
+/// Map over an SBE-XIP image .halt section
+///
+/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections.
+///
+/// \param[in] i_fn A pointer to a function to call on each entry in .halt.
+/// The function has the prototype:
+///
+/// \code
+/// int (*i_fn)(void* io_image,
+/// const uint64_t i_poreAddress,
+/// const char* i_rcString,
+/// void* io_arg)
+///
+/// \param[in,out] io_arg The private argument of \a i_fn.
+///
+/// This API iterates over each entry of the .halt section, calling \a i_fn
+/// with each HALT address, the string form of the return code associated with
+/// that HALT address, and a private argument. The iteration terminates either
+/// when all .halt entries have been mapped, or \a i_fn returns a non-zero
+/// code. The \a i_poreAddddress passed to \a i_fn is the full 48-bit
+/// relocatable PORE address.
+///
+/// \retval 0 Success, including the case that the image has no .halt section.
+///
+/// \revtal non-0 May be either one of the SBE-XIP image error codes (see \ref
+/// sbe_xip_image_errors), or any non-zero code from \a i_fn. Since the
+/// standard SBE_XIP return codes are > 0, application-defined codes should be
+/// < 0.
+int
+sbe_xip_map_halt(void* io_image,
+ int (*i_fn)(void* io_image,
+ const uint64_t i_poreAddress,
+ const char* i_rcString,
+ void* io_arg),
+ void* io_arg);
+
+
+/// Get the string from of a HALT code from an SBE-XIP image .halt section
+///
+/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections.
+///
+/// \param[in] i_poreAddress This is the 48-bit address found in the PC when
+/// the PORE halts. This address is actually 4 bytes beyond the actual HALT
+/// instruction, however for simplicity this is the address used to index the
+/// HALT.
+///
+/// \param[out] o_rcString The caller provides the address of a string-pointer
+/// variable which is updated with a pointer to the string form of the halt
+/// code associated with \a i_poreAddress (assuming a successful completion).
+///
+/// \retval 0 Success
+///
+/// \retval SBE_XIP_ITEM_NOT_FOUND The \a i_poreAddress is not associated
+/// with a halt code in .halt.
+///
+/// \revtal Other See \ref sbe_xip_image_errors
+int
+sbe_xip_get_halt(void* io_image,
+ const uint64_t i_poreAdress,
+ const char** o_rcString);
+
+
+/// Delete a section from an SBE-XIP image in host memory
+///
+/// \param[in,out] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_sectionId Identifies the section to be deleted. See \ref
+/// sbe_xip_sections.
+///
+/// This API effectively deletes a section from an SBE-XIP image held in host
+/// memory. Unless the requested section \a i_section is already empty, only
+/// the final (highest address offset) section of the image may be deleted.
+/// Deleting the final section of the image means that the section size is set
+/// to 0, and the size of the image recorded in the header is reduced by the
+/// section size. This API does not check for or warn if other sections in
+/// the image reference the deleted section.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_delete_section(void* io_image, const int i_sectionId);
+
+
+/// Duplicate a section from an SBE-XIP image in host memory
+///
+/// \param[in,out] i_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections.
+///
+/// \param[in] i_sectionId Identifies the section to be duplicated. See \ref
+/// sbe_xip_sections.
+///
+/// \param[out] o_duplicate At exit, points to the newly allocated and
+/// initialized duplicate of the given section. The caller is responsible for
+/// free()-ing this memory when no longer required.
+///
+/// \param[out] o_size At exit, contains the size (in bytes) of the duplicated
+/// section.
+///
+/// This API creates a bytewise duplicate of a non-empty section into newly
+/// malloc()-ed memory. At exit \a o_duplicate points to the duplicate, and \i
+/// o_size is set the the size of the duplicated section. The caller is
+/// responsible for free()-ing the memory when no longer required. The
+/// pointer at \o_duplicate is set to NULL (0) and teh \a o_size is set to 0
+/// in the event of any failure.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_duplicate_section(const void* i_image,
+ const int i_sectionId,
+ void** o_duplicate,
+ uint32_t* size);
+
+
+/// Append binary data to an SBE-XIP image held in host memory
+///
+/// \param[in,out] io_image A pointer to an SBE-XIP image in host memory. The
+/// image is assumed to be consistent with the information contained in the
+/// header regarding the presence of and sizes of all sections. The image is
+/// also required to have been normalized.
+///
+/// \param[in] i_sectionId Identifies the section to contain the new data.
+///
+/// \param[in] i_data A pointer to the data to be appended to the image. If
+/// this pointer is NULL (0), then the effect is as if \a i_data were a
+/// pointer to an \a i_size array of 0 bytes.
+///
+/// \param[in] i_size The size of the data to be appended in bytes. If \a
+/// i_data is 0, then this is the number of bytes to clear.
+///
+/// \param[in] i_allocation The size of the memory region containing the
+/// image, measured from the first byte of the image. The call will fail if
+/// appending the new data plus any alignment padding would overflow the
+/// allocated memory.
+///
+/// \param[out] o_sectionOffset If non-0 at entry, then the API updates the
+/// location pointed to by \a o_sectionOffset with the offset of the first
+/// byte of the appended data within the indicated section.
+///
+/// This API copies data from \a i_data to the end of the indicated \a
+/// i_section. The section \a i_section must either be empty, or must be the
+/// final (highest address) section in the image. If the section is initially
+/// empty and \a i_size is non-0 then the section is created at the end of the
+/// image. The size of \a i_section and the size of the image are always
+/// adjusted to reflect the newly added data. This is a simple binary copy
+/// without any interpretation (e.g., endian-translation) of the copied data.
+/// The caller is responsible for insuring that the host memory area
+/// containing the SBE-XIP image is large enough to hold the newly appended
+/// data without causing addressing errors or buffer overrun errors.
+///
+/// The final parameter \a o_sectionOffset is optional, and may be passed as
+/// NULL (0) if the application does not require the information. This return
+/// value is provided to simplify typical use cases of this API:
+///
+/// - A scan program is appended to the image, or a run-time data area is
+/// allocated and cleared at the end of the image.
+///
+/// - Pointer variables in the image are updated with PORE addresses obtained
+/// via sbe_xip_section2pore(), or
+/// other procedure code initializes a newly allocated and cleared data area
+/// via host addresses obtained from sbe_xip_section2host().
+///
+/// Regarding alignment, note that the SBE-XIP format requires that sections
+/// maintain an initial alignment that varies by section, and the API will
+/// enforce these alignment constraints for all sections created by the API.
+/// All alignment is relative to the first byte of the image (\a io_image) -
+/// \e not to the current in-memory address of the image. By specification
+/// SBE-XIP images must be loaded at a 4K alignment in order for PORE hardware
+/// relocation to work, however the APIs don't require this 4K alignment for
+/// in-memory manipulation of images. Images to be executed on PoreVe will
+/// normally require at least 8-byte final aligment in order to guarantee that
+/// the PoreVe can execute an 8-byte fetch or load/store of the final
+/// doubleword.
+///
+/// \note If the TOC section is modified then the image is marked as having an
+/// unsorted TOC.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_append(void* io_image,
+ const int i_sectionId,
+ const void* i_data,
+ const uint32_t i_size,
+ const uint32_t i_allocation,
+ uint32_t* o_sectionOffset);
+
+
+/// Convert an SBE-XIP section offset to a relocatable PORE address
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory
+///
+/// \param[in] i_sectionId A valid SBE-XIP section identifier; The section
+/// must be non-empty.
+///
+/// \param[in] i_offset An offset (in bytes) within the section. At least one
+/// byte at \a i_offset must be currently allocated in the section.
+///
+/// \param[in] o_poreAddress The equivalent relocatable PORE address is
+/// returned via this pointer. Since valid PORE addresses are always either
+/// 4-byte (code) or 8-byte (data) aligned, this API checks the aligment of
+/// the translated address and returns SBE_XIP_ALIGNMENT_ERROR if the PORE
+/// address is not at least 4-byte aligned. Note that the translated address
+/// is still returned even if incorrectly aligned.
+///
+/// This API is typically used to translate section offsets returned from
+/// sbe_xip_append() into relocatable PORE addresses.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_section2pore(const void* i_image,
+ const int i_sectionId,
+ const uint32_t i_offset,
+ uint64_t* o_poreAddress);
+
+
+/// Convert an SBE-XIP relocatable PORE address to a host memory address
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory.
+///
+/// \param[in] i_poreAddress A relocatable PORE address putatively addressing
+/// relocatable memory contained in the image.
+///
+/// \param[out] o_hostAddress The API updates the location pointed to by \a
+/// o_hostAddress with the host address of the memory addressed by \a
+/// i_poreAddress. In the event of an error (non-0 return code) the final
+/// content of \a o_hostAddress is undefined.
+///
+/// This API is typically used to translate relocatable PORE addresses stored
+/// in the SBE-XIP image into the equivalent host address of the in-memory
+/// image, allowing host-code to manipulate arbitrary data structures in the
+/// image. If the \a i_poreAddress does not refer to memory within the image
+/// (as determined by the link address and image size) then the
+/// SBE_XIP_INVALID_ARGUMENT error code is returned.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_pore2host(const void* i_image,
+ const uint64_t i_poreAddress,
+ void** o_hostAddress);
+
+
+/// Convert an SBE-XIP relocatable PORE address to section Id and offset
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory.
+///
+/// \param[in] i_poreAddress A relocatable PORE address putatively addressing
+/// relocatable memory contained in the image.
+///
+/// \param[out] o_section The API updates the location pointed to by \a
+/// o_section with the section Id of the memory addressed by \a
+/// i_poreAddress. In the event of an error (non-0 return code) the final
+/// content of \a o_section is undefined.
+///
+/// \param[out] o_offset The API updates the location pointed to by \a
+/// o_offset with the byte offset of the memory addressed by \a i_poreAddress
+/// within \a o_section. In the event of an error (non-0 return code) the
+/// final content of \a o_offset is undefined.
+///
+/// This API is typically used to translate relocatable PORE addresses stored
+/// in the SBE-XIP image into the equivalent section + offset form, allowing
+/// host-code to manipulate arbitrary data structures in the image. If the \a
+/// i_poreAddress does not refer to memory within the image (as determined by
+/// the link address and image size) then the SBE_XIP_INVALID_ARGUMENT error
+/// code is returned.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_pore2section(const void* i_image,
+ const uint64_t i_poreAddress,
+ int* o_section,
+ uint32_t* o_offset);
+
+
+/// Convert an in-memory SBE-XIP host address to a relocatable PORE address
+///
+/// \param[in] i_image A pointer to an SBE-XIP image in host memory
+///
+/// \param[in] i_hostAddress A host address addressing data within the image.
+///
+/// \param[out] o_poreAddress The API updates the location pointed to by \a
+/// o_poreAddress with the equivelent relocatable PORE address of the memory
+/// addressed by i_hostAddress. Since valid PORE addresses are always either
+/// 4-byte (code) or 8-byte (data) aligned, this API checks the aligment of
+/// the translated address and returns SBE_XIP_ALIGNMENT_ERROR if the PORE
+/// address is not at least 4-byte aligned. Note that the translated address
+/// is still returned evn if incorrectly aligned.
+///
+/// This API is provided as a convenient way to convert host memory addresses
+/// for an in-memory SBE-XIP image into PORE addresses correctly relocated for
+/// the image, for example to update pointer variables in the image. If the
+/// \a i_hostAddress does not refer to memory within the image (as determined
+/// by the image address and image size) then the SBE_XIP_INVALID_ARGUMENT
+/// error code is returned.
+///
+/// \retval 0 Success
+///
+/// \retval non-0 See \ref sbe_xip_image_errors
+int
+sbe_xip_host2pore(const void* i_image,
+ void* i_hostAddress,
+ uint64_t* i_poreAddress);
+
+
+/// \defgroup sbe_xip_image_errors Error codes from SBE-XIP image APIs
+///
+/// @{
+
+/// A putative SBE-XIP image does not have the correct magic number, or
+/// contains some other major inconsistency.
+#define SBE_XIP_IMAGE_ERROR 1
+
+/// The TOC may be missing, partially present or may have an alignment problem.
+#define SBE_XIP_TOC_ERROR 2
+
+/// A named item was not found in the SBE-XIP TOC, or a putative HALT address
+/// is not associated with a halt code in .halt.
+#define SBE_XIP_ITEM_NOT_FOUND 3
+
+/// A named item appears in the SBE-XIP TOC, but the data is not present in
+/// the image. This error can occur if sections have been deleted from the
+/// image.
+#define SBE_XIP_DATA_NOT_PRESENT 4
+
+/// A named item appears in the SBE-XIP TOC, but the data can not be
+/// modified. This error will occur if an attempt is made to modify an
+/// address-only entry.
+#define SBE_XIP_CANT_MODIFY 5
+
+/// A direct or implied argument is invalid, e.g. an illegal data type or
+/// section identifier, or an address not contained within the image.
+#define SBE_XIP_INVALID_ARGUMENT 6
+
+/// A data type mismatch or an illegal type was specified or implied for an
+/// operation.
+#define SBE_XIP_TYPE_ERROR 8
+
+/// A bug in an SBE-XIP image API
+#define SBE_XIP_BUG 8
+
+/// The image must first be normalized with sbe_xip_normalize().
+#define SBE_XIP_NOT_NORMALIZED 9
+
+/// Attempt to delete a non-empty section that is not the final section of the
+/// image, or an attempt to append data to a non-empty section that is not the
+/// final section of the image, or an attempt to operate on an empty section
+/// for those APIs that prohibit this.
+#define SBE_XIP_SECTION_ERROR 10
+
+/// An address translation API returned a PORE address that was not at least
+/// 4-byte aligned, or alignment violations were observed by
+/// sbe_xip_validate() or sbe_xip_append().
+#define SBE_XIP_ALIGNMENT_ERROR 11
+
+/// An API that performs dynamic memory allocation was unable to allocate
+/// memory.
+#define SBE_XIP_NO_MEMORY 12
+
+/// Attempt to get or set a vector element with an index that is outside of
+/// the declared bounds of the vector.
+#define SBE_XIP_BOUNDS_ERROR 13
+
+/// Attempt to grow the image past its defined memory allocation
+#define SBE_XIP_WOULD_OVERFLOW 14
+
+/// Error associated with the disassembler occured.
+#define SBE_XIP_DISASSEMBLER_ERROR 15
+
+/// Applications can expand this macro to declare an array of string forms of
+/// the error codes if desired.
+#define SBE_XIP_ERROR_STRINGS(var) \
+ const char* var[] = { \
+ "Success", \
+ "SBE_XIP_IMAGE_ERROR", \
+ "SBE_XIP_TOC_ERROR", \
+ "SBE_XIP_ITEM_NOT_FOUND", \
+ "SBE_XIP_DATA_NOT_PRESENT", \
+ "SBE_XIP_CANT_MODIFY", \
+ "SBE_XIP_INVALID_ARGUMENT", \
+ "SBE_XIP_TYPE_ERROR", \
+ "SBE_XIP_BUG", \
+ "SBE_XIP_NOT_NORMALIZED", \
+ "SBE_XIP_SECTION_ERROR", \
+ "SBE_XIP_ALIGNMENT_ERROR", \
+ "SBE_XIP_NO_MEMORY", \
+ "SBE_XIP_BOUNDS_ERROR", \
+ "SBE_XIP_WOULD_OVERFLOW", \
+ "SBE_XIP_DISASSEMBLER_ERROR", \
+ }
+
+/// Applications can use this macro to safely index the array of error
+/// strings.
+#define SBE_XIP_ERROR_STRING(var, n) \
+ ((((n) < 0) || ((n) > (int)(sizeof(var) / sizeof(char*)))) ? \
+ "Bug : Invalid SBE-XIP error code" : var[n])
+
+/// @}
+
+/// Disassembler error codes.
+#define DIS_IMAGE_ERROR 1
+#define DIS_MEMORY_ERROR 2
+#define DIS_DISASM_ERROR 3
+#define DIS_RING_NAME_ADDR_MATCH_SUCCESS 4
+#define DIS_RING_NAME_ADDR_MATCH_FAILURE 5
+#define DIS_TOO_MANY_DISASM_WARNINGS 6
+#define DIS_DISASM_TROUBLES 7
+
+#define DIS_ERROR_STRINGS(var) \
+ const char* var[] = { \
+ "Success", \
+ "DIS_IMAGE_ERROR", \
+ "DIS_MEMORY_ERROR", \
+ "DIS_DISASM_ERROR", \
+ "DIS_RING_NAME_ADDR_MATCH_SUCCESS", \
+ "DIS_RING_NAME_ADDR_MATCH_FAILURE", \
+ "DIS_TOO_MANY_DISASM_WARNINGS", \
+ "DIS_DISASM_TROUBLES", \
+ }
+
+#define DIS_ERROR_STRING(var, n) \
+ ((((n) < 0) || ((n) > (int)(sizeof(var) / sizeof(char*)))) ? \
+ "Bug : Invalid DIS error code" : var[n])
+
+#if 0
+{ /* So __cplusplus doesn't mess w/auto-indent */
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __ASSEMBLER__
+
+
+////////////////////////////////////////////////////////////////////////////
+// Assembler Definitions
+////////////////////////////////////////////////////////////////////////////
+
+#ifdef __ASSEMBLER__
+
+/// Create an XIP TOC entry
+///
+/// \param[in] index The string form of the \a index symbol is created and
+/// linked from the TOC entry to allow external search procedures to locate
+/// the \a address.
+///
+/// \param[in] type One of the SBE_XIP_* type constants; See \ref
+/// sbe_xip_toc_types.
+///
+/// \param[in] address The address of the idexed code or data; This wlll
+/// typically be a symbol.
+///
+/// \param[in] elements <Optional> For vector types, number of elements in the
+/// vector, which is limited to an 8-bit unsigned integer. This parameter
+/// defaults to 1 which indicates a scalar type. Declaring a vector with 0
+/// elements disables bounds checking on vector accesses, and can be used if
+/// very large or indeterminate sized vectors are required. The TOC format
+/// does not support vectors of strings or addresses.
+///
+/// The \c .xip_toc macro creates a XIP Table of Contents (TOC) structure in
+/// the \c .toc section, as specified by the parameters. This macro is
+/// typically not used directly in assembly code. Instead programmers should
+/// use .xip_quad, .xip_quada, .xip_quadia, .xip_address, .xip_string or
+/// .xip_cvs_revision.
+
+ .macro .xip_toc, index:req, type:req, address:req, elements=1
+
+ .if (((\type) < 1) || ((\type) > SBE_XIP_MAX_TYPE_INDEX))
+ .error ".xip_toc : Illegal type index"
+ .endif
+
+ // First push into the .strings section to lay down the
+ // string form of the index name under a local label.
+
+ .pushsection .strings
+7667862:
+ .asciz "\index"
+ .popsection
+
+ // Now the 12-byte TOC entry is created. Push into the .toc section
+ // and lay down the first 4 bytes which are always a pointer to the
+ // string just declared. The next 4 bytes are the address of the data
+ // (or the address itself in the case of address types). The final 4
+ // bytes are the type, section (always 0 prior to normalization),
+ // number of elements, and a padding byte.
+
+ .pushsection .toc
+
+ .long 7667862b, (\address)
+ .byte (\type), 0, (\elements), 0
+
+ .popsection
+
+ .endm
+
+
+/// Allocate and initialize 64-bit global scalar or vector data and create the
+/// TOC entry.
+///
+/// \param[in] symbol The name of the scalar or vector; this name is also used
+/// as the TOC index of the data.
+///
+/// \param[in] init The initial value of (each element of) the data.
+/// This is a 64-bit integer; To allocate address pointers use .xip_quada.
+///
+/// \param[in] elements The number of 64-bit elements in the data structure,
+/// defaulting to 1, with a maximum value of 255.
+///
+/// \param[in] section The section where the data will be allocated,
+/// default depends on the memory space
+
+ .macro .xip_quad, symbol:req, init:req, elements=1, section
+
+ ..xip_quad_helper .quad, \symbol, (\init), (\elements), \section
+
+ .endm
+
+
+/// Allocate and initialize 64-bit global scalar or vector data containing a
+/// relocatable address in and create the TOC entry.
+///
+/// \param[in] symbol The name of the scalar or vector; this name is also used
+/// as the TOC index of the data.
+///
+/// \param[in] init The initial value of (each element of) the data. This
+/// will typically be a symbolic address. If the intention is to define an
+/// address that will always be filled in later by image manipulation tools,
+/// then use the .xip_quad macro with a 0 initial value.
+///
+/// \param[in] elements The number of 64-bit elements in the data structure,
+/// defaulting to 1, with a maximum value of 255.
+///
+/// \param[in] section The section where the data will be allocated,
+/// default depends on the memory space
+
+ .macro .xip_quada, symbol:req, offset:req, elements=1, section
+
+ ..xip_quad_helper .quada, \symbol, (\offset), (\elements), \section
+
+ .endm
+
+
+/// Helper for .xip_quad and .xip_quada
+
+ .macro ..xip_quad_helper, directive, symbol, init, elements, section
+
+ .if (((\elements) < 1) || ((\elements) > 255))
+ .error "The number of vector elements must be in the range 1..255"
+ .endif
+
+ ..xip_pushsection \section
+ .balign 8
+
+ .global \symbol
+\symbol\():
+ .rept (\elements)
+ \directive (\init)
+ .endr
+
+ .popsection
+
+ .xip_toc \symbol, SBE_XIP_UINT64, \symbol, (\elements)
+
+ .endm
+
+
+/// Allocate and initialize 64-bit global scalar or vector data containing
+/// full 64-bit addresses and create a TOC entry
+///
+/// \param[in] symbol The name of the scalar or vector; this name is also used
+/// as the TOC index of the data.
+///
+/// \param[in] space A valid PORE memory space descriptor
+///
+/// \param[in] offset A 32-bit relocatable offset
+///
+/// \param[in] elements The number of 64-bit elements in the data structure,
+/// defaulting to 1, with a maximum value of 255.
+///
+/// \param[in] section The section where the data will be allocated,
+/// default depends on the memory space
+
+ .macro .xip_quadia, symbol:req, space:req, offset:req, \
+ elements=1, section
+
+ .if (((\elements) < 1) || ((\elements) > 255))
+ .error "The number of vector elements must be in the range 1..255"
+ .endif
+
+ ..xip_pushsection \section
+ .balign 8
+
+ .global \symbol
+\symbol\():
+ .rept (\elements)
+ .quadia (\space), (\offset)
+ .endr
+
+ .popsection
+
+ .xip_toc \symbol, SBE_XIP_UINT64, \symbol, (\elements)
+
+ .endm
+
+/// Default push into .ipl_data unless in an OCI space, then .data
+
+ .macro ..xip_pushsection, section
+
+ .ifnb \section
+ .pushsection \section
+ .else
+ .if (_PGAS_DEFAULT_SPACE == PORE_SPACE_OCI)
+ .pushsection .data
+ .else
+ .pushsection .ipl_data
+ .endif
+ .endif
+
+ .balign 8
+
+ .endm
+
+/// Allocate and initialize a string in .strings
+///
+/// \param[in] index The string will be stored in the TOC using this index
+/// symbol.
+///
+/// \param[in] string The string to be allocated in .strings. String space is
+/// fixed once allocated. Strings designed to be overwritten by external tools
+/// should be allocated to be as long as eventually needed (e.g., by a string
+/// of blanks.)
+
+ .macro .xip_string, index:req, string:req
+
+ .pushsection .strings
+7874647:
+ .asciz "\string"
+ .popsection
+
+ .xip_toc \index, SBE_XIP_STRING, 7874647b
+
+ .endm
+
+
+/// Allocate and initialize a CVS Revison string in .strings
+///
+/// \param[in] index The string will be stored in the TOC using this index
+/// symbol.
+///
+/// \param[in] string A CVS revision string to be allocated in .strings. CVS
+/// revision strings are formatted by stripping out and only storing the
+/// actual revision number :
+///
+/// \code
+/// "$Revision <n>.<m> $" -> "<n>.<m>"
+/// \endcode
+
+
+ .macro .xip_cvs_revision, index:req, string:req
+
+ .pushsection .strings
+7874647:
+ ..cvs_revision_string "\string"
+ .popsection
+
+ .xip_toc \index, SBE_XIP_STRING, 7874647b
+
+ .endm
+
+
+/// Shorthand to create a TOC entry for an address
+///
+/// \param[in] index The symbol will be indexed as this name
+///
+/// \param[in] symbol <Optional> The symbol to index; by default the same as
+/// the index.
+
+ .macro .xip_address, index:req, symbol
+
+ .ifb \symbol
+ .xip_toc \index, SBE_XIP_ADDRESS, \index
+ .else
+ .xip_toc \index, SBE_XIP_ADDRESS, \symbol
+ .endif
+
+ .endm
+
+
+/// Edit and allocate a CVS revision string
+///
+/// CVS revision strings are formatted by stripping out and only storing the
+/// actual revision number :
+/// \code
+/// "$Revision <n>.<m> $" -> "<n>.<m>"
+/// \endcode
+
+ .macro ..cvs_revision_string, rev:req
+ .irpc c, \rev
+ .ifnc "\c", "$"
+ .ifnc "\c", "R"
+ .ifnc "\c", "e"
+ .ifnc "\c", "v"
+ .ifnc "\c", "i"
+ .ifnc "\c", "s"
+ .ifnc "\c", "i"
+ .ifnc "\c", "o"
+ .ifnc "\c", "n"
+ .ifnc "\c", ":"
+ .ifnc "\c", " "
+ .ascii "\c"
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endif
+ .endr
+ .byte 0
+ .endm
+
+#endif // __ASSEMBLER__
+
+#endif // __SBE_XIP_TOC_H
diff --git a/src/usr/hwpf/makefile b/src/usr/hwpf/makefile
index ad020ada0..b2fae34c2 100644
--- a/src/usr/hwpf/makefile
+++ b/src/usr/hwpf/makefile
@@ -1,11 +1,11 @@
-# IBM_PROLOG_BEGIN_TAG
+# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
#
# $Source: src/usr/hwpf/makefile $
#
# IBM CONFIDENTIAL
#
-# COPYRIGHT International Business Machines Corp. 2011
+# COPYRIGHT International Business Machines Corp. 2011-2012
#
# p1
#
@@ -19,7 +19,7 @@
#
# Origin: 30
#
-# IBM_PROLOG_END
+# IBM_PROLOG_END_TAG
ROOTPATH = ../../..
SUBDIRS = fapi.d hwp.d plat.d test.d
@@ -36,7 +36,9 @@ HWP_ERROR_XML_FILES = hwp/fapiHwpErrorInfo.xml \
hwp/dimm_errors.xml \
hwp/dram_training/memory_errors.xml \
hwp/start_clocks_on_nest_chiplets/proc_start_clocks_chiplets/proc_start_clocks_chiplets_errors.xml \
- hwp/edi_ei_initialization/proc_fab_iovalid/proc_fab_smp_errors.xml
+ hwp/edi_ei_initialization/proc_fab_iovalid/proc_fab_smp_errors.xml \
+ hwp/build_winkle_images/proc_slw_build/proc_slw_build_errors.xml
+
HWP_ATTR_XML_FILES = hwp/memory_attributes.xml \
hwp/L2_L3_attributes.xml \
OpenPOWER on IntegriCloud