NT4/public/sdk/inc/kxppc.h
2020-09-30 17:12:29 +02:00

1734 lines
64 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//++ BUILD Version: 0003 // Increment this if a change has global effects //
//*++
//
// Copyright (c) 1990-1996 IBM Corporation
//
// Module Name:
//
// kxppc.h
//
// Abstract:
//
// This module contains the nongenerated part of the PPC assembler
// header file. In general, it contains processor architecture constant
// information, however some assembler macros are also included.
//
// Author:
//
// Chuck Bauman (chuck2) 03-Aug-1993
//
// Revision History:
//
// Base on kxmips.h, NT product1 source (R3000 paths removed)
// Add procedure entry exit macros (Chuck Bauman) 10-Aug-1993
// Fixed # comments so C modules compile (Chuck Bauman) 13-Aug-1993
// Add exception entry codes and STK_SLACK_SPACE (Peter Johnston) 19-Aug-1993
// Optimizations for NESTED ENTRY/EXIT (Chuck Bauman) 27-Aug-1993
// New entry point linkage convention (Chuck Bauman) 01-Sep-1993
// Added SPECIAL ENTRY/EXIT (Curt Fawcett) 22-Sep-1993
// Deleted EXCEPTION_HANDLER and changed NESTED_ENTRY_EX
// and LEAF_ENTRY_EX to not append .scope to the Scope
// parameter (Tom Wood) 02-Nov-1993
// Added definition for SPR #1, Fixed Point Exception
// register XER (Mark D. Johnson) 11-Mar-1994
// Added in the macros that used to be in /private/ntos/
// crt32/h/ppcsects.h. I then removed that file since
// we don't need it anymore. (Matt Holle) 27-Apr-1994
//
//--*/
#ifndef _KXPPC_
#define _KXPPC_
#ifndef _KXPPC_C_HEADER_
// =====================================================================
// Begin code extracted from ppcsects.h
// =====================================================================
//Purpose:
// This file defines sections for the C and C++ libs.
//
// NOTE: As needed, special "CRT" sections can be added into the existing
// init/term tables. These will be for our use only -- users who put
// stuff in here do so at their own risk.
//
//Revision History:
// 03-19-92 SKS Loosely based on the 16-bit include file DEFSEGS.INC
// 08-06-92 SKS Changed these section names from X[ICPT]$[ACLUXZ] to
// .CRT$X[ICPT][ACLUXZ] to avoid creating too many sections
// Also, sections are no longer defined in groups. That was
// for use with OMF type objects where order of appearance
// is important. With COFF, sorting is done by section name.
// 10-26-93 CDB Based on MS defsects.inc
//
// beginSection - a macro for declaring and beginning a section
//
// endSection - a macro for ending a previously declared section
//
// *****
#define beginSection(SectName) \
.section .CRT$##SectName, "drw2"
#define endSection(SectName)
// XIA Begin C Initializer Sections
// XIC Microsoft Reserved
// XIU User
// XIZ End C Initializer Sections
//
// XCA Begin C++ Constructor Sections
// XCC Compiler (MS)
// XCL Library
// XCU User
// XCZ End C++ Constructor Sections
//
// XPA Begin C Pre-Terminator Sections
// XPU User
// XPX Microsoft Reserved
// XPZ End C Pre-Terminator Sections
//
// XTA Begin C Pre-Terminator Sections
// XTU User
// XTX Microsoft Reserved
// XTZ End C Pre-Terminator Sections
// =====================================================================
// End code extracted from ppcsects.h
// =====================================================================
#endif // _KXPPC_C_HEADER_
//
// Define soft reset vector address for nonhandled cache parity errors.
//
#define SOFT_RESET_VECTOR 0xbfc00300 // default parity error routine address
//
// Define low memory transfer vector address and TB index address (temporary).
//
#define TRANSFER_VECTOR (KSEG1_BASE + 0x400) // exception handler address
//
// Maximum Bit number (32 bit implementation)
//
#define MAX_BITS 0x1f
//
// Macro to generate a mask using the SPR bit definitions below
//
#define MASK_SPR(shift,mask) ((mask) << (MAX_BITS-(shift)))
//
// Define Machine State Register bit field offsets.
//
// MSR_POW 0x0d Power management enable <13>
// MSR_IMPL 0x0e Implementation dependent <14>
// MSR_ILE 0x0f Interrupt Little-Endian mode <15>
// MSR_EE 0x10 External interrupt Enable <16>
// MSR_PR 0x11 Problem state <17>
// MSR_FP 0x12 Floating Point available <18>
// MSR_ME 0x13 Machine check Enable <19>
// MSR_FE0 0x14 Floating point Exception mode 0 <20>
// MSR_SE 0x15 Single-step trace Enable <21>
// MSR_BE 0x16 Branch trace Enable <22>
// MSR_FE1 0x17 Floating point Exception mode 1 <23>
// MSR_IP 0x19 Interrupt Prefix <25>
// MSR_IR 0x1a Instruction Relocate <26>
// MSR_DR 0x1b Data Relocate <27>
// MSR_PM 0x1d Performance Monitor <29>
// MSR_RI 0x1e Recoverable Interrupt <30>
// MSR_LE 0x1f Little-Endian execution mode <31>
#define MSR_POW 0x0d
#define MSR_IMPL 0x0e
#define MSR_ILE 0x0f
#define MSR_EE 0x10
#define MSR_PR 0x11
#define MSR_FP 0x12
#define MSR_ME 0x13
#define MSR_FE0 0x14
#define MSR_SE 0x15
#define MSR_BE 0x16
#define MSR_FE1 0x17
#define MSR_IP 0x19
#define MSR_IR 0x1a
#define MSR_DR 0x1b
#define MSR_PM 0x1d
#define MSR_RI 0x1e
#define MSR_LE 0x1f
//
// Define Processor Version Register (PVR) bit fields
//
// PVR_Version 0x0 Processor Version <0:15>
// PVR_Revision 0x10 Processor Revision <16:31>
#define PVR_Version 0x0
#define PVR_Revision 0x10
//
// Fixed Point Exception Register is Special Purpose Reg no. 1
//
#define XER 0x1
//
// Define Fixed Point Exception Register (XER) bit fields
//
// XER_SO 0x0 Summary Overflow <0>
// XER_OV 0x1 Overflow <1>
// XER_CA 0x2 Carry <2>
// XER_COMP 0x10 > Carry <16:23>
// XER_COUNT 0x19 Carry <25:31>
#define XER_SO 0x0
#define XER_OV 0x1
#define XER_CA 0x2
#define XER_COMP 0x10
#define XER_COUNT 0x19
//
// Define Floating Point Status/Control Register (FPSCR) bit fields
//
// FPSCR_FX 0x0 Exception summary <0>
// FPSCR_FEX 0x1 Enabled Exception summary <1>
// FPSCR_VX 0x2 Invalid operation exception summary <2>
// FPSCR_OX 0x3 Overflow exception <3>
// FPSCR_UX 0x4 Underflow exception <4>
// FPSCR_ZX 0x5 Zero divide exception <5>
// FPSCR_XX 0x6 Inexact exception <6>
// FPSCR_VXSNAN 0x7 Invalid op exception (signalling NaN) <7>
// FPSCR_VXISI 0x8 Invalid op exception (infinity - infinity) <8>
// FPSCR_VXIDI 0x9 Invalid op exception (infinity / infinity) <9>
// FPSCR_VXZDZ 0x0a Invalid op exception (0 / 0) <10>
// FPSCR_VXIMZ 0x0b Invalid op exception (infinity * 0) <11>
// FPSCR_VXVC 0x0c Invalid op exception (compare) <12>
// FPSCR_FR 0x0d Fraction Rounded <13>
// FPSCR_FI 0x0e Fraction Inexact <14>
// FPSCR_C 0x0f Result Class descriptor <15>
// FPSCR_FL 0x10 Result Less than or negative <16>
// FPSCR_FG 0x11 Result Greater than or positive <17>
// FPSCR_FE 0x12 Result Equal or zero <18>
// FPSCR_FU 0x13 Result Unordered or NaN <19>
// FPSCR_Res1 0x14 reserved <20>
// FPSCR_VXSOFT 0x15 Invalid op exception (software request) <21>
// FPSCR_VXSQRT 0x16 Invalid op exception (square root) <22>
// FPSCR_VXCVI 0x17 Invalid op exception (integer convert) <23>
// FPSCR_VE 0x18 Invalid operation exception Enable <24>
// FPSCR_OE 0x19 Overflow exception Enable <25>
// FPSCR_UE 0x1a Underflow exception Enable <26>
// FPSCR_ZE 0x1b Zero divide exception Enable <27>
// FPSCR_XE 0x1c Inexact exception Enable <28>
// FPSCR_NI 0x1d Non-IEEE mode <29>
// FPSCR_RN 0x1e Rounding control <30:31>
#define FPSCR_FX 0x0
#define FPSCR_FEX 0x1
#define FPSCR_VX 0x2
#define FPSCR_OX 0x3
#define FPSCR_UX 0x4
#define FPSCR_ZX 0x5
#define FPSCR_XX 0x6
#define FPSCR_VXSNAN 0x7
#define FPSCR_VXISI 0x8
#define FPSCR_VXIDI 0x9
#define FPSCR_VXZDZ 0x0a
#define FPSCR_VXIMZ 0x0b
#define FPSCR_VXVC 0x0c
#define FPSCR_FR 0x0d
#define FPSCR_FI 0x0e
#define FPSCR_C 0x0f
#define FPSCR_FL 0x10
#define FPSCR_FG 0x11
#define FPSCR_FE 0x12
#define FPSCR_FU 0x13
#define FPSCR_Res1 0x14
#define FPSCR_VXSOFT 0x15
#define FPSCR_VXSQRT 0x16
#define FPSCR_VXCVI 0x17
#define FPSCR_VE 0x18
#define FPSCR_OE 0x19
#define FPSCR_UE 0x1a
#define FPSCR_ZE 0x1b
#define FPSCR_XE 0x1c
#define FPSCR_NI 0x1d
#define FPSCR_RN 0x1e
//
// Define exception codes.
//
#define XCODE_INTERRUPT 0x0 // Interrupt
#define XCODE_MODIFY 0x4 // TLB modify
#define XCODE_READ_MISS 0x8 // TLB read miss
#define XCODE_WRITE_MISS 0xc // TLB write miss
#define XCODE_READ_ADDRESS_ERROR 0x10 // Read alignment error
#define XCODE_WRITE_ADDRESS_ERROR 0x14 // Write alignment error
#define XCODE_INSTRUCTION_BUS_ERROR 0x18 // Instruction bus error
#define XCODE_DATA_BUS_ERROR 0x1c // Data bus error
#define XCODE_SYSTEM_CALL 0x20 // System call
#define XCODE_BREAKPOINT 0x24 // Breakpoint
#define XCODE_ILLEGAL_INSTRUCTION 0x28 // Illegal instruction
#define XCODE_COPROCESSOR_UNUSABLE 0x2c // Coprocessor unusable
#define XCODE_INTEGER_OVERFLOW 0x30 // Arithmetic overflow
#define XCODE_TRAP 0x34 // Trap instruction
#define XCODE_VIRTUAL_INSTRUCTION 0x38 // Virtual instruction coherency
#define XCODE_FLOATING_EXCEPTION 0x3c // Floating point exception
#define XCODE_WATCHPOINT 0x5c // Watch point
#define XCODE_PANIC 0x78 // Stack overflow (software)
#define XCODE_VIRTUAL_DATA 0x7c // Virtual data coherency
#define R4000_XCODE_MASK (0x1f << CAUSE_XCODE) // R4000 exception code mask
#define R4000_MISS_MASK (R4000_XCODE_MASK & \
(~(XCODE_READ_MISS ^ XCODE_WRITE_MISS))) //
//
// Define page mask values.
//
#define PAGEMASK_4KB 0x0 // 4kb page
#define PAGEMASK_16KB 0x3 // 16kb page
#define PAGEMASK_64KB 0xf // 64kb page
#define PAGEMASK_256KB 0x3f // 256kb page
#define PAGEMASK_1MB 0xff // 1mb page
#define PAGEMASK_4MB 0x3ff // 4mb page
#define PAGEMASK_16MB 0xfff // 16mb page
//
// Define primary cache states.
//
#define PRIMARY_CACHE_INVALID 0x0 // primary cache invalid
#define PRIMARY_CACHE_SHARED 0x1 // primary cache shared (clean or dirty)
#define PRIMARY_CACHE_CLEAN_EXCLUSIVE 0x2 // primary cache clean exclusive
#define PRIMARY_CACHE_DIRTY_EXCLUSIVE 0x3 // primary cache dirty exclusive
//
// Define cache instruction operation codes.
//
#define INDEX_INVALIDATE_I 0x0 // invalidate primary instruction cache
#define INDEX_WRITEBACK_INVALIDATE_D 0x1 // writeback/invalidate primary data cache
#define INDEX_INVALIDATE_SI 0x2 // invalidate secondary instruction cache
#define INDEX_WRITEBACK_INVALIDATE_SD 0x3 // writeback/invalidate secondary data cache
#define INDEX_LOAD_TAG_I 0x4 // load primary instruction tag indexed
#define INDEX_LOAD_TAG_D 0x5 // load primary data tag indexed
#define INDEX_LOAD_TAG_SI 0x6 // load secondary instruction tag indexed
#define INDEX_LOAD_TAG_SD 0x7 // load secondary data tag indexed
#define INDEX_STORE_TAG_I 0x8 // store primary instruction tag indexed
#define INDEX_STORE_TAG_D 0x9 // store primary data tag indexed
#define INDEX_STORE_TAG_SI 0xa // store secondary instruction tag indexed
#define INDEX_STORE_TAG_SD 0xb // store secondary data tag indexed
#define CREATE_DIRTY_EXCLUSIVE_D 0xd // create dirty exclusive primary data cache
#define CREATE_DIRTY_EXCLUSIVE_SD 0xf // create dirty exclusive secondary data cache
#define HIT_INVALIDATE_I 0x10 // invalidate primary instruction cache
#define HIT_INVALIDATE_D 0x11 // invalidate primary data cache
#define HIT_INVALIDATE_SI 0x12 // invalidate secondary instruction cache
#define HIT_INVALIDATE_SD 0x13 // invalidate secondary data cache
#define HIT_WRITEBACK_INVALIDATE_D 0x15 // writeback/invalidate primary data cache
#define HIT_WRITEBACK_INVALIDATE_SD 0x17 // writeback/invalidate secondary data cache
#define HIT_WRITEBACK_D 0x19 // writeback primary data cache
#define HIT_WRITEBACK_SD 0x1b // writeback secondary data cache
#define HIT_SET_VIRTUAL_SI 0x1e // hit set virtual secondary instruction cache
#define HIT_SET_VIRTUAL_SD 0x1f // hit set virtual secondary data cache
#ifndef _KXPPC_C_HEADER_
//
// Define save and restore floating state macros.
//
#define RESTORE_VOLATILE_FLOAT_STATE(_tf) \
lfd f.13, TrFpscr(_tf); \
lfd f.0, TrFpr0(_tf); \
lfd f.1, TrFpr1(_tf); \
lfd f.2, TrFpr2(_tf); \
lfd f.3, TrFpr3(_tf); \
lfd f.4, TrFpr4(_tf); \
lfd f.5, TrFpr5(_tf); \
lfd f.6, TrFpr6(_tf); \
lfd f.7, TrFpr7(_tf); \
lfd f.8, TrFpr8(_tf); \
mtfsf 0xff, f.13; \
lfd f.9, TrFpr9(_tf); \
lfd f.10, TrFpr10(_tf); \
lfd f.11, TrFpr11(_tf); \
lfd f.12, TrFpr12(_tf); \
lfd f.13, TrFpr13(_tf);
#define SAVE_VOLATILE_FLOAT_STATE(_tf) \
stfd f.0, TrFpr0(_tf); \
stfd f.1, TrFpr1(_tf); \
stfd f.2, TrFpr2(_tf); \
stfd f.3, TrFpr3(_tf); \
stfd f.4, TrFpr4(_tf); \
stfd f.5, TrFpr5(_tf); \
mffs f.0; \
stfd f.6, TrFpr6(_tf); \
stfd f.7, TrFpr7(_tf); \
stfd f.8, TrFpr8(_tf); \
stfd f.9, TrFpr9(_tf); \
stfd f.10, TrFpr10(_tf); \
stfd f.11, TrFpr11(_tf); \
stfd f.12, TrFpr12(_tf); \
stfd f.13, TrFpr13(_tf); \
stfd f.0, TrFpscr(_tf);
//#define RESTORE_NONVOLATILE_FLOAT_STATE
// ldc1 f20,ExFltF20(sp);
// jal KiRestoreNonvolatileFloatState;
//#define SAVE_NONVOLATILE_FLOAT_STATE
// sdc1 f20,ExFltF20(sp);
// jal KiSaveNonvolatileFloatState;
#endif // _KXPPC_C_HEADER_
//
// Define TB and cache parameters.
//
#define PCR_ENTRY 0 // TB entry numbers (2) for the PCR
#define PDR_ENTRY 2 // TB entry number (1) for the PDR
#define KSTACK_ENTRY 3 // TB entry numbers (1) for kernel stack
#define DMA_ENTRY 4 // TB entry number (1) for DMA/InterruptSource
#define TB_ENTRY_SIZE (3 * 4) // size of TB entry
#define FIXED_BASE 0 // base index of fixed TB entries
#define FIXED_ENTRIES (DMA_ENTRY + 1) // number of fixed TB entries
//
// Define cache parameters
//
#define DCACHE_SIZE (4 * 1024) // size of data cache in bytes
#define ICACHE_SIZE (4 * 1024) // size of instruction cache in bytes
#define MINIMUM_CACHE_SIZE (4 * 1024) // minimum size of cache
#define MAXIMUM_CACHE_SIZE (128 * 1024) // maximum size fo cache
#ifndef _KXPPC_C_HEADER_
//
// Define subtitle macro
//
#define SBTTL(x)
//
// Define global definition macros.
//
//
// Define load immediate macro for 32-bit values.
//
// reg - Register to load with the 32-bit immediate
// immediate - 32-bit immediate value
//
#define LWI(reg,immediate) \
lis reg,(immediate) >> 16 ;\
ori reg,reg,(immediate) & 0xffff
#define END_REGION(Name) \
.globl Name ;\
Name:
#define START_REGION(Name) \
.globl Name ;\
Name:
//
// Define trap frame generation macro.
//
//#define GENERATE_TRAP_FRAME
// .set noat;
// sw AT,TrIntAt(s8);
// jal KiGenerateTrapFrame;
// .set at;
//
// Define restore volatile integer state macro.
//
//#define RESTORE_VOLATILE_INTEGER_STATE
// .set noat;
// lw AT,TrIntAt(s8);
// jal KiRestoreVolatileIntegerState;
// .set at;
//
// Define save volatile integer state macro.
//
//#define SAVE_VOLATILE_INTEGER_STATE
// .set noat;
// sw AT,TrIntAt(s8);
// jal KiSaveVolatileIntegerState;
// .set at;
//
// Define macros used by procedure entry/exit macros
//
//
// Set register 12 to the GPR save location based on the number
// of floating point registers to be saved.
//
#define __setFramemr(Fpr) \
mr r.12,r.sp
#define __setFramesubi(Fpr) \
subi r.12,r.sp,8*Fpr
//
// Save the number of GPRs specified inline or by setting r.12 to the GPR
// save location and branching to the appropriate millicode save procedure.
//
// Changed bla to bl in __savegpr4-__savegrp19 IBMCDB
#define __savegpr0(op,Fpr)
#define __savegpr1(op,Fpr) \
stw r.31,-(4+(8*Fpr))(r.sp)
#define __savegpr2(op,Fpr) \
stw r.31,-(4+(8*Fpr))(r.sp) ;\
stw r.30,-(8+(8*Fpr))(r.sp)
#define __savegpr3(op,Fpr) \
stw r.31,-(4+(8*Fpr))(r.sp) ;\
stw r.30,-(8+(8*Fpr))(r.sp) ;\
stw r.29,-(12+(8*Fpr))(r.sp)
#define __savegpr4(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_28
#define __savegpr5(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_27
#define __savegpr6(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_26
#define __savegpr7(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_25
#define __savegpr8(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_24
#define __savegpr9(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_23
#define __savegpr10(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_22
#define __savegpr11(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_21
#define __savegpr12(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_20
#define __savegpr13(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_19
#define __savegpr14(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_18
#define __savegpr15(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_17
#define __savegpr16(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_16
#define __savegpr17(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_15
#define __savegpr18(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_14
#define __savegpr19(op,Fpr) \
__setFrame##op(Fpr) ;\
bl .._savegpr_13
//
// Macros for removing the stack frame established through NESTED ENTRY.
//
#define __unsetFramemov(Fsize,Fpr) \
addi r.12,r.sp,Fsize ; \
mtlr r.0 ; \
mr r.sp,r.12
#define __unsetFrameaddi(Fsize,Fpr) \
addi r.12,r.sp,(Fsize)-(8*Fpr)
#define __unsetFrameblr(Fsize,Fpr) \
mtlr r.0 ; \
addi r.sp,r.sp,Fsize ; \
blr
// Change __unsetFrameba to __unsetFrameb IBMCDB
#define __unsetFrameb(Fsize,Fpr) \
addi r.sp,r.sp,Fsize ; \
blr
// Change __unsetFramebla to __unsetFramebl IBMCDB
#define __unsetFramebl(Fsize,Fpr)
#define __unsetFramenop(Fsize,Fpr)
// Change __setLRba to __setLRb IBMCDB
#define __setLRb(Fsize,Fpr) \
mtlr r.0
// Change __setLRbla to __setLRbl IBMCDB
#define __setLRbl(Fsize,Fpr)
//
// Restore number of GPRs specified
// setr - determines how to remove the stack frame (mov or addi)
// mov - will cause __unsetFramemov to be used
// addi - will cause __unsetFrameaddi to be used
// opret - if set to blr will cause GPR restore to return to caller
// only used for 0 GPRs and 0 FPRs
// op - specifies instruction to be used for the call to the
// restore millicode (ba, bla) - Changed to (b, bl) IBMCDB
// Fsize - stack frame size
// Fpr - number of FPRs to be restored
//
#define __restgpr0(setr,opret,op,Fsize,Fpr) \
__unsetFrame##opret(Fsize,Fpr)
#define __restgpr1(setr,opret,op,Fsize,Fpr) \
__setLR##op(Fsize,Fpr) ;\
lwz r.31,((Fsize)-(4+(8*Fpr)))(r.sp) ;\
__unsetFrame##op(Fsize,Fpr)
#define __restgpr2(setr,opret,op,Fsize,Fpr) \
lwz r.31,((Fsize)-(4+(8*Fpr)))(r.sp) ;\
__setLR##op(Fsize,Fpr) ;\
lwz r.30,((Fsize)-(8+(8*Fpr)))(r.sp) ;\
__unsetFrame##op(Fsize,Fpr)
#define __restgpr3(setr,opret,op,Fsize,Fpr) \
lwz r.31,((Fsize)-(4+(8*Fpr)))(r.sp) ;\
__setLR##op(Fsize,Fpr) ;\
lwz r.30,((Fsize)-(8+(8*Fpr)))(r.sp) ;\
lwz r.29,((Fsize)-(12+(8*Fpr)))(r.sp) ;\
__unsetFrame##op(Fsize,Fpr)
#define __restgpr4(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_28
#define __restgpr5(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_27
#define __restgpr6(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_26
#define __restgpr7(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_25
#define __restgpr8(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_24
#define __restgpr9(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_23
#define __restgpr10(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_22
#define __restgpr11(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_21
#define __restgpr12(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_20
#define __restgpr13(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_19
#define __restgpr14(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_18
#define __restgpr15(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_17
#define __restgpr16(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_16
#define __restgpr17(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_15
#define __restgpr18(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_14
#define __restgpr19(setr,opret,op,Fsize,Fpr) \
__unsetFrame##setr(Fsize,Fpr) ;\
op .._restgpr_13
//
// Set r.12 to GPR save location based on number of FPRs to save.
//
#define __setGPRFrm0(Fsize,Gpr,Fpr) \
__savegpr##Gpr(mr,0) ;\
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __setGPRFrm1(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,1)
#define __setGPRFrm2(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,2)
#define __setGPRFrm3(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,3)
#define __setGPRFrm4(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,4)
#define __setGPRFrm5(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,5)
#define __setGPRFrm6(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,6)
#define __setGPRFrm7(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,7)
#define __setGPRFrm8(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,8)
#define __setGPRFrm9(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,9)
#define __setGPRFrm10(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,10)
#define __setGPRFrm11(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,11)
#define __setGPRFrm12(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,12)
#define __setGPRFrm13(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,13)
#define __setGPRFrm14(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,14)
#define __setGPRFrm15(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,15)
#define __setGPRFrm16(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,16)
#define __setGPRFrm17(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,17)
#define __setGPRFrm18(Fsize,Gpr,Fpr) \
__savegpr##Gpr(subi,18)
//
// Generate epilogue code for NESTED EXIT based on number of GPRs and FPRs
// to be restored.
// Fsize - stack frame size
// Gpr - number of GPRs to restore
// Fpr - number of FPRs to restore
//
// Changed 3rd argument to __restgpr##Gpr in __unsetGPRFrm1 from ba to b IBMCDB
// Changed 3rd argument to __restgpr##Gpr in __unsetGPRFrm2-18 from bla to bl IBMCDB
#define __unsetGPRFrm0(Fsize,Gpr,Fpr) \
__restgpr##Gpr(mov,blr,b,Fsize,Fpr)
#define __unsetGPRFrm1(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
mtlr r.0 ;\
lfd f.31,((Fsize)-8)(r.sp) ;\
addi r.sp,r.sp,Fsize ;\
blr
#define __unsetGPRFrm2(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
lfd f.31,((Fsize)-8)(r.sp) ;\
mtlr r.0 ;\
lfd f.30,((Fsize)-16)(r.sp) ;\
addi r.sp,r.sp,Fsize ;\
blr
#define __unsetGPRFrm3(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
lfd f.31,((Fsize)-8)(r.sp) ;\
mtlr r.0 ;\
lfd f.30,((Fsize)-16)(r.sp) ;\
lfd f.29,((Fsize)-24)(r.sp) ;\
addi r.sp,r.sp,Fsize ;\
blr
#define __unsetGPRFrm4(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm5(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm6(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm7(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm8(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm9(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm10(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm11(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm12(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm13(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm14(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm15(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm16(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm17(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
#define __unsetGPRFrm18(Fsize,Gpr,Fpr) \
__restgpr##Gpr(addi,nop,bl,Fsize,Fpr) ;\
addi r.sp,r.sp,Fsize ;\
mtlr r.0 ;\
__restfpr##Fpr
//
// Save the number of FPRs specified inline or by branching to the appropriate
// millicode procedure.
//
// Change bla to bl in __savefrp4-18 IBMCDB
#define __savefpr0(Fsize,Gpr,Fpr)
#define __savefpr1(Fsize,Gpr,Fpr) \
stfd f.31,-8(r.sp) ;\
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr2(Fsize,Gpr,Fpr) \
stfd f.31,-8(r.sp) ;\
stfd f.30,-16(r.sp) ;\
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr3(Fsize,Gpr,Fpr) \
stfd f.31,-8(r.sp) ;\
stfd f.30,-16(r.sp) ;\
stfd f.29,-24(r.sp) ;\
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr4(Fsize,Gpr,Fpr) \
bl .._savefpr_28 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr5(Fsize,Gpr,Fpr) \
bl .._savefpr_27 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr6(Fsize,Gpr,Fpr) \
bl .._savefpr_26 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr7(Fsize,Gpr,Fpr) \
bl .._savefpr_25 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr8(Fsize,Gpr,Fpr) \
bl .._savefpr_24 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr9(Fsize,Gpr,Fpr) \
bl .._savefpr_23 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr10(Fsize,Gpr,Fpr) \
bl .._savefpr_22 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr11(Fsize,Gpr,Fpr) \
bl .._savefpr_21 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr12(Fsize,Gpr,Fpr) \
bl .._savefpr_20 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr13(Fsize,Gpr,Fpr) \
bl .._savefpr_19 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr14(Fsize,Gpr,Fpr) \
bl .._savefpr_18 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr15(Fsize,Gpr,Fpr) \
bl .._savefpr_17 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr16(Fsize,Gpr,Fpr) \
bl .._savefpr_16 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr17(Fsize,Gpr,Fpr) \
bl .._savefpr_15 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
#define __savefpr18(Fsize,Gpr,Fpr) \
bl .._savefpr_14 ; \
stwu r.sp,-(Fsize)(r.sp) ;\
stw r.0,(Fsize)-(4*(Gpr+1)+(8 * Fpr))(r.sp)
//
// Restore the number of FPRs specified inline or by branching to the
// appropriate millicode procedure.
//
// Changed ba to b in __restfpr4-18 IBMCDB
#define __restfpr0
#define __restfpr4 \
b .._restfpr_28
#define __restfpr5 \
b .._restfpr_27
#define __restfpr6 \
b .._restfpr_26
#define __restfpr7 \
b .._restfpr_25
#define __restfpr8 \
b .._restfpr_24
#define __restfpr9 \
b .._restfpr_23
#define __restfpr10 \
b .._restfpr_22
#define __restfpr11 \
b .._restfpr_21
#define __restfpr12 \
b .._restfpr_20
#define __restfpr13 \
b .._restfpr_19
#define __restfpr14 \
b .._restfpr_18
#define __restfpr15 \
b .._restfpr_17
#define __restfpr16 \
b .._restfpr_16
#define __restfpr17 \
b .._restfpr_15
#define __restfpr18 \
b .._restfpr_14
#endif // _KXPPC_C_HEADER_
//**************************************************************************/
//
// PPC Linkage support macros
//
//
//**************************************************************************/
// Caller's stack frame is addressed via R1, which points to
// the stack frame header. The 6 words following where R1 points
// comprise the header. The area PRECEEDING R1 is where FPRs are saved,
// and the area preceeding that is where GPRs are saved.
//
// | |
// +--------------------------------------+
// | |
// | |
// | Saved GPRs |
// | |
// | |
// | |
// +--------------------------------------+
// | |
// | |
// | Saved FPRs |
// | |
// | |
// | |
// R1 ------> +------------------+-------------------+
// | Back chain | Glue saved reg |
// +------------------+-------------------+
// | Glue saved rtoc | Reserved |
// +------------------+-------------------+
// | Reserved | Reserved |
// +------------------+-------------------+
// | Parameter Wd 0 | Parameter Wd 1 |
// +------------------+-------------------+
// | Parameter Wd 2 | Parameter Wd 3 |
// +------------------+-------------------+
// | Parameter Wd 4 | Parameter Wd 5 |
// +------------------+-------------------+
// | Parameter Wd 6 | Parameter Wd 7 |
// +------------------+-------------------+
// | ... |
//
// Offsets to various elements of stack frame header
#define STK_RSP 0
#define STK_GSR 4
#define STK_GSRTOC 8
#define STK_HDR_SZ 24
#define STK_P0 STK_HDR_SZ
#define STK_P1 (STK_P0+4)
#define STK_P2 (STK_P0+8)
#define STK_P3 (STK_P0+12)
#define STK_P4 (STK_P0+16)
#define STK_P5 (STK_P0+20)
#define STK_P6 (STK_P0+24)
#define STK_P7 (STK_P0+28)
#define STK_MIN_FRAME 56
#ifndef _KXPPC_C_HEADER_
//
// Define procedure entry/exit macros
//
// Name - Name of the nested procedure entry
// Fsize - Stack frame size
// Gprs - Number of general purpose registers to save
// Fprs - Number of floating point registers to save
//
//
// For primary entry points (NESTED_ENTRY, LEAF_ENTRY), a function table
// entry (for debugging, exception handling) is built.
//
// For all entry points, a function descriptor is built.
//
//
// NESTED_ENTRY is used for routines that call other routines; a stack
// frame is acquired and registers are saved.
//
// LEAF_ENTRY is used for routines that do not call other routines; no stack
// frame is acquired and no registers are saved.
//
//
// NESTED_ENTRY_EX and LEAF_ENTRY_EX are used when an exception or termination
// handler is provided.
//
//
// NESTED_ENTRY always saves the LR register. Fsize must account for this.
// Fsize must be a multiple of 8 bytes.
// Minimum stack frame size is 64 bytes.
//
//
// The PROLOGUE_END macro must be coded in all routines that used NESTED_ENTRY
// or NESTED_ENTRY_EX, because the function table entry refers to the label
// that it generates.
//
// SPECIAL_ENTRY is a used for routines that function like a LEAF_ENTRY
// but require some prologue for exception handling. An example of this
// is a stack checking routine which must make a system call to get
// the TEB pointer. The efficiency of a LEAF_ENTRY is needed, but also
// parts of the NESTED_ENTRY are required for the system call.
//
// Just like the NESTED_ENTRY, SPECIAL_ENTRY requires the PROLOGUE_END
// macro.
//
// FN_TABLE, DUMMY_ENTRY, and DUMMY_EXIT are used to construct the "prologues"
// for low-level exception handling code. These prologues are never executed,
// but are present to allow unwinding through the hand-written low-level
// assembly code. See real0.s for examples.
//
// The following macros are provided for coding by assembly language programmers
//
#define NESTED_ENTRY(Name,Fsize,Gprs,Fprs) \
__fntabentry(Name,0,0) ;\
__gendescriptor(Name) ;\
__begintext(Name) ;\
mflr r.0 ;\
__setGPRFrm##Fprs(Fsize,Gprs,Fprs) ;\
__savefpr##Fprs(Fsize,Gprs,Fprs)
#define NESTED_ENTRY_EX(Name,Fsize,Gprs,Fprs,LangHandler,Scope) \
__fntabentry(Name,LangHandler,Scope) ;\
__gendescriptor(Name) ;\
__begintext(Name) ;\
mflr r.0 ;\
__setGPRFrm##Fprs(Fsize,Gprs,Fprs) ;\
__savefpr##Fprs(Fsize,Gprs,Fprs)
#define NESTED_ENTRY_S(Name,Fsize,Gprs,Fprs,Section) \
__fntabentry(Name,0,0) ;\
__gendescriptor(Name) ;\
__begintext_S(Name,Section) ;\
mflr r.0 ;\
__setGPRFrm##Fprs(Fsize,Gprs,Fprs) ;\
__savefpr##Fprs(Fsize,Gprs,Fprs)
#define NESTED_ENTRY_EX_S(Name,Fsize,Gprs,Fprs,LangHandler,Scope,Section) \
__fntabentry(Name,LangHandler,Scope) ;\
__gendescriptor(Name) ;\
__begintext_S(Name,Section) ;\
mflr r.0 ;\
__setGPRFrm##Fprs(Fsize,Gprs,Fprs) ;\
__savefpr##Fprs(Fsize,Gprs,Fprs)
#define NESTED_EXIT(Name,Fsize,Gprs,Fprs) \
Name##.epi: \
lwz r.0,((Fsize)-(4*(Gprs+1)+(8*Fprs)))(r.sp) ;\
__unsetGPRFrm##Fprs(Fsize,Gprs,Fprs) ;\
Name##.end:
#define PROLOGUE_END(Name) \
Name##.body:
#define ALTERNATE_ENTRY(Name) \
__gendescriptor(Name) ;\
__begintext(Name)
#define LEAF_ENTRY(Name) \
__gendescriptor(Name) ;\
__begintext(Name) ;\
Name##.body:
#define LEAF_ENTRY_EX(Name,LangHandler,Scope) \
__gendescriptor(Name) ;\
__begintext(Name) ;\
Name##.body:
#define SPECIAL_ENTRY(Name) \
__fntabentry(Name,0,0) ;\
__gendescriptor(Name) ;\
__begintext(Name)
#define DUMMY_ENTRY(Name) \
__begintext(Name)
#define ALTERNATE_ENTRY_S(Name,Section) \
__gendescriptor(Name) ;\
__begintext_S(Name,Section)
#define LEAF_ENTRY_S(Name,Section) \
__gendescriptor(Name) ;\
__begintext_S(Name,Section) ;\
Name##.body:
#define LEAF_ENTRY_EX_S(Name,LangHandler,Scope,Section) \
__gendescriptor(Name) ;\
__begintext_S(Name,Section) ;\
Name##.body:
#define SPECIAL_ENTRY_S(Name,Section) \
__fntabentry(Name,0,0) ;\
__gendescriptor(Name) ;\
__begintext_S(Name,Section)
#define DUMMY_ENTRY_S(Name,Section) \
__begintext_S(Name,Section)
#define LEAF_EXIT(Name) \
blr ;\
Name##.end:
#define ALTERNATE_EXIT(Name) \
blr
#define SPECIAL_EXIT(Name) \
blr ;\
Name##.end:
#define DUMMY_EXIT(Name) \
Name##.end:
#define FN_TABLE(Name,ExHandler,Data) \
__fntabentry(Name,ExHandler,Data)
//
// Define special section "names" for use with the NESTED/LEAF_ENTRY_S
// macros. For the moment just define all possibilities as .text.
//
#define _TEXT$normal .text
#define _TEXT$00 .text
#define _TEXT$01 .text
//
// Internal macros, used by the above (not for programmer use)
//
#define __gendescriptor(Name) \
.rdata ;\
.align 2 ;\
.globl Name ;\
Name: ;\
.long ..##Name, .toc
#define __fntabentry(Name,ExHandler,Data) \
.pdata ;\
.align 2 ;\
.long ..##Name ;\
.long Name##.end ;\
.long ExHandler ;\
.long Data ;\
.long Name##.body
#define __begintext(Name) \
.text ;\
.align 2 ;\
.globl ..##Name ;\
..##Name:
#define __begintext_S(Name,Section) \
.section Section ;\
.align 2 ;\
.globl ..##Name ;\
..##Name:
//
// KIPCR(reg)
//
// Get address of KiPcr into reg
//
#define KIPCR(reg) li reg, 0xffffd000
//
// DISABLE_INTERRUPTS(p0,s0)
//
// Clear EXTERNAL INTERRUPT ENABLE bit in Machine State Register
// (bit MSR:EE).
//
// The cror instructions in these macros work around 603e/ev errata #15
// by forcing the mtmsr to complete before allowing any subsequent loads
// to issue. The condition register no-op is executed in the system unit
// on the 603. This will not dispatch until the mtmsr completes and will
// halt further dispatch. On a 601 or 604 this instruction executes in
// the branch unit and will run in parallel (i.e., no performance penalty
// except for code bloat).
//
// Returns OLD value in p0
// Destroys s0 (actually, s0 contains new value)
#define DISABLE_INTERRUPTS(p0, s0) ; \
mfmsr p0 ; \
rlwinm s0,p0,0,~MASK_SPR(MSR_EE,1) ; \
mtmsr s0 ; \
cror 0,0,0
#define ENABLE_INTERRUPTS(p0) ; \
mtmsr p0 ; \
cror 0,0,0
//
// RAISE_SOFTWARE_IRQL(p0, p1, s0)
//
// Raise Interrupt Request Level.
// Parameters
// p0 new irql
// p1 pointer to byte to receive old irql
// s0 scratch register (destroyed by this macro)
//
// LOWER_SOFTWARE_IRQL is done in a function rather than a macro.
//
// This macro should only be used to raise the IRQL if the interrupt
// mask does NOT need to be changed.
//
#define RAISE_SOFTWARE_IRQL(p0, p1, s0) ;\
lbz s0, KiPcr+PcCurrentIrql(r.0) ;\
stb p0, KiPcr+PcCurrentIrql(r.0) ;\
stb s0, 0(p1)
//
// SOFTWARE_INTERRUPT(level, scratch)
//
// Set a flag indicating we need to process a software interrupt.
// This flag is checked when priority is lowered below dispatch level.
//
// Parameters
// level is the priority of the interrupt (either DISPATCH_LEVEL
// or APC_LEVEL).
// scratch is a register that will be destroyed by this macro.
//
// The flag is in fact a word in the PCR. There are only two levels of
// software interrupt and we need to be able to set either one atomically.
// To accomplish this we store into a different byte for either of the
// interrupts. To indicate an APC_LEVEL interrupt store a non-zero value
// at pcr->SoftwareInterrupt + 0, DISPATCH_LEVEL store at the same address
// + 1.
//
#define SOFTWARE_INTERRUPT(level, scr) \
li scr, 1 ;\
stb scr, KiPcr+PcSoftwareInterrupt+(level)-APC_LEVEL(r.0)
//
// ACQUIRE_SPIN_LOCK(_lock, _value, _scratch, _try, _spin)
//
// Acquire a spin lock.
//
// _lock is the register that holds the address of the spin lock.
// _value is the register that holds the value to be stored to the
// spin lock to lock it.
// _scratch is a scratch register.
// _try is a label to use in the generated code.
// _spin is the label at an out-of-line location where a
// SPIN_ON_SPIN_LOCK invocation occurs.
//
#if !SPINDBG
#define ACQUIRE_SPIN_LOCK(_lock, _value, _scratch, _try, _spin) \
_try: \
lwarx _scratch, 0, _lock ;\
cmpwi _scratch, 0 ;\
bne- _spin ;\
stwcx. _value, 0, _lock ;\
bne- _spin ;\
isync
#else
#define ACQUIRE_SPIN_LOCK(_lock, _value, _scratch, _try, _spin) \
stw _lock,KiPcr+PcPcrPage2+8(0) ;\
li _scratch,0 ;\
stw _scratch,KiPcr+PcPcrPage2+16(0) ;\
_try: \
lwarx _scratch, 0, _lock ;\
cmpwi _scratch, 0 ;\
bne- _spin ;\
stwcx. _value, 0, _lock ;\
bne- _spin ;\
isync ;\
stw _lock,KiPcr+PcPcrPage2+16(0) ;\
stw _scratch,KiPcr+PcPcrPage2+20(0)
#endif
//
// SPIN_ON_SPIN_LOCK(_lock, _scratch, _try, _spin)
//
// Spin waiting for a spin lock to be released.
//
// _lock is the register that holds the address of the spin lock.
// _scratch is a scratch register.
// _try is the label on the associated ACQUIRE_SPIN_LOCK invocation.
// _spin is a label to use in the generated code.
//
#if !SPINDBG
#define SPIN_ON_SPIN_LOCK(_lock, _scratch, _try, _spin) \
_spin: \
lwz _scratch, 0(_lock) ;\
cmpwi _scratch, 0 ;\
beq+ _try ;\
b _spin
#else
#define SPIN_ON_SPIN_LOCK(_lock, _scratch, _try, _spin) \
_spin: \
stw _lock,KiPcr+PcPcrPage2+12(0) ;\
lwz _scratch, 0(_lock) ;\
cmpwi _scratch, 0 ;\
bne- _spin ;\
stw _lock,KiPcr+PcPcrPage2+24(0) ;\
stw _scratch,KiPcr+PcPcrPage2+12(0) ;\
b _try
#endif
//
// SPIN_ON_SPIN_LOCK_ENABLED(_lock, _scratch, _try, _entry, _spin, _enable, _disable)
//
// Spin with interrupts enabled waiting for a spin lock to be released.
//
// _lock is the register that holds the address of the spin lock.
// _scratch is a scratch register.
// _try is the label on the associated ACQUIRE_SPIN_LOCK invocation.
// _entry is a label to use in the generated code.
// _spin is a label to use in the generated code.
//
// The cror instruction in this macro works around 603e/ev errata #15
// by forcing the mtmsr to complete before allowing any subsequent loads
// to issue. The condition register no-op is executed in the system unit
// on the 603. This will not dispatch until the mtmsr completes and will
// halt further dispatch. On a 601 or 604 this instruction executes in
// the branch unit and will run in parallel (i.e., no performance penalty
// except for code bloat).
//
#if !SPINDBG
#define SPIN_ON_SPIN_LOCK_ENABLED(_lock, _scratch, _try, _entry, _spin, _enable, _disable) \
_entry: \
ENABLE_INTERRUPTS(_enable) ;\
_spin: \
lwz _scratch, 0(_lock) ;\
cmpwi _scratch, 0 ;\
bne- _spin ;\
mtmsr _disable ;\
cror 0,0,0 ;\
b _try
#else
#define SPIN_ON_SPIN_LOCK_ENABLED(_lock, _scratch, _try, _entry, _spin, _enable, _disable) \
_entry: \
ori _scratch,_lock,0 ;\
ori _scratch,_scratch,1 ;\
stw _scratch,KiPcr+PcPcrPage2+12(0) ;\
ENABLE_INTERRUPTS(_enable) ;\
_spin: \
lwz _scratch, 0(_lock) ;\
cmpwi _scratch, 0 ;\
bne- _spin ;\
ori _scratch,_lock,0 ;\
ori _scratch,_scratch,1 ;\
stw _scratch,KiPcr+PcPcrPage2+24(0) ;\
li _scratch,0 ;\
stw _scratch,KiPcr+PcPcrPage2+12(0) ;\
mtmsr _disable ;\
cror 0,0,0 ;\
b _try
#endif
//
// TRY_TO_ACQUIRE_SPIN_LOCK(_lock, _value, _scratch, _try, _fail)
//
// Try to acquire a spin lock.
//
// _lock is the register that holds the address of the spin lock.
// _value is the register that holds the value to be stored to the
// spin lock to lock it.
// _scratch is a scratch register.
// _try is a label to use in the generated code.
// fail_label is the label to jump to if the spin lock is already held.
//
#if !SPINDBG
#define TRY_TO_ACQUIRE_SPIN_LOCK(_lock, _value, _scratch, _try, _fail) \
_try: \
lwarx _scratch, 0, _lock ;\
cmpwi _scratch, 0 ;\
bne- _fail ;\
stwcx. _value, 0, _lock ;\
bne- _try ;\
isync
#else
#define TRY_TO_ACQUIRE_SPIN_LOCK(_lock, _value, _scratch, _try, _fail) \
ori _scratch,_lock,0 ;\
ori _scratch,_scratch,1 ;\
stw _scratch,KiPcr+PcPcrPage2+8(0) ;\
li _scratch,0 ;\
stw _scratch,KiPcr+PcPcrPage2+16(0) ;\
_try: \
lwarx _scratch, 0, _lock ;\
cmpwi _scratch, 0 ;\
bne- _fail ;\
stwcx. _value, 0, _lock ;\
bne- _try ;\
isync ;\
ori _scratch,_lock,0 ;\
ori _scratch,_scratch,1 ;\
stw _scratch,KiPcr+PcPcrPage2+16(0) ;\
li _scratch,0 ;\
stw _scratch,KiPcr+PcPcrPage2+20(0)
#endif
//
// RELEASE_SPIN_LOCK(_lock, _zero)
//
// Release a spin lock.
//
// _lock is the register that holds the address of the spin lock.
// _zero is a register that contains a 0.
//
#if !SPINDBG
#define RELEASE_SPIN_LOCK(_lock, _zero) \
eieio ;\
stw _zero, 0(_lock)
#else
#define RELEASE_SPIN_LOCK(_lock, _zero) \
stw _lock,KiPcr+PcPcrPage2+20(0) ;\
eieio ;\
stw _zero, 0(_lock)
#endif
#endif // _KXPPC_C_HEADER_
#ifndef _PPC601_
#define _PPC601_ 601
#endif
#define PPC60X _PPC601_
//
// Exception entry reasons. Passed to KiDispatchException from
// exception entry routines.
//
#define ppc_machine_check 1
#define ppc_data_storage 2
#define ppc_instruction_storage 3
#define ppc_external 4
#define ppc_alignment 5
#define ppc_program 6
#define ppc_fp_unavailable 7
#define ppc_decrementer 8
#define ppc_direct_store_error 9
#define ppc_syscall 10
#define ppc_trace 11
#define ppc_fp_assist 12
#define ppc_run_mode 13
#define ppc_panic 256
#if !DBG_STORE
#define DBGSTORE(reg,reg2,regv)
#define DBGSTORE_I(reg,reg2,val)
#define DBGSTORE_IRR(reg,reg2,val,regv2,regv3)
#define DBGSTORE_IRRR(reg,reg2,val,regv2,regv3,regv4)
#define DBGSTORE_I_R(reg,reg2,val)
#else
#define STORE_ADDR 0x3800
#if 1
#define DCBST(reg)
#else
#define DCBST(reg) dcbst 0,reg
#endif
#if 0
#define DBGSTORE(reg,reg2,regv)
#else
#define DBGSTORE(reg,reg2,regv) \
mfsprg reg,1; \
lwz reg2,PcSpare+4(reg); \
addi reg2,reg2,16; \
clrlwi reg2,reg2,22; \
stw reg2,PcSpare+4(reg); \
lbz reg,PcNumber(reg); \
slwi reg,reg,10; \
add reg,reg,reg2; \
addi reg,reg,STORE_ADDR; \
oris reg,reg,0x8000; \
stw regv,0(reg); \
DCBST(reg)
#endif
#if 0
#define DBGSTORE_I(reg,reg2,val)
#else
#define DBGSTORE_I(reg,reg2,val) \
mfsprg reg,1; \
lwz reg2,PcSpare+4(reg); \
addi reg2,reg2,16; \
clrlwi reg2,reg2,22; \
stw reg2,PcSpare+4(reg); \
lbz reg,PcNumber(reg); \
slwi reg,reg,10; \
add reg,reg,reg2; \
addi reg,reg,STORE_ADDR; \
oris reg,reg,0x8000; \
li reg2,val; \
stw reg2,0(reg); \
DCBST(reg)
#endif
#if 0
#define DBGSTORE_IRR(reg,reg2,val,regv2,regv3)
#else
#define DBGSTORE_IRR(reg,reg2,val,regv2,regv3) \
.extern KeTickCount; \
mfsprg reg,1; \
lwz reg2,PcSpare+4(reg); \
addi reg2,reg2,16; \
clrlwi reg2,reg2,22; \
stw reg2,PcSpare+4(reg); \
lbz reg,PcNumber(reg); \
slwi reg,reg,10; \
add reg,reg,reg2; \
addi reg,reg,STORE_ADDR; \
oris reg,reg,0x8000; \
li reg2,val; \
stw reg2,0(reg); \
stw regv2,4(reg); \
stw regv3,8(reg); \
lwz reg2,[toc]KeTickCount(r2); \
lwz reg2,0(reg2); \
stw reg2,0xc(reg); \
DCBST(reg)
#endif
#if 0
#define DBGSTORE_IRRR(reg,reg2,val,regv2,regv3,regv4)
#else
#define DBGSTORE_IRRR(reg,reg2,val,regv2,regv3,regv4) \
mfsprg reg,1; \
lwz reg2,PcSpare+4(reg); \
addi reg2,reg2,16; \
clrlwi reg2,reg2,22; \
stw reg2,PcSpare+4(reg); \
lbz reg,PcNumber(reg); \
slwi reg,reg,10; \
add reg,reg,reg2; \
addi reg,reg,STORE_ADDR; \
oris reg,reg,0x8000; \
li reg2,val; \
stw reg2,0(reg); \
stw regv2,4(reg); \
stw regv3,8(reg); \
stw regv4,0xc(reg); \
DCBST(reg)
#endif
#if 0
#define DBGSTORE_I_R(reg,reg2,val)
#else
#define DBGSTORE_I_R(reg,reg2,val) \
mfsprg reg,0; \
lwz reg2,PcSpare+4(reg); \
addi reg2,reg2,16; \
clrlwi reg2,reg2,22; \
stw reg2,PcSpare+4(reg); \
lbz reg,PcNumber(reg); \
slwi reg,reg,10; \
add reg,reg,reg2; \
addi reg,reg,STORE_ADDR; \
li reg2,val; \
stw reg2,0(reg); \
DCBST(reg)
#endif
#endif // DBG_STORE
#if !SPINDBG
#define CHKBRK(reg,label)
#define CHKLOCK(reg,regl,label)
#else
#if 1
#define CHKBRK(reg,label)
#else
#define CHKBRK(reg,label) \
mfsprg reg,1; \
lwz reg,PcSpare+8(reg); \
cmpwi reg,0; \
beq label; \
twi 31,0,0x16; \
label:
#endif
#if 1
#define CHKLOCK(reg,regl,label)
#else
#define CHKLOCK(reg,regl,label) \
.extern KiDispatcherLock; \
lwz reg,[toc]KiDispatcherLock(r2); \
cmpw reg,regl; \
bne label
#endif
#endif // SPINDBG
#if !COLLECT_PAGING_DATA
#define INC_CTR(ctr,rpcr,rscr)
#define INC_CTR2(ctr,rpcr,rscr)
#define INC_GRP_CTR_R(ctr,roff)
#define INC_GRP_CTR(ctr,roff,rscr1,rscr2)
#else
#define CTR_DTLB_MISS 0
#define CTR_DTLB_MISS_VALID_PTE 4
#define CTR_ITLB_MISS 8
#define CTR_ITLB_MISS_VALID_PTE 12
#define CTR_DSI 16
#define CTR_DSI_HPT_MISS 20
#define CTR_ISI 24
#define CTR_ISI_HPT_MISS 28
#define CTR_PCR 32
#define CTR_PCR2 36
#define CTR_STORAGE_ERROR 40
#define CTR_PAGE_FAULT 44
#define CTR_FLUSH_SINGLE 48
#define CTR_FILL_ENTRY 52
#define CTR_FLUSH_CURRENT 56
#define PROC_CTR_SIZE 60
#define GRP_CTR_BASE PROC_CTR_SIZE
#define GRP_CTR_DSI_VALID_PTE (GRP_CTR_BASE + 0)
#define GRP_CTR_DSI_FULL (GRP_CTR_BASE + 4)
#define GRP_CTR_DSI_FOUND (GRP_CTR_BASE + 8)
#define GRP_CTR_FLUSH_SINGLE (GRP_CTR_BASE + 12)
#define GRP_CTR_FLUSH_SINGLE_FOUND (GRP_CTR_BASE + 16)
#define GRP_CTR_FILL_ENTRY (GRP_CTR_BASE + 20)
#define GRP_CTR_FILL_ENTRY_FOUND (GRP_CTR_BASE + 24)
#define GRP_CTR_FILL_ENTRY_FULL (GRP_CTR_BASE + 28)
#define GRP_CTR_SIZE (GRP_CTR_BASE + 32)
#define CTR_SIZE (PROC_CTR_SIZE + GRP_CTR_SIZE)
#define PcSpare (PcPcrPage2+4)
#define PcR31 (PcSpare+4)
#define PcPagingData (PcSpare+8)
#define INC_CTR(ctr,rpcr,rscr) \
lwz rscr,PcPagingData+ctr(rpcr); \
addi rscr,rscr,1; \
stw rscr,PcPagingData+ctr(rpcr)
#define INC_CTR2(ctr,rpcr,rscr) \
mfsprg rpcr,1; \
lwz rscr,PcPagingData+ctr(rpcr); \
addi rscr,rscr,1; \
stw rscr,PcPagingData+ctr(rpcr)
#define INC_GRP_CTR_R(ctr,rgrp) \
ori r0,r30,0; \
mfsprg r30,0; \
stw r31,PcR31(r30); \
lwz r31,PcPagingData+ctr(r30); \
addi r31,r31,1; \
stw r31,PcPagingData+ctr(r30); \
lwz r31,PcR31(r30); \
ori r30,r0,0
#define INC_GRP_CTR(ctr,rgrp,rscr1,rscr2) \
mfsprg rscr2,1; \
lwz rscr1,PcPagingData+ctr(rscr2); \
addi rscr1,rscr1,1; \
stw rscr1,PcPagingData+ctr(rscr2)
#endif // COLLECT_PAGING_DATA
#endif // _KXPPC_