[libcpu][c28x]Add __rt_ffs support

Use a native instruction "Count Sign Bits" to support fast ffs function, then add __rt_ffs support in C28x.
This commit is contained in:
明德无敌赵晓薇 2019-07-03 19:31:54 +08:00
parent c578016f92
commit d68220d866
2 changed files with 37 additions and 0 deletions

View File

@ -6,6 +6,8 @@
; Change Logs: ; Change Logs:
; Date Author Notes ; Date Author Notes
; 2018-09-01 xuzhuoyi the first version. ; 2018-09-01 xuzhuoyi the first version.
; 2019-06-17 zhaoxiaowei fix bugs of old c28x interrupt api.
; 2019-07-03 zhaoxiaowei add _rt_hw_calc_csb function to support __rt_ffs.
; ;
.ref _rt_interrupt_to_thread .ref _rt_interrupt_to_thread
@ -15,6 +17,7 @@
.def _RTOSINT_Handler .def _RTOSINT_Handler
.def _rt_hw_get_st0 .def _rt_hw_get_st0
.def _rt_hw_get_st1 .def _rt_hw_get_st1
.def _rt_hw_calc_csb
.def _rt_hw_context_switch_interrupt .def _rt_hw_context_switch_interrupt
.def _rt_hw_context_switch .def _rt_hw_context_switch
.def _rt_hw_context_switch_to .def _rt_hw_context_switch_to
@ -229,6 +232,25 @@ _rt_hw_get_st1:
LRETR LRETR
.endasmfunc .endasmfunc
; C28x do not have a build-in "__ffs" func in its C compiler.
; We can use the "Count Sign Bits" (CSB) instruction to make one.
; CSB will return the number of 0's minus 1 above the highest set bit.
; The count is placed in T. For example:
; ACC T maxbit
; 0x00000001 30 0
; 0x00000010 26 4
; 0x000001FF 22 8
; 0x000001F0 22 8
.asmfunc
_rt_hw_calc_csb:
MOV AH, #0
CSB ACC ; T = no. of sign bits - 1
MOVU ACC, T ; ACC = no. of sign bits - 1
SUBB ACC, #30 ; ACC = ACC - 30
ABS ACC ; ACC = |ACC|
lretr
.endasmfunc
; ;
; * void rt_hw_context_switch_to(rt_uint32 to); ; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to ; * r0 --> to

View File

@ -6,6 +6,7 @@
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2018-09-01 xuzhuoyi the first version. * 2018-09-01 xuzhuoyi the first version.
* 2019-07-03 zhaoxiaowei add support for __rt_ffs.
*/ */
#include <rtthread.h> #include <rtthread.h>
@ -19,6 +20,7 @@ static rt_err_t (*rt_exception_hook)(void *context) = RT_NULL;
extern rt_uint16_t rt_hw_get_st0(void); extern rt_uint16_t rt_hw_get_st0(void);
extern rt_uint16_t rt_hw_get_st1(void); extern rt_uint16_t rt_hw_get_st1(void);
extern int rt_hw_calc_csb(int value);
struct exception_stack_frame struct exception_stack_frame
{ {
@ -102,6 +104,19 @@ struct exception_info
struct stack_frame stack_frame; struct stack_frame stack_frame;
}; };
#ifdef RT_USING_CPU_FFS
/*
* This function called rt_hw_calc_csb to finds the first bit set in value.
* rt_hw_calc_csb is a native assembly program that use "CSB" instruction in C28x.
* When you use this function, remember that "int" is only 16-bit in C28x's C compiler.
* If value is a number bigger that 0xFFFF, trouble may be caused.
* Maybe change "int __rt_ffs(int value)" to "rt_int32_t __rt_ffs(rt_int32_t value)" will be better.
*/
int __rt_ffs(int value)
{
return rt_hw_calc_csb(value);
}
#endif
/** /**
* shutdown CPU * shutdown CPU