//++ 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_