On Fri, 18 Jan 2013, Vincent Pelletier wrote:

> Hi.
>
> I'm looking at asm generated for the following loop (8051, a CYCFX2LP
> actually) with sdcc 3.1.0#7066:
>
> __sbit __at 0x98+1 TI;
> void main() {
>  while (!TI);
>  TI = 0;
> }
>
> I get this:
>
> 00101$:
>       jbc     _TI,00115$
>       sjmp    00101$
> 00115$:
>
> Wouldn't it be more efficient, for such bit polling loop, to use instead:
>
> 00101$:
>       jnb     _TI,00101$
>       clr     _TI
>
> The first version polls _TI every 7 cycles.
> The second version polls _TI every 4 cycles.
> If _TI is set on loop entry, the first version exits after 4 cycles while the
> second exits after 6 cycles. I believe it's sane to assume this is an unlikely
> event, so it shouldn't matter too much.
>
> Regards,
> -- 
> Vincent Pelletier

The compiler is thinking you are trying to use TI as a binary semaphore 
and so implements the sequence with an atomic test and clear to eliminate 
the possibility that an interrupt might occur between the while loop and 
the assignment. It does not realize that you are simply polling a hardware 
status bit followed by a write to a control bit (that happens to be at the 
same location as the status bit). From a C perspective, both of these 
operations look like the same C code.

With TI=0 not present, sdcc would not treat this as a special case and 
instead would use the jnb instruction that you expected. If you were 
simply curious about sdcc's odd instruction selection, I hope this is a 
sufficient explanation of what's going on here. Otherwise, if this cycle 
timing issue is critical in your application and you need to change this 
behavior, there several methods you could use:

1) If there is any operation that is performed after TI=0, that could be 
moved to preceed TI=0, then doing so would keep the compiler from seeing 
this as a semaphore style operation.

2) You could split TI into two bits (that happen to be at the same 
address) and use one for read and one for writes:

  __sbit __at 0x98+1 TI;
  __sbit __at 0x98+1 TIclear;
  void main() {
   while (!TI);
   TIclear = 0;
  }

3) You could use a custom peephole rule:

replace {
%3:
         jbc     %1,%2
         sjmp    %3
%2:
} by {
%3:
         jnb     %1,%3
         clr     %1
} if labelRefCount %2 1

(Just put this in a file "peep.def" (or whatever) and then add the option 
"--peep-file peep.def" to the parameters passed to sdcc when compiling)

   Erik


------------------------------------------------------------------------------
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. SALE $99.99 this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122912
_______________________________________________
Sdcc-user mailing list
Sdcc-user@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sdcc-user

Reply via email to