summaryrefslogtreecommitdiffstats
path: root/libpore/pore_inline.h
diff options
context:
space:
mode:
Diffstat (limited to 'libpore/pore_inline.h')
-rw-r--r--libpore/pore_inline.h881
1 files changed, 881 insertions, 0 deletions
diff --git a/libpore/pore_inline.h b/libpore/pore_inline.h
new file mode 100644
index 00000000..f74aa6fa
--- /dev/null
+++ b/libpore/pore_inline.h
@@ -0,0 +1,881 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/build_winkle_images/p8_slw_build/pore_inline.h $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2012,2014 */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#ifndef __PORE_INLINE_H__
+#define __PORE_INLINE_H__
+
+// $Id: pore_inline.h,v 1.20 2013/12/11 00:11:13 bcbrock Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/pore_inline.h,v $
+//-----------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2013
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//-----------------------------------------------------------------------------
+
+// ** 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.
+
+#ifndef PPC_HYP
+#include <ctype.h>
+#include <stddef.h>
+#include <stdint.h>
+#endif // PPC_HYP
+#include "pgas.h"
+
+#if( defined(__cplusplus) && !defined(PLIC_MODULE) )
+extern "C" {
+#endif
+#if 0
+} /* So __cplusplus doesn't mess w/auto-indent */
+#endif
+
+
+#ifndef __ASSEMBLER__
+
+// PHYP tools do not support 'static' functions and variables as it interferes
+// with their concurrent patch methodology. So when compiling for PHYP the
+// PORE instruction "macros" are simply declared "inline". This also extends
+// into the implementation C files - so under PHYP all previosuly local static
+// functions will now be global functions. We retain 'static' to reduce code
+// size and improve abstraction for OCC applications.
+
+#ifdef PPC_HYP
+#define PORE_STATIC
+#include <p8_pore_api_custom.h>
+#else
+#define PORE_STATIC static
+#endif
+
+/// 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
+
+/// Disassemble unrecognized opcodes as 4-byte data
+///
+/// This flag is an option to pore_inline_context_create(). If set, then
+/// any putative instruction with an unrecognized opcode will be silently
+/// diassembled as 4-byte data.
+///
+/// This option was added to allow error-free disassembly of
+/// non-parity-protected PORE text sections that contain 0x00000000 alignment
+/// padding, and is not guaranteed to produce correct or consistent results in
+/// any other case.
+#define PORE_INLINE_DISASSEMBLE_UNKNOWN 0x20
+
+
+#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, 4 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;
+
+ /// Was this location disassembled as an instruction (0) or as data (1)
+ int is_data;
+
+} 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
+
+PORE_STATIC inline int
+pore_NOP(PoreInlineContext *ctx)
+{
+ return pore_inline_instruction1(ctx, PGAS_OPCODE_NOP, 0);
+}
+
+
+PORE_STATIC inline int
+pore_TRAP(PoreInlineContext *ctx)
+{
+ return pore_inline_instruction1(ctx, PGAS_OPCODE_TRAP, 0);
+}
+
+
+PORE_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);
+
+PORE_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
+
+PORE_STATIC inline int
+pore_BRA(PoreInlineContext *ctx, PoreInlineLocation target)
+{
+ return pore_inline_bra(ctx, PGAS_OPCODE_BRA, target);
+}
+
+PORE_STATIC inline int
+pore_BSR(PoreInlineContext *ctx, PoreInlineLocation target)
+{
+ return pore_inline_bra(ctx, PGAS_OPCODE_BSR, target);
+}
+
+PORE_STATIC inline int
+pore_LOOP(PoreInlineContext *ctx, PoreInlineLocation target)
+{
+ return pore_inline_bra(ctx, PGAS_OPCODE_LOOP, target);
+}
+
+
+// BRAZ, BRANZ
+
+PORE_STATIC inline int
+pore_BRAZ(PoreInlineContext *ctx, int reg, PoreInlineLocation target)
+{
+ return pore_inline_brac(ctx, PGAS_OPCODE_BRAZ, reg, target);
+}
+
+
+PORE_STATIC inline int
+pore_BRANZ(PoreInlineContext *ctx, int reg, PoreInlineLocation target)
+{
+ return pore_inline_brac(ctx, PGAS_OPCODE_BRANZ, reg, target);
+}
+
+
+// CMPIBRAEQ, CMPIBRANE, CMPIBSREQ
+
+PORE_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);
+}
+
+
+PORE_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);
+}
+
+
+PORE_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
+
+PORE_STATIC inline int
+pore_BRAD(PoreInlineContext *ctx, int reg) {
+ return pore_inline_brad(ctx, PGAS_OPCODE_BRAD, reg);
+}
+
+PORE_STATIC inline int
+pore_BSRD(PoreInlineContext *ctx, int reg) {
+ return pore_inline_brad(ctx, PGAS_OPCODE_BSRD, reg);
+}
+
+
+// ANDI, ORI, XORI
+
+PORE_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);
+}
+
+PORE_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);
+}
+
+PORE_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
+
+PORE_STATIC inline int
+pore_AND(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_AND, dest, src1, src2);
+}
+
+PORE_STATIC inline int
+pore_OR(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_OR, dest, src1, src2);
+}
+
+PORE_STATIC inline int
+pore_XOR(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_XOR, dest, src1, src2);
+}
+
+PORE_STATIC inline int
+pore_ADD(PoreInlineContext *ctx, int dest, int src1, int src2)
+{
+ return pore_inline_alurr(ctx, PGAS_OPCODE_ADD, dest, src1, src2);
+}
+
+PORE_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
+
+PORE_STATIC inline int
+pore_ADDS(PoreInlineContext *ctx, int dest, int src, int imm)
+{
+ return pore_inline_adds(ctx, PGAS_OPCODE_ADDS, dest, src, imm);
+}
+
+PORE_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
+
+PORE_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);
+}
+
+PORE_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);
+}
+
+PORE_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);
+}
+
+PORE_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);
+}
+
+
+#ifdef IGNORE_HW274735
+
+// BSI and BCI are redacted as instructions and reimplemented as "macros" due
+// to HW274735, unless specifically overridden. Note that the inline assembler
+// will allow D1 to be used as scratch here, unlike the underlying hardware
+// instruction.
+
+PORE_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);
+}
+
+PORE_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);
+}
+
+#else
+
+PORE_STATIC inline int
+pore_BSI(PoreInlineContext *ctx,
+ int src, int32_t offset, int base, uint64_t imm)
+{
+ return
+ ((pore_LD(ctx, src, offset, base) ||
+ pore_ORI(ctx, src, src, imm) ||
+ pore_STD(ctx, src, offset, base)) ? ctx->error : 0);
+}
+
+PORE_STATIC inline int
+pore_BCI(PoreInlineContext *ctx,
+ int src, int32_t offset, int base, uint64_t imm)
+{
+ return
+ ((pore_LDANDI(ctx, src, offset, base, ~imm) ||
+ pore_STD(ctx, src, offset, base)) ? ctx->error : 0);
+}
+
+#endif // IGNORE_HW274735
+
+
+// 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
+#if( defined(__cplusplus) && !defined(PLIC_MODULE) )
+}
+#endif
+
+#endif /* __PORE_INLINE_H__ */
+
OpenPOWER on IntegriCloud