/* * This expands to a sequence of operations with reg incrementing from * start to end inclusive, of this form: * * op reg, (offset + (width * reg))(base) * * Note that offset is not the offset of the first operation unless start * is zero (or width is zero).
*/
.macro OP_REGS op, width, start, end, base, offset
.Lreg=\start
.rept (\end - \start + 1)
\op .Lreg, \offset + \width * .Lreg(\base)
.Lreg=.Lreg+1
.endr
.endm
/* * This expands to a sequence of register clears for regs start to end * inclusive, of the form: * * li rN, 0
*/
.macro ZEROIZE_REGS start, end
.Lreg=\start
.rept (\end - \start + 1)
li .Lreg, 0
.Lreg=.Lreg+1
.endr
.endm
#define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base); \
XXSWAPD(n,n) #endif /* Save the lower 32 VSRs in the thread VSR region */ #define SAVE_VSR(n,b,base) li b,16*(n); STXVD2X_ROT(n,R##base,R##b) #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base) #define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base) #define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base) #define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base) #define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base) #define REST_VSR(n,b,base) li b,16*(n); LXVD2X_ROT(n,R##base,R##b) #define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base) #define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base) #define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base) #define REST_16VSRS(n,b,base) REST_8VSRS(n,b,base); REST_8VSRS(n+8,b,base) #define REST_32VSRS(n,b,base) REST_16VSRS(n,b,base); REST_16VSRS(n+16,b,base)
/* * b = base register for addressing, o = base offset from register of 1st EVR * n = first EVR, s = scratch
*/ #define SAVE_EVR(n,s,b,o) evmergehi s,s,n; stw s,o+4*(n)(b) #define SAVE_2EVRS(n,s,b,o) SAVE_EVR(n,s,b,o); SAVE_EVR(n+1,s,b,o) #define SAVE_4EVRS(n,s,b,o) SAVE_2EVRS(n,s,b,o); SAVE_2EVRS(n+2,s,b,o) #define SAVE_8EVRS(n,s,b,o) SAVE_4EVRS(n,s,b,o); SAVE_4EVRS(n+4,s,b,o) #define SAVE_16EVRS(n,s,b,o) SAVE_8EVRS(n,s,b,o); SAVE_8EVRS(n+8,s,b,o) #define SAVE_32EVRS(n,s,b,o) SAVE_16EVRS(n,s,b,o); SAVE_16EVRS(n+16,s,b,o) #define REST_EVR(n,s,b,o) lwz s,o+4*(n)(b); evmergelo n,s,n #define REST_2EVRS(n,s,b,o) REST_EVR(n,s,b,o); REST_EVR(n+1,s,b,o) #define REST_4EVRS(n,s,b,o) REST_2EVRS(n,s,b,o); REST_2EVRS(n+2,s,b,o) #define REST_8EVRS(n,s,b,o) REST_4EVRS(n,s,b,o); REST_4EVRS(n+4,s,b,o) #define REST_16EVRS(n,s,b,o) REST_8EVRS(n,s,b,o); REST_8EVRS(n+8,s,b,o) #define REST_32EVRS(n,s,b,o) REST_16EVRS(n,s,b,o); REST_16EVRS(n+16,s,b,o)
/* Macros to adjust thread priority for hardware multithreading */ #define HMT_VERY_LOW or 31,31,31 # very low priority #define HMT_LOW or 1,1,1 #define HMT_MEDIUM_LOW or 6,6,6 # medium low priority #define HMT_MEDIUM or 2,2,2 #define HMT_MEDIUM_HIGH or 5,5,5 # medium high priority #define HMT_HIGH or 3,3,3 #define HMT_EXTRA_HIGH or 7,7,7 # power7 only
/* * Used to name C functions called from asm
*/ #ifdefined(__powerpc64__) && defined(CONFIG_PPC_KERNEL_PCREL) #define CFUNC(name) name@notoc #else #define CFUNC(name) name #endif
/* * We use __powerpc64__ here because we want the compat VDSO to use the 32-bit * version below in the else case of the ifdef.
*/ #ifdef __powerpc64__
/* * __kprobes (the C annotation) puts the symbol into the .kprobes.text * section, which gets emitted at the end of regular text. * * _ASM_NOKPROBE_SYMBOL and NOKPROBE_SYMBOL just adds the symbol to * a blacklist. The former is for core kprobe functions/data, the * latter is for those that incdentially must be excluded from probing * and allows them to be linked at more optimal location within text.
*/ #ifdef CONFIG_KPROBES #define _ASM_NOKPROBE_SYMBOL(entry) \
.pushsection "_kprobe_blacklist","aw"; \
PPC_LONG (entry) ; \
.popsection #else #define _ASM_NOKPROBE_SYMBOL(entry) #endif
/* * LOAD_REG_IMMEDIATE(rn, expr) * Loads the value of the constant expression 'expr' into register 'rn' * using immediate instructions only. Use this when it's important not * to reference other data (i.e. on ppc64 when the TOC pointer is not * valid) and when 'expr' is a constant or absolute address. * * LOAD_REG_ADDR(rn, name) * Loads the address of label 'name' into register 'rn'. Use this when * you don't particularly need immediate instructions only, but you need * the whole address in one register (e.g. it's a structure address and * you want to access various offsets within it). On ppc32 this is * identical to LOAD_REG_IMMEDIATE. * * LOAD_REG_ADDR_PIC(rn, name) * Loads the address of label 'name' into register 'run'. Use this when * the kernel doesn't run at the linked or relocated address. Please * note that this macro will clobber the lr register. * * LOAD_REG_ADDRBASE(rn, name) * ADDROFF(name) * LOAD_REG_ADDRBASE loads part of the address of label 'name' into * register 'rn'. ADDROFF(name) returns the remainder of the address as * a constant expression. ADDROFF(name) is a signed expression < 16 bits * in size, so is suitable for use directly as an offset in load and store * instructions. Use this when loading/storing a single word or less as: * LOAD_REG_ADDRBASE(rX, name) * ld rY,ADDROFF(name)(rX)
*/
/* Be careful, this will clobber the lr register. */ #define LOAD_REG_ADDR_PIC(reg, name) \
bcl 20,31,$+4; \
0: mflr reg; \
addis reg,reg,(name - 0b)@ha; \
addi reg,reg,(name - 0b)@l;
#ifdefined(__powerpc64__) && defined(HAVE_AS_ATHIGH) #define __AS_ATHIGH high #else #define __AS_ATHIGH h #endif
#ifdef CONFIG_PPC_BOOK3E_64 /* * This is used in register-constrained interrupt handlers. Not to be used * by BOOK3S. ld complains with "got/toc optimization is not supported" if r2 * is not used for the TOC offset, so use @got(tocreg). If the interrupt * handlers saved r2 instead, LOAD_REG_ADDR could be used.
*/ #define LOAD_REG_ADDR_ALTTOC(reg,tocreg,name) \
ld reg,name@got(tocreg) #endif
/* offsets for stack frame layout */ #define LRSAVE 16
/* * GCC stack frames follow a different pattern on 32 vs 64. This can be used * to make asm frames be consistent with C.
*/ #define PPC_CREATE_STACK_FRAME(size) \
mflr r0; \
std r0,16(r1); \
stdu r1,-(size)(r1)
/* * This instruction is not implemented on the PPC 603 or 601; however, on * the 403GCX and 405GP tlbia IS defined and tlbie is not. * All of these instructions exist in the 8xx, they have magical powers, * and they must be used.
*/
/* The following stops all load and store data streams associated with stream * ID (ie. streams created explicitly). The embedded and server mnemonics for * dcbt are different so this must only be used for server.
*/ #define DCBT_BOOK3S_STOP_ALL_STREAM_IDS(scratch) \
lis scratch,0x60000000@h; \
.machine push; \
.machine power4; \
dcbt 0,scratch,0b01010; \
.machine pop;
#define DCBT_SETUP_STREAMS(from, from_parms, to, to_parms, scratch) \
lis scratch,0x8000; /* GO=1 */ \
clrldi scratch,scratch,32; \
.machine push; \
.machine power4; \ /* setup read stream 0 */ \
dcbt 0,from,0b01000; /* addr from */ \
dcbt 0,from_parms,0b01010; /* length and depth from */ \ /* setup write stream 1 */ \
dcbtst 0,to,0b01000; /* addr to */ \
dcbtst 0,to_parms,0b01010; /* length and depth to */ \
eieio; \
dcbt 0,scratch,0b01010; /* all streams GO */ \
.machine pop;
/* * toreal/fromreal/tophys/tovirt macros. 32-bit BookE makes them * keep the address intact to be compatible with code shared with * 32-bit classic. * * On the other hand, I find it useful to have them behave as expected * by their name (ie always do the addition) on 64-bit BookE
*/ #ifdefined(CONFIG_BOOKE) && !defined(CONFIG_PPC64) #define toreal(rd) #define fromreal(rd)
/* * We use addis to ensure compatibility with the "classic" ppc versions of * these macros, which use rs = 0 to get the tophys offset in rd, rather than * converting the address in r0, and so this version has to do that too * (i.e. set register rd to 0 when rs == 0).
*/ #define tophys(rd,rs) \
addis rd,rs,0
#define tovirt(rd,rs) \
addis rd,rs,0
#elifdefined(CONFIG_PPC64) #define toreal(rd) /* we can access c000... in real mode */ #define fromreal(rd)
/* * General Purpose Registers (GPRs) * * The lower case r0-r31 should be used in preference to the upper * case R0-R31 as they provide more error checking in the assembler. * Use R0-31 only when really nessesary.
*/
/* * Create an endian fixup trampoline * * This starts with a "tdi 0,0,0x48" instruction which is * essentially a "trap never", and thus akin to a nop. * * The opcode for this instruction read with the wrong endian * however results in a b . + 8 * * So essentially we use that trick to execute the following * trampoline in "reverse endian" if we are running with the * MSR_LE bit set the "wrong" way for whatever endianness the * kernel is built for.
*/
#ifdef CONFIG_PPC_BOOK3E_64 #define FIXUP_ENDIAN #else /* * This version may be used in HV or non-HV context. * MSR[EE] must be disabled.
*/ #define FIXUP_ENDIAN \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b 191f; /* Skip trampoline if endian is good */ \
.long 0xa600607d; /* mfmsr r11 */ \
.long 0x01006b69; /* xori r11,r11,1 */ \
.long 0x00004039; /* li r10,0 */ \
.long 0x6401417d; /* mtmsrd r10,1 */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x14004a39; /* addi r10,r10,20 */ \
.long 0xa6035a7d; /* mtsrr0 r10 */ \
.long 0xa6037b7d; /* mtsrr1 r11 */ \
.long 0x2400004c; /* rfid */ \
191:
/* * This version that may only be used with MSR[HV]=1 * - Does not clear MSR[RI], so more robust. * - Slightly smaller and faster.
*/ #define FIXUP_ENDIAN_HV \
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \
b 191f; /* Skip trampoline if endian is good */ \
.long 0xa600607d; /* mfmsr r11 */ \
.long 0x01006b69; /* xori r11,r11,1 */ \
.long 0x05009f42; /* bcl 20,31,$+4 */ \
.long 0xa602487d; /* mflr r10 */ \
.long 0x14004a39; /* addi r10,r10,20 */ \
.long 0xa64b5a7d; /* mthsrr0 r10 */ \
.long 0xa64b7b7d; /* mthsrr1 r11 */ \
.long 0x2402004c; /* hrfid */ \
191:
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.