由于看到OPENGL ES中有这么一段代码:
#if defined(ARM) && defined(__gnu_linux__)
#define CLEAR_INSN_CACHE(BEG, END) \
{ \
register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \
register unsigned long _end __asm ("a2") = (unsigned long) (END); \
register unsigned long _flg __asm ("a3") = 0; \
register unsigned long _scno __asm ("r7") = 0xf0002; \
__asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \
: "=r" (_beg) \
: "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); \
}
#endif
起作用是用来清除指令缓存
后来在网上查了下相关内容,如下:
引自:http://hi.baidu.com/hellogcc/blog/item/a3a60b062cb6af78020881b2.html
一个蹦床为在运行时,当使用嵌套函数的地址时,创建的一小块代码。其通常驻于栈上,在包含函数的栈帧中。这些宏告诉GCC如何生成代码来分配和初始化一个蹦床。
在蹦床中的指令必须做两件事情:将一个常量地址加载到静态链寄存器中,并跳转到嵌套函数的实际地址。在CISC机器,像m68k上,这要求两条指令,一个move立即数和一个jump。然后两个地址存放在蹦床中作为字长的立即操作数。在RISC机器上,其通常需要分成两部分加载每个地址到寄存器中。然后地址的各部分形成独立的立即操作数。
用来初始化蹦床的代码必须将变量的组成部分——静态链值和函数地址——存储到指令的立即操作数中。在CISC机器上,这是简单的复制每个地址到一个内存引用,在蹦床起始处的合适偏移量上。在RISC机器上,其可能需要拿出部分地址并单独存储它们。
一条C语句,来在流file上,为一个包含蹦床常量部分的数据块输出汇编代码。该代码应该不包括标号——标号被自动考虑。
如果没有定义该宏,其意味着target不需要模版。不要在将蹦床复制到一个地方的块移动代码会比在该处生成它的代码大的系统上定义该宏。
返回蹦床模版被放入的section(参见Sections)。缺省值为readonly_data_section。
一个C表达式,蹦床的字节单位的大小,为整数。
蹦床需要的对齐,以位为单位。
如果没有定义该宏,则使用BIGGEST_ALIGNMENT的值来对齐蹦床。
一条C语句用来初始化蹦床的可变部分。addr为一个RTX,蹦床的地址;fnaddr为一个RTX,嵌套函数的地址;static_chain为一个RTX,当其被调用时,应该传递给函数的静态链值。
一条C语句,应该执行任何机器特定的调整,对蹦床的地址。其参数包含传给INITIALIZE_TRAMPOLINE的地址。对于用于函数调用的地址应该不同于模版被存储的地址的情况,应该赋给addr不同的地址。如果没有定义该宏,则addr将被用于函数调用。
如果没有定义该宏,缺省的蹦床作为一个栈槽被分配。这对于大多数机器是正确的。例外的是一些机器,其不可能在栈区域中执行指令。在这样的机器上,你可能必须实行一个独立的栈,使用该宏,并结合TARGET_ASM_FUNCTION_PROLOGUE 和 TARGET_ASM_FUNCTION_EPILOGUE。
fp指向一个数据结构体,一个struct函数,其描述了对直接包含蹦床所对应函数的函数的编译状态。蹦床的栈槽在该包含函数的栈帧中。其它分配策略可能也必须作一些类似的事情。
在许多机器上实现蹦床是困难的,因为它们具有独立的指令和数据缓存。写到栈位置中使得无法清除指令缓存中的内存,所以当程序跳转到那个位置时,其执行了旧的内容。
有两种可能的解决方法。一种是清除指令缓存的相关部分,当蹦床被建立的时候。另一种是使所有蹦床为等同的,通过使它们跳转到一个标准的子程序中。前者使得蹦床执行更快;后者使得初始化更快。
要在初始化蹦床时清除指令缓存,定义下列宏。
如果被定义,将扩展为一个C表达式,在指定的间隔处来清除指令缓存。该宏的定义通常为一系列asm语句。beg和end都为指针表达式。
操作系统可能还需要栈被设为可执行的,在调用蹦床之前。要实现这种需求,定义下列宏。
定义该宏,如果在执行位于栈上的代码之前必须执行特定的操作。宏应该扩展为一系列的C文件作用域的结构(例如函数)并提供一个唯一的如何口点名为__enable_execute_stack。target负责生成对入口点的调用,例如从INITIALIZE_TRAMPOLINE宏中。
要使用标准的子程序,定义下列宏。另外,你必须确信在蹦床中的指令使用相同的指令来填充整个缓存行,或者蹦床代码的起始处总是在缓存行的某点被对齐。查看m68k.h作为参考。
定义该宏,如果蹦床需要一个特定的子程序来做它们的工作。该宏应该扩展为一系列的asm语句,其将由GCC来编译。它们放在名为__transfer_from_trampoline的库函数中。
如果当你跳转到子程序时,你需要避免普通的被编译的C函数的序言代码,你可以通过在汇编代码中放一个你自己的特定标号。使用一条asm语句来生成汇编标号,另一条语句使得标号为global的。然后蹦床可以使用该标号直接跳到你特定的汇编代码上。