Effect of additionnal save/restore instructions

Gedare Bloom gedare at rtems.org
Wed Apr 24 13:00:35 UTC 2013


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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/users/attachments/20130424/b47bacbc/attachment-0001.html>


More information about the users mailing list