Xtensa——内核及汇编
小狼@http://blog.csdn.net/xiaolangyangyang
1、寄存器Windows函数调用机制原理
AR物理寄存器环形Buffer
Xtensa处理器使用AR物理寄存器环形Buffer方式取代函数调用时的通用寄存器压栈,当有32个AR寄存器时,每次函数调用(如call8),AR寄存器滑动8个,替代寄存器压栈,此时只能支持3级子函数调用,超过3级调用需要进行压栈。
一般还支持call4、call8、call12,具体使用哪种方式在生成CPU时已经确定,C编译器默认使用call8。
环形Buffer寄存器每4个为一组(pane),WindowStart的每个比特依次表示是否该组作为逻辑寄存器窗口的起始位置或者占用,当前的逻辑寄存器的起始位置则用WindowBase状态寄存器来表示,如下图所示:
Windows ABI函数调用规范
callx函数调用
call4/call8/call12/callx4/callx8/callx12调用的函数,入口第一条指令必须是entry指令,entry指令必须在PS.WOE=1并且PS.EXCM=0的时候才能正常执行;
call4/call8/call12/callx4/callx8/callx12指令不会旋转寄存器窗口,只将旋转增量写入PS.CALLINC,真正由entry指令进行寄存器窗口旋转操作,WindowStart由entry设置,retw指令清除。
1、call8要求extra save area 16个字节和base save area 16个字节,所以入口处的entry至少是32;
2、call12要求extra save area 32个字节和base save area 16个字节,所以入口处的entry至少是48;
3、C代码编译默认只用call8指令,子函数是以entry 32开始的;
4、采用window的旋转机制,父子函数之间没有寄存器冲突,父函数不需要保存;
5、movsp指令的硬件执行逻辑,中间会触发alloca异常搬运当前堆栈的base save area[sp-16,sp]到新的[as-16,as]范围内,算是lazy restore的一种方式。
callx函数格式
<READ_COMM>:
006136 entry a1, 48
3129 s32i.n a2, a1, 12
31a8 l32i.n a10, a1, 12
4b0c movi.n a11, 4
ffe781 l32r a8, 300002e0 (2fb80d20 <xthal_dcache_region_writeback>)
0008e0 callx8 a8
3128 l32i.n a2, a1, 12
0020c0 memw
0228 l32i.n a2, a2, 0
2129 s32i.n a2, a1, 8
2128 l32i.n a2, a1, 8
1129 s32i.n a2, a1, 4
1128 l32i.n a2, a1, 4
f01d retw.n