diff options
Diffstat (limited to 'src/lib/pgas.h')
-rwxr-xr-x | src/lib/pgas.h | 1153 |
1 files changed, 0 insertions, 1153 deletions
diff --git a/src/lib/pgas.h b/src/lib/pgas.h deleted file mode 100755 index bdd3ba1..0000000 --- a/src/lib/pgas.h +++ /dev/null @@ -1,1153 +0,0 @@ -#ifndef __PGAS_H__ -#define __PGAS_H__ - -#define __PGAS__ - -// $Id: pgas.h,v 1.1.1.1 2013/12/11 20:49:20 bcbrock Exp $ -// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/lib/pgas.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, 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_STD0 PORE_OPCODE_SCR1WR /* Used by STD */ -#define PGAS_OPCODE_STD1 PORE_OPCODE_SCR2WR /* Used by STD */ -#define PGAS_OPCODE_SCAND PORE_OPCODE_SCAND - -#ifdef IGNORE_HW274735 - -// BSI and BCI are normally redacted due to HW274735. See also pgas.h - -#define PGAS_OPCODE_BSI PORE_OPCODE_BS -#define PGAS_OPCODE_BCI PORE_OPCODE_BC - -#endif // IGNORE_HW274735 - -// 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 - - -// Memory Spaces - -#define PORE_SPACE_UNDEFINED 0xffff -#define PORE_SPACE_OCI 0x8000 -#define PORE_SPACE_PNOR 0x800b -#define PORE_SPACE_OTPROM 0x0001 -#define PORE_SPACE_SEEPROM 0x800c -#define PORE_SPACE_PIBMEM 0x0008 - - -#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 A0, A1 in any order - .macro ..axay, reg1, reg2, err="Expecting A0, A1 in either order" - .if !((((\reg1) == A0) && ((\reg2) == A1)) || \ - (((\reg1) == A1) && ((\reg2) == A0))) - .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. - - .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 -#ifndef PGAS_PPC - .pibmem_port (PORE_SPACE_PIBMEM & 0xf) -#else - // NB: PGAS_PPC does not support relocatable PIBMEM addressing -#endif - .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 - - ////////////////////////////////////////////////////////////////////// - // Bug workarounds - ////////////////////////////////////////////////////////////////////// - -#ifndef IGNORE_HW274735 - - // HW274735 documents that BC and BS are broken for the PORE-GPE0/1 - // pair. This bug is unfixed in POWER8, and by default we require BSI - // and BCI to be implemented as macros on all engines. For - // compatability we continue to require that dx == D0. - - .macro bsi, dx:req, offset:req, base:req, imm:req - ..d0 (\dx) - ld D0, (\offset), (\base) - ori D0, D0, (\imm) - std D0, (\offset), (\base) - .endm - - .macro bci, dx:req, offset:req, base:req, imm:req - ..d0 (\dx) - ldandi D0, (\offset), (\base), ~(\imm) - std D0, (\offset), (\base) - .endm - -#endif // IGNORE_HW274735 - - ////////////////////////////////////////////////////////////////////// - // "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[N]<eng> - Test Engine and branch if [not] 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 - - - .macro tebngpe0, dest:req, target:req - mr (\dest), IFR - andi (\dest), (\dest), 0xf - branz (\dest), (\target) - .endm - - .macro tebngpe1, dest:req, target:req - mr (\dest), IFR - andi (\dest), (\dest), PORE_ID_GPE1 - braz (\dest), (\target) - .endm - - .macro tebnslw, dest:req, target:req - mr (\dest), IFR - andi (\dest), (\dest), PORE_ID_SLW - braz (\dest), (\target) - .endm - - .macro tebnsbe, dest:req, target:req - mr (\dest), IFR - andi (\dest), (\dest), PORE_ID_SBE - braz (\dest), (\target) - .endm - - - ////////////////////////////////////////////////////////////////////// - // EXTRPRC - Extract and right-justify the PIB/PCB return code - // TPRCB[N]Z - Test PIB return code and branch if [not] zero - // TPRCBGT - Test PIB return code and branch if greater-than - // TPRCBLE - Test PIB return code and branch if less-then or equal - ////////////////////////////////////////////////////////////////////// - // - // To support cases where PORE code expects or must explicitly handle - // non-0 PIB return codes, the PIB return code and parity indication - // are stored in bits 32 (parity) and 33-35 (return code) of the IFR. - // These macros extract the four PIB/PCB status bits from the IFR and - // right-justifies them into the data register provided. For EXTRPRC - // that is the total function of the macro. The TPRCB[N]Z macros - // provide a simple non-destructive test and branch for zero (success) - // and non-zero (potential problem) codes after the extraction. - // - // In complex error handling scenarios one would typically compare the - // PIB return code against an upper-bound, e.g., the offline response - // (0x2), and then take further action. If the parity error bit is set - // then this would produce an aggregate "return code" higher than any - // that one would typically want to ignore. The TPRCBGT/TPRCBLE macros - // provide this function; however the test destroys the extracted - // return code so that if further analysis is required the code will - // need to be a extracted again. - ////////////////////////////////////////////////////////////////////// - - .macro extrprc, dest:req - ..data (\dest) - mr (\dest), IFR - extrdi (\dest), (\dest), 4, 32 - .endm - - .macro tprcbz, dest:req, target:req - extrprc (\dest) - braz (\dest), (\target) - .endm - - .macro tprcbnz, dest:req, target:req - extrprc (\dest) - branz (\dest), (\target) - .endm - - .macro tprcbgt, dest:req, target:req, bound:req - extrprc (\dest) - subs (\dest), (\dest), (\bound) - tfbugt (\dest), (\target) - .endm - - .macro tprcble, dest:req, target:req, bound:req - extrprc (\dest) - subs (\dest), (\dest), (\bound) - tfbule (\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__ |