On Fri, 2010-07-16 at 15:31 +0100, Dave Martin wrote:
Hi Richard,
Am I right in understanding that fsf's primary objection to -mimplicit-it is the resulting unpredictability of the size of the assembler output for asm blocks? Note that the assmbler output size is _already_ unpredictable: what about the variable size of Thumb-2 instructions already, and what about use of assembler directives such as:
GCC will count each statement in the asm as using 4 bytes. So the variable length is not an issue (it over-accounts). It can't account for instructions that are missing from the stream.
#define nops(count) asm( \ ".rept " #count "\n\t" "nop\n\t" ".endr" \ )
This isn't supported in either ARM or Thumb mode.
Presumably this will defeat GCC's literal pool placement on any architecture which has literal pools. Indeed, we can come with an inexhaustible supply of such cases: it's an inevitable result of the separation between GCC and the assembler.
If for Thumb-2 I assume we already have a heuristic that attempts to count the number of instructions and predicts the maximum size of the asm block as n*4 bytes (where n is the instruction count), would it be feasible to estimate a bound of n*6 bytes if using -mimplicit-it? Or, do we dump the literal before the asm block to be on the safe side (and if so, why doesn't this work equally well when using -mimplicit-it?)
That would be overkill.
Re the suggestion that inline asm should be "fixed" to include explicit IT instructions, do you know a practical way to do this?
Run your code through the compiler with the correct assembly option, then fix the errors. The default configuration of the assembler will make it quietly ignore IT instructions in ARM code, so by adding them the worst you do is cause a slight increase in GCC's assumptions about the size of such blocks.
My concern is that with GCC -marm, the inline asm is passed as-is to be interpreted non-unified syntax (for backwards compatibility purposes), whereas with -march>=armv6t2 -mthumb, the asm is passed (again as-is) to be interpreted in unified syntax. But with explicit IT blocks, it's impossible to be compatible with both syntaxes if my understanding is correct: Am I right in thinking that current GNU as in non-unified syntax mode, and indeed legacy versions of the tools will treat the IT instructions as an error and barf? Can you think of a way of working round this?
There really isn't any such thing as non-unified ARM mode assembly. Some asm statements may not be fully conforming (ie use old organization of S and <cond>) but that's all. If the assembler doesn't accept IT in legacy mode then it should be fixed to permit it in the same way as unified mode.
The best I can think of right now is ghastly preprocessor stuff along the lines of
#ifdef __thumb__ /* or more correctly __thumb2__ ? */ #define __asm_it_generic(mnemonic,cond) #mnemonic " " #cond "\n\t" #else #define __asm_it_generic(mnemonic,cond) /* expands to nothing */ #endif
#define __it(cond) __asm_it_generic(it,cond) #define __ite(cond) __asm_it_generic(ite,cond)
/* ... */
asm( __it(eq) "moveq r0, #0\n\t" __ite(eq) "bleq func1\n\t" "blne func2\n\t" );
Yes, you could do something like that.
An alternative, if we are happy to "fix" source packages in a way which breaks building them with older tools, is to pass unified assembler assembler in unified syntax too. But that would require some work in the code gen backend for arm if I understand correctly. But it's a huge task to port everything and some upstream projects may not accept the changes at all. My concern is that without some transitional approach, there's simply too much existing code for this to be viable.
What would their reason be to not accept valid source? The only excuse they could use would be based on an invalid view of the ARM world.
Do you know when unified assmbler support was introduced in fsf?
About 5 years ago would be my best guess. But it's been somewhat progressive.
Cheers ---Dave