Inline Assembly
Corrin Meyer
Corrin.Meyer at dornerworks.com
Tue Aug 5 13:58:46 UTC 2008
I am having issues generating inline assembly for the ColdFire with GCC.
Below is the function with inline assembly in question.
static inline uint32_t hal_set_ipl(uint32_t new_ipl)
{
uint32_t old_ipl;
register uint32_t _ipl;
_ipl = (new_ipl & 0x00000007) << 8;
// Get the old IPL setting and set it to the new one.
__asm__ __volatile__ (
"move.w %%sr, %%d7 \n\t"
"move.l %%d7, %0 \n\t"
"andi.l #0xf8ff, %%d7 \n\t"
"or.l %1, %%d7 \n\t"
"move.w %%d7, %%sr \n\t"
: "=d" (old_ipl) : "d" (_ipl) : "%%d7" );
// Mask out non-IPL bits (placed in lower 7 bits).
old_ipl = (old_ipl & 0x0700) >> 8;
return old_ipl;
}
The assembly generated is below (I disabled function inlining for
debugging purposes though I get a similar result even when inlining).
static inline uint32_t hal_set_ipl(uint32_t new_ipl)
{
200006e4: 4e56 0000 linkw %fp,#0
200006e8: 2f07 movel %d7,%sp at -
register uint32_t _ipl;
_ipl = (new_ipl & 0x00000007) << 8;
// Get the old IPL setting and set it to the new one.
__asm__ __volatile__ (
200006ea: 7007 moveq #7,%d0
200006ec: c0ae 0008 andl %fp@(8),%d0
200006f0: e188 lsll #8,%d0
200006f2: 40c7 movew %sr,%d7
200006f4: 2007 movel %d7,%d0
200006f6: 0287 0000 f8ff andil #63743,%d7
200006fc: 8e80 orl %d0,%d7
200006fe: 46c7 movew %d7,%sr
20000700: 0280 0000 0700 andil #1792,%d0
// Mask out non-IPL bits (placed in lower 7 bits).
old_ipl = (old_ipl & 0x0700) >> 8;
return old_ipl;
}
20000706: e088 lsrl #8,%d0
20000708: 2e1f movel %sp at +,%d7
2000070a: 4e5e unlk %fp
2000070c: 4e75 rts
The problem is that register %d0 is being used for both 'old_ipl' and
'_ipl' (as can be seed at 200006f4 and 200006fc) and the result is that
%d7 and hence %sr are not updated appropriately. The purpose of this
function is to set the Interrupt Priority level (IPL) bits in the Status
Register and to return the original value of the IPL bits. I have tried
using both 'r' and 'd' constraints on the output/input to the inline
assembly but both result in this problem. Using a constraint of 'i'
does not work unless optimization level of at least "-O" is used (which
makes since I think since it would actually require the or.l instruction
changing to ori.l and figuring out the actual value of new_ipl at
compile time).
Any insights on why GCC is not allocating the registers correctly (or
maybe I am missing something...)? I can get to straight assembly if
needed but I would prefer, for the simplicity of this series of
instructions, to use inline assembly.
Corrin J. Meyer
DornerWorks, Ltd.
Embedded Systems Engineering
T: 616.389.8336
F: 616.245.8372
E: corrin.meyer at dornerworks.com <mailto:corrin.meyer at dornerworks.com>
3445 Lake Eastbrook Blvd. SE
Grand Rapids, MI 49546
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/coldfire-gnu-discuss/attachments/20080805/3dd3fe45/attachment.html>
More information about the coldfire-gnu-discuss
mailing list