----- Ursprüngliche Nachricht -----
Von: David Brown
Gesendet am: 22 Aug 2012 23:28:09
>>      volatile unsigned char state;
>>      ...
>>      state |= (state>>  1)&  DIRTY_FLAG;
>>
>> the compiler apparently generates code like this > instead:
>>      MOV.B&state, R15
>>      MOV.B&state, R14
>>      RRUM   #0x0001, R15
>>      AND.B  #0x0002, R15
>>      BIS.B  R14, R15
>>      MOV.B  R15,&state
>>I really want the compiler to generate code like this:
>>      MOV.B&state, R15
>>      RRUM   #0x0001, R15
>>      AND.B  #0x0002, R15
>>      BIS.B  R15,&state
>> Besides being smaller and faster, this actually does the right thing.

> No, it does not "do the right thing".  It might do what you want - but 
> it does not implement the C code you wrote.  Single "state" is volatile, 
> the code generated by the compiler is optimal.

The compiler code might be do wha tis asked for, but it surely isn't optimal.
I too had expected the compiler to first resolve the rvalue
then use a BIS.B instruction on the target
Instead, state is read twice (which is correct since it is volatile and the 
formula
reads it twice), then all the calculations are done in registers and then the
result is written abck to state.
Both versions read state twice and write it once, but the first one is 
unnecessarily inefficient. 
Maybe the compiler is too smart here. An old-fashioned non-optimizing
compiler would likely have produced the second result by simply parsing 
the instruction.

I think it's a flaw in the compiler that it doesn't use  BIS Rx, &y for an |= 
instruction where the result of the right-side value is in Rx.
It only does so if the rvalue is a compile-time constant. However,
the strength of the MSP CPU is the orthogonality fo operands for
almost all instructions.
There is apparently still some room for improvements.
I guess (and it's only a guess) that the compiler will also push
parameters on stack by loading them into a register and pushing the
register instead of just pushing the immediate value or the
memory content to the stack.
I know GCC is designed to be processor-independent, and not many
processors offer this kind of orthogonality, but then, producing small
and fast code is a reason why people choose a compiler.
(except for those who have to run the same code on several different
platforms)



> First off, you can check that the C code you wrote is what you meant to 
> write - the shift operation here looks very out of place.

This may or may not be. But this is not the question here. The generated
assembly code has to do what the C code says, and most efficiently so.
If the C code is wrong, the result is wrong too, but it's not the job of the
compiler to only compile code that seems to be correct to you.

>From the code snippet you cannot even imagine what it is intended to do.
It may be that state is shifted all day long and sometimes get the dirty 
flag or'ed in and if this didn't happen, state will be clear after some shifts.
Or it may be complete nonsense. 
Fact is, that the compiler doesn't compile this rather simple line as 
William (and I) would expect it.

> Then you can look at doing /correct/ treatment of mixing data between an 
> ISR and a main loop.  That means you don't mix different sorts of 
> information within a single byte, but keep all your accesses simple so 
> that they are atomic (or you disable interrupts, or provide additional 
> locking mechanisms). 

This is a good advice, but still off-topic.

> Your "desired" code is not atomic, and will cause  trouble. 
Indeed, the code won't be atomic in either version.
The chance for a failure is significantly larger in the first version but 
exists in the second too.
However, design flaws are no excuse for an inefficiently compilation of
explicitely given code. No matter how much sense this code may make
in the global context.
taken further, this argument would scale to "If you wouldn't write code,
the compiler wouldn't compile it wrong", which obviously is no point.

> If you want to get code generated they way you describe, you need to 
> remove the "volatile" qualifier.

I don't think so. The 'expected' code is totally compliant with the volatile 
restrictions. But without beign volatile, the code might look completely
different

> But the code may still fail because the operation is not atomic.

Nobody denied that. Only operations with an rvalue that has no 
volatile parts could be made atomic. And apparently only constant
rvalues lead  to an atomic operation with the current compiler version.



----- Ursprüngliche Nachricht -----
Von: William Swanson
Gesendet am: 23 Aug 2012 22:52:09

On Thu, Aug 23, 2012 at 12:49 PM, William Swanson <swanson...@gmail.com> wrote:
>>> Another option is a single inline assembly call for the "|=" if the above
>>> code split does not help.
>> I've had to do this in a few places, like when I need to atomically
>> update a hardware flag.
> I just realized something horrible. Code like this is not safe:
> P1IFG &= ~P1_PWR_SW;
> There is no assurance that the "&=" operator will work atomically.
> Even if it does compile to the correct "bis.b" instruction, what
> happens if another IO pin toggles mid-instruction? Could the
> transition be lost? Hopefully the chip designers accounted for this,
> but it's still a scary thought.

Congratulations! You just discovered a well-known erratum in the 1x family 
(and to lesser extent in all families).
Any RMW operation, even if atomic, to a regsiter that is updated 
asynchronously to MCLK may result in lost bits.
On 1x family, teh hardware was unable to set the port IFG bit if the processor
was just reading or writing the register.
Also, if the processor is just clearing IFG bits in the port IFG register,
it may happen that the interrupt that happens after the read part and before 
the write part of the RMW instruciton is lost.

On newer MSP families, this has been addressed by the introduction of the IV 
registers for almost every interrupt source.






----- Ursprüngliche Nachricht -----
Von: Grant Edwards
An: mspgcc-users@lists.sourceforge.net
Gesendet am: 24 Aug 2012 17:24:02
Betreff: Re: [Mspgcc-users] Atomic bit-twiddling instructions

>> On many processors doing things like clearing an interrupt flag is
>> done by writing a 1 to the bit you wish to clear.  That makes the
>> hardware implementation much simpler and it lets you use a C statement
>> like:
>>   P1IFG = P1_PWR_SW;
>> Which is much less likely to be a non-atomic operation.

>I've always been a bit baffled why TI didn't follow the normal "write
>1's to clear interrupt flags" paradigm.  Instead, they chose something
>that's more complex for both software and hardware.

This kind of operation only works, if the whole register is made of
IFG bits. However, on MSP, the hardware is modular. Each module
has its own set of registers and often only one IFG bit. So the IFG bits
are mixe dwith other control bits and the 'write 1 to clear'  operation would
clear all non-IFG bits too.
Alternatively, each module would have required a separate register only for
IFGs. TI apparently decided that consistency across modules
(the ports have been the only module where there was a plain IFG register)
was more important than this conveniency. Especially since the MSP CPU
offers BIC and BIS instructions tha twork on memory locations (and therefore
module registers)
Now, about 400 MSP variants later, almost every hardware module has its
own IFG register (timers don't) and it turns out that this might have been a 
bad decision. But since now almost every module also has an IV register, 
this is not important anymore.

And nobody is going to update the old MSPs, as it will break existing code
and existing projects have already worked around these problems.
Hindsight is always easier than foresight.


JMGross


------------------------------------------------------------------------------
Live Security Virtual Conference
Exclusive live event will cover all the ways today's security and 
threat landscape has changed and how IT managers can respond. Discussions 
will include endpoint security, mobile security and the latest in malware 
threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/
_______________________________________________
Mspgcc-users mailing list
Mspgcc-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mspgcc-users

Reply via email to