📄 excarchlib.c
字号:
LOCAL INSTR blCompute ( VOIDFUNCPTR target, /* target address */ INSTR * branch /* address of branch instruction */ ) { INSTR offset; /* Try a PC-relative branch (bl). */ offset = ((int)target - (int)branch); if (SEXT_26BIT(offset) == offset) return (0x48000001 | (offset & 0x03fffffc)); /* Next try an absolute branch (bla). */ offset = (int)target; if (SEXT_26BIT(offset) == offset) return (0x48000003 | (offset & 0x03fffffc)); /* Address cannot be reached by a short branch instruction at <branch>. */ return (INSTR) 0; }/********************************************************************************* blExtract - compute target address of a specified branch instruction** This routine returns the destination address of a branch instruction inst* which is located at address.** RETURNS: target address of the branch.*/LOCAL INSTR blExtract ( INSTR inst, /* branch instruction word */ INSTR * address /* address of branch instruction */ ) { INSTR target = SEXT_26BIT(inst & 0x03fffffc); /* If the AA bit is not set, then this is a PC-relative branch. */ if ( (inst & 0x2) == 0 ) target += (INSTR) address; return target; }/***************************************************************************** vecOffRelocMatch - lookup vector table for relocation offset** This routine looks up the exception vector table excBlTbl[] for the vector* offset specified. If the vector offset is found to be relocated, it* returns the relocated offset. If it is not relocated, or if such an entry* is not found, it returns the vector offset given to it as input.* The status (found unrelocated, found relocated, not found) has no current* use and thus is not returned to optimize performance. This can be added* in future if API not published by then. Probably a user specified* relocation table as well.** RETURNS: The input vector offset if not relocated or if not found in* excBlTbl[], or the relocated vector offset value.**/UINT32 vecOffRelocMatch ( UINT32 vector /* original vector to match */ ) { FAST int i = 0; while (excBlTbl[i].vecOff != 0) { if (excBlTbl[i].vecOff == vector) { if (excBlTbl[i].vecOffReloc == 0) return (vector); else return (excBlTbl[i].vecOffReloc); } i++; } return vector; }/***************************************************************************** vecOffRelocMatchRev - reverse lookup vector table for relocation offset** This routine looks up the exception vector table excBlTbl[] for the* relocated vector offset specified. If such a relocated vector offset* is found, it returns the original offset. If it has not been relocated,* or if such an entry is not found, it returns the vector offset given to* it as input.** RETURNS: The input vector offset if not relocated or if not found in* excBlTbl[], or the relocated vector offset value.**/UINT32 vecOffRelocMatchRev ( UINT32 vector /* relocated vector to match */ ) { FAST int i = 0; while (excBlTbl[i].vecOff != 0) { if (excBlTbl[i].vecOffReloc == vector) return (excBlTbl[i].vecOff); i++; } return vector; }/********************************************************************************* excConnect - connect a C routine to an exception vector** This routine connects a specified C routine to a specified exception* vector. An exception stub is created and in placed at <vector> in the* exception table. The address of <routine> is stored in the exception stub* code. When an exception occurs, the processor jumps to the exception stub* code, saves the registers, and call the C routines.** The routine can be any normal C code, except that it must not* invoke certain operating system functions that may block or perform* I/O operations.** The registers are saved to an Exception Stack Frame (ESF) which is placed* on the stack of the task that has produced the exception. The ESF structure* is defined in /h/arch/ppc/esfPpc.h.** The only argument passed by the exception stub to the C routine is a pointer* to the ESF containing the registers values. The prototype of this C routine* is as follows:* .CS* void excHandler (ESFPPC *);* .CE** When the C routine returns, the exception stub restores the registers saved* in the ESF and continues execution of the current task.** RETURNS: OK if the routine connected successfully, or* ERROR if the routine was too far away for a 26-bit offset.* * SEE ALSO: excIntConnect(), excVecSet()* */STATUS excConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine /* routine to be called */ ) { return ( excRelocConnect (vector, routine, (VOIDFUNCPTR *) 0) ); }/********************************************************************************* excRelocConnect - connect a C routine to an exception vector with possible* relocation** This routine is same as excConnect with an added parameter, which is* the relocation offset of the vector to be installed. If the extra* parameter is non-zero, the vector is installed at this offset instead* of the standard offset specified in the first parameter. A branch* instruction is then written to the original offset to reach the* relocated vector. A relative branch will be used, unless out of the* 26-bit offset range where it will attempt an absolute branch. The* caller should take care of the branch instruction clobbering useful* data specified by vector, including the stub being installed should* the original offset overlaps the stub of the relocated vector.** RETURNS: OK if the routine connected successfully, or* ERROR if the routine was too far away for one branch instr.**/STATUS excRelocConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ VOIDFUNCPTR * vectorReloc /* relocated exception vector */ ) { FAST STATUS rc; FAST INSTR branch; FAST INSTR * newVector; FAST int base = (int) excVecBaseGet (); if ((int) vectorReloc == 0) { newVector = (INSTR *) ( base | (int) vector ); } else { vector = (VOIDFUNCPTR *) ( base | (int) vector ); newVector = (INSTR *) ( base | (int) vectorReloc ); } rc = excConnectVector(newVector, VEC_TYPE_NORM, excEnt, routine, excExit); if ( ((int) vectorReloc != 0) && (rc == OK) ) { /* if relocated vector, write branch (with link bit cleared) */ branch = blCompute ( (VOIDFUNCPTR) newVector, (INSTR *) vector ); if (branch == 0) return ERROR; *vector = (VOIDFUNCPTR) (branch & 0xfffffffe); CACHE_TEXT_UPDATE ((void *) vector, sizeof(INSTR)); } return (rc); }/********************************************************************************* excIntConnect - connect a C routine to an asynchronous exception vector** This routine connects a specified C routine to a specified asynchronous * exception vector, such as the external interrupt vector (0x500) and the* decrementer vector (0x900). An interrupt stub is created and placed at* <vector> in the exception table. The address of <routine> is stored in the* interrupt stub code. When the asynchronous exception occurs, the processor* jumps to the interrupt stub code, saves only the requested registers, and* calls the C routines.** When the C routine is invoked, interrupts are still locked. It is the* C routine responsibility to re-enable interrupts.** The routine can be any normal C code, except that it must not* invoke certain operating system functions that may block or perform* I/O operations.** Before the requested registers are saved, the interrupt stub switches from the* current task stack to the interrupt stack. In the case of nested interrupts,* no stack switching is performed, because the interrupt is already set.** RETURNS: OK if the routine connected successfully, or* ERROR if the routine was too far away for a 26-bit offset.* * SEE ALSO: excConnect(), excVecSet()*/STATUS excIntConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine /* routine to be called */ ) { return ( excRelocIntConnect (vector, routine, (VOIDFUNCPTR *) 0) ); }/********************************************************************************* excRelocIntConnect - connect a C routine to an exception vector with* possible relocation** This routine is same as excIntConnect with an added parameter, which is* the relocation offset of the vector to be installed. If the extra* parameter is non-zero, the vector is installed at this offset instead* of the standard offset specified in the first parameter. A branch* instruction is then written to the original offset to reach the* relocated vector. A relative branch will be used, unless out of the* 26-bit offset range where it will attempt an absolute branch. The* caller should take care of the branch instruction clobbering useful* data specified by vector, including the stub being installed should* the original offset overlaps the stub of the relocated vector.** RETURNS: OK if the routine connected successfully, or* ERROR if the routine was too far away for one branch instr.**/STATUS excRelocIntConnect ( VOIDFUNCPTR * vector, /* exception vector to attach to */ VOIDFUNCPTR routine, /* routine to be called */ VOIDFUNCPTR * vectorReloc /* relocated exception vector */ ) { FAST STATUS rc; FAST INSTR branch; FAST INSTR * newVector; FAST int base = (int) excVecBaseGet (); if ((int) vectorReloc == 0) { newVector = (INSTR *) ( base | (int) vector ); } else { vector = (VOIDFUNCPTR *) ( base | (int) vector ); newVector = (INSTR *) ( base | (int) vectorReloc ); } rc = excConnectVector(newVector, VEC_TYPE_NORM, intEnt, routine, intExit); if ( ((int) vectorReloc != 0) && (rc == OK) ) { /* if relocated vector, write branch (with link bit cleared) */ branch = blCompute ( (VOIDFUNCPTR) newVector, (INSTR *) vector ); if (branch == 0) return ERROR; *vector = (VOIDFUNCPTR) (branch & 0xfffffffe); CACHE_TEXT_UPDATE ((void *) vector, sizeof(INSTR)); } return (rc); }/********************************************************************************* excConnectVector - connect a C routine to an asynchronous exception vector** Code factored from original excIntConnect/excExcConnect.** Should never be called directly except by * excConnect(), or excRelocConnect()* excIntConnect(), or excRelocIntConnect()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -