Effect of additionnal save/restore instructions

Leonard Bise leonard.bise at syderal.ch
Wed Apr 24 13:31:48 UTC 2013


Thank you Gedare for the input.
There is also something not very clear for me.
Claudio earlier told me that using %l7 register was not safe but how come?
Since it is a local register I'd expect I can do whatever I want with it?


2013/4/24 Gedare Bloom <gedare at rtems.org>

> This is a lot better. As Joel said, there is still a problem if an
> interrupt can come. For that you should use a general timer if available.
> Also, I made one comment below.
>
>
> On Wed, Apr 24, 2013 at 5:54 AM, Leonard Bise <leonard.bise at syderal.ch>wrote:
>
>> Thanks a lot for your inputs guys. I realise now that I actually didn't
>> know exactly how to write inline assembly code properly.
>>
>> Joel: Yes the goal of this function is to have a known number of cycles.
>> Thank you for your precious input.
>>
>> Here is the final code version we settled on.
>>
>> void SCET_wait_2us(void) {****
>>
>>     {****
>>
>>         /*#[ operation SCET_wait_2us() */****
>>
>>     uint32 count;****
>>
>>         /* Performs a 60us delay using an __asm__ __volatile__ loop, this
>> piece of code has been****
>>
>>          * measured on HW to validate the duration is correct */****
>>
>>     __asm__ __volatile__("set " XSTR(NB_ITER_60US) ", %0" : "=r"(count));
>> ****
>>
>>     __asm__ __volatile__("StartLoop1us:");****
>>
>>     __asm__ __volatile__("dec 1, %0" : "=r" (count));****
>>
>>     __asm__ __volatile__("cmp %0, 0" : "=r" (count));
>>
> While this should work, the count variable is actually an input here, so
> you really just need
> __asm__ __volatile__("cmp %0, 0" : :  "r" (count));
>
> As always, check the output of the assembler pass to make sure your
> function looks like how you expect. The compiler could (in theory) move
> data between memory and register within this code block.
>
>> ****
>>
>>     __asm__ __volatile__("bne StartLoop1us");****
>>
>>     __asm__ __volatile__("nop");****
>>
>>         /*#]*/****
>>
>>     }****
>>
>> }
>>
>>
>> 2013/4/23 Joel Sherrill <joel.sherrill at oarcorp.com>
>>
>>>  Hi
>>>
>>> SPARC register usage combined with the the register windowing
>>> makes things difficult to figure out.  Using save/restore in the middle
>>> of inline assembly like that is too scary for my personal taste. It is
>>> certainly not normal SPARC programming.
>>>
>>> I don't like the fact they used a "trivial" save instruction which adds
>>> 0 bytes to the stack as best I can tell. It is equivalent to
>>> "save %g0,%g0,%g0". Normal usage includes three real arguments
>>> and looks more like this:
>>>
>>>         PUBLIC(_CPU_Context_save_fp)
>>> SYM(_CPU_Context_save_fp):
>>>         save    %sp, -CPU_MINIMUM_STACK_FRAME_SIZE, %sp
>>>
>>> That saves space on the stack to save the window. I THINK the trivial
>>> save rotates the CWP but doesn't make space. I expect this would
>>> lead to a crash eventually as (my guess) is that you end up with
>>> two register windows associated with the same spot on the stack.
>>> You have rotated twice but only saved one hole on the stack. As
>>> you start returning and restoring, I expect this would result in
>>> some odd type of stack reuse.
>>>
>>> My first question is always ... Why is this in inline assembly anyway?
>>>
>>> If it is to do a tight loop with a known number of cycles, then the
>>> second round of questions are:
>>>
>>> + Why didn't they use the proper asm statement constraints?
>>> + Why isn't this asm volatile?
>>> + What happens if an interrupt occurs in the middle of this?
>>>
>>> If you are using a general purpose register gcc may use, then you need to
>>> specify that. Generally speaking, you can declare local variables and
>>> "pass"
>>> them to inline asm via constraint specifications. This lets gcc pick the
>>> register(s)
>>> and avoids one type of trouble.
>>>
>>> There are some asm with constraint examples in cpukit/score/cpu/sparc.
>>>
>>> --joel
>>>
>>>
>>> On 4/23/2013 4:02 AM, Leonard Bise wrote:
>>>
>>> Hello all,
>>>
>>>  I'm having a problem regarding the processor window registers that I
>>> cannot explain easily mostly because I'm not super familiar with this
>>> subject.
>>>
>>>  First, I'm using a LEON2 Sparc v8 processor and RTEMS 4.8 version
>>> which is required by our project.
>>>
>>>  We have a function using inline assembly to perform a flat delay, here
>>> is the code it use.
>>>
>>>   void SCET_wait_2us(void) {
>>>
>>>     {
>>>
>>>         /*#[ operation SCET_wait_2us() */
>>>
>>>         /* Performs a 60us delay using an ASM loop, this piece of code
>>> has been
>>>
>>>          * measured on HW to validate the duration is correct */
>>>
>>>         __asm__("                                \
>>>
>>>                 save;                            \
>>>
>>>                 set " XSTR(NB_ITER_60US) ", %l7; \
>>>
>>>                 StartLoop1us:                    \
>>>
>>>                 dec 1, %l7;                      \
>>>
>>>                 cmp %l7, 0;                      \
>>>
>>>                 bne StartLoop1us;                \
>>>
>>>                 nop;                             \
>>>
>>>                 restore;                         \
>>>
>>>                 ");
>>>
>>>         /*#]*/
>>>
>>>     }
>>>
>>> }
>>>
>>>  Originally this code didn't have the save and restore instruction but
>>> our sub contractor added them because they had problems compiling. I find
>>> it an odd solution but whatever.
>>>
>>>  Once this code was implemented we started seeing random processor
>>> reset occurring in various contexts.
>>>
>>>  I tested this code while being in the Eclipse debugger and once the
>>> crash happened I noticed I had a segmentation fault in Eclipse. I used
>>> GRMON to check the processor register and noticed that the last trap that
>>> occurred was a window underflow trap 0x06.
>>>
>>>  I found in the RTEMS sources the code for this handler, and while I
>>> haven't understood everything I took out that the code was trying to
>>> recover from this error, is this correct?
>>>  I copied the trap handler code below.
>>>
>>>  RTEMS 4.8 branch
>>> file : rtems / c / src / lib / libcpu / sparc / reg_win / window.S
>>> *
>>> *
>>> SYM(window_underflow_trap_handler):
>>>
>>>         /*
>>>          * Calculate new WIM by "rotating" the valid bits in the WIM left
>>>          * by one position. The following shows how the bits move for a
>>> SPARC
>>>          * cpu implementation where SPARC_NUMBER_OF_REGISTER_WINDOWS is
>>> 8.
>>>          *
>>>          * OLD WIM = 76543210
>>>          * NEW WIM = 07654321
>>>          *
>>>          * NOTE: New WIM must be stored in a global register since the
>>>          * "save" instruction just prior to the load of the wim
>>>          * register will result in the local register set changing.
>>>          */
>>>
>>>         mov %wim, %l3 ! Calculate new WIM
>>>         sll %l3, 1, %l4 ! l4 = WIM << 1
>>>         srl %l3, SPARC_NUMBER_OF_REGISTER_WINDOWS-1, %l5
>>>                                         ! l5 = WIM >> (Number Windows-1)
>>>         or %l5, %l4, %l5 ! l5 = (WIM << 1) |
>>>                                         ! (WIM >> (Number Windows-1))
>>>         mov %l5, %wim ! load the new WIM
>>>         nop; nop; nop
>>>         restore ! Two restores to get into the
>>>         restore ! window to restore
>>>         ldd [%sp + 0x00], %l0 ! First the local register set
>>>         ldd [%sp + 0x08], %l2
>>>         ldd [%sp + 0x10], %l4
>>>         ldd [%sp + 0x18], %l6
>>>         ldd [%sp + 0x20], %i0 ! Then the input registers
>>>         ldd [%sp + 0x28], %i2
>>>         ldd [%sp + 0x30], %i4
>>>         ldd [%sp + 0x38], %i6
>>>         save ! Get back to the trap window.
>>>         save
>>>         jmp %l1 ! Re-execute restore.
>>>         rett %l2
>>>
>>>  From my understanding this code should not ever fail, is that correct?
>>> What I'm not sure is that if this type of trap can be a
>>> common occurrence or if that means something went bad in the software.
>>>
>>>  Basically now I removed the save/restore and it seems to be working
>>> fine but I'll have to explain exactly what was happening before.
>>> Is the compiler not expecting the user to add save/restore and could
>>> that lead to the behavior we see sometimes (processor reset). What are the
>>> usual way to handle this type of inline assembly? Never use save/restore?
>>>
>>>  Also our customer gave us a sequence of command to send to the
>>> software that would produce this reset systematically however when we got
>>> the equipment over here, I tried with the same code the sequence and it is
>>> not happening as often as they say. There seem to be a lot of randomness to
>>> this problem.
>>>
>>>  I really hope someone can provide some knowledge on this type of issue.
>>> --
>>>  *
>>> *
>>>  *Léonard Bise*
>>> Software Design Engineer
>>> Direct Line +41 (0)32 338 9902
>>>
>>>  *SYDERAL SA*
>>> Neuenburgstrasse 7
>>> CH-3238 Gals (Switzerland)
>>> Desk Line +41 (0)32 338 9800
>>> Web Site http://www.syderal.ch
>>>
>>>
>>>
>>> --
>>> Joel Sherrill, Ph.D.             Director of Research & Development joel.sherrill at OARcorp.com        On-Line Applications Research
>>> Ask me about RTEMS: a free RTOS  Huntsville AL 35805
>>> Support Available                (256) 722-9985
>>>
>>>
>>
>>
>> --
>> *
>> *
>> *Léonard Bise*
>> Software Design Engineer
>> Direct Line +41 (0)32 338 9902
>>
>> *SYDERAL SA*
>> Neuenburgstrasse 7
>> CH-3238 Gals (Switzerland)
>> Desk Line +41 (0)32 338 9800
>> Web Site http://www.syderal.ch
>>
>> _______________________________________________
>> rtems-users mailing list
>> rtems-users at rtems.org
>> http://www.rtems.org/mailman/listinfo/rtems-users
>>
>>
>


-- 
*
*
*Léonard Bise*
Software Design Engineer
Direct Line +41 (0)32 338 9902

*SYDERAL SA*
Neuenburgstrasse 7
CH-3238 Gals (Switzerland)
Desk Line +41 (0)32 338 9800
Web Site http://www.syderal.ch
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/users/attachments/20130424/1506bf25/attachment.html>


More information about the users mailing list