I am trying to implement some simple software delays
using MSP430GCC compiler (-Os optimization).
void DELAY_uS(int count) //** Microsecond delay
{
do {
// Assume four clocks/loop (~1uS @ 4MHz)
} while (--count);
}
void DELAY_mS(int count) //** Millisecond delay
{
while (count--) {
DELAY_uS(250);
DELAY_uS(250);
DELAY_uS(250);
DELAY_uS(250);
}
}
I could not avoid DELAY_uS being optimized away to "reta",
or else bloated with memory accesses due to volatiles
so tried an assembly approach.
void DELAY_uS(int count) //** Microsecond delay
{
#define ASM(string) __asm__ __volatile__(string)
//ASM("add #-1,r12"); // Tried this
//ASM("add #-1,%0" : "=r" (count)); // Tried this
ASM("add #-1,%0" : "=r" (count) : "r" (count)); // And tried this
ASM("jnz $-2");
}
This produces following output.
DELAY_uS is implemented as expected with r12 as the parameter
(as per SLAU646A section6) but calls to DELAY_uS are broken
- being implemented as inline with r14 as an uninitialized parameter.
00010358 <DELAY_uS>:
10358: 3c 53 add #-1, r12 ;r3 As==11
1035a: fe 23 jnz $-2 ;abs 0x10358
1035c: 10 01 reta ;
0001035e <DELAY_mS>:
1035e: 3d 40 fa 00 mov #250, r13 ;#0x00fa
10362: 3c 53 add #-1, r12 ;r3 As==11
10364: 3c 93 cmp #-1, r12 ;r3 As==11
10366: 0a 24 jz $+22 ;abs 0x1037c
10368: 3e 53 add #-1, r14 ;r3 As==11
1036a: fe 23 jnz $-2 ;abs 0x10368
1036c: 3e 53 add #-1, r14 ;r3 As==11
1036e: fe 23 jnz $-2 ;abs 0x1036c
10370: 3e 53 add #-1, r14 ;r3 As==11
10372: fe 23 jnz $-2 ;abs 0x10370
10374: 3e 53 add #-1, r14 ;r3 As==11
10376: fe 23 jnz $-2 ;abs 0x10374
10378: 80 01 62 03 mova #66402, r0 ;0x10362
1037c: 10 01 reta ;
The optimizer decides that since DELAY_uS is such a small function it can
be inlined (using r14) and sets up r13 with the call parameter (250),
but does not move this to r14.
It gets even weirder if I try to sprinkle around volatiles.
For instance it can bloat out DELAY_uS as shown below,
while DELAY_mS still uses the same broken inline as above.
00010358 <DELAY_uS>:
10358: b1 00 02 00 suba #2, r1 ;
1035c: 81 4c 00 00 mov r12, 0(r1) ;
10360: 2c 41 mov @r1, r12 ;
10362: 3c 53 add #-1, r12 ;r3 As==11
10364: 81 4c 00 00 mov r12, 0(r1) ;
10368: fe 23 jnz $-2 ;abs 0x10366
1036a: a1 00 02 00 adda #2, r1 ;
1036e: 10 01
Can suggest how how to pass a function parameter to an inline assembly statement.
Unfortunately 'volatile' does not seem to be the solution here since this makes the volatile
item a memory location which causes unnecessary bloat. I did also try declaring count as
'register' but this seems to be ignored.