This is the mail archive of the crossgcc@sources.redhat.com mailing list for the crossgcc project.

See the CrossGCC FAQ for lots more information.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Q for inline arm assembly: 'M' constraint?


> [code]
> inline int fixp_mul_32s_nX( int a, int b, char n ) {
> 	int res, tmp;
> 	__asm__ __volatile__ (
> 		"smull	%0, %1, %2, %3			\n\t"
> 		"movs	%0, %0, lsr #%4			\n\t"
> 		"adc	%1, %0, %1, lsl #(32-%4)	\n\t"
> 		: "=&r" (res), "=&r" (tmp)
> 		: "r" (a), "r" (b), "M" (n)
> 	);
> 	return res;
> }
> [/code]
> 
> But the assembler complains with the below error output:
> 
> [console]
> arm-elf-gcc -g -c -I ../../include -save-temps -O0 -MMD -MP -MF 
> dep/test_math.d -o obj/test_math.o test_math.c
> In file included from test_math.c:8:
> fixp.h: In function `fixp_mul_32s_nX':
> fixp.h:26: warning: asm operand 4 probably doesn't match constraints
> fixp.h:26: error: impossible constraint in `asm'
> [/console]
> 
> I assume that the problem is something to do with the "M" constraint, as 
> I can use the first function without issue.  So what is the correct way 
> to use the "M" constraint?  Or do I even need the "M" constraint?  Or is 
>   there a better way to do this altogether?

Sorry, the compiler isn't clever enough to support that, and it's not what 
%4 will output anyway (it always puts a '#' in front of an immediate).  
Because you've written this as an inline function 'n' will start off in a 
(pseudo) register, even if you are always calling your inline function 
with an immediate at that point.  You might (but I must emphasise the 
'might', since I haven't tried this), be able to make the following work:

inline int fixp_mul_32s_nX( int a, int b, char n ) {
	int res, tmp;
	int p = 32-n;
	__asm__ __volatile__ (
		"smull	%0, %1, %2, %3			\n\t"
		"movs	%0, %0, lsr %4			\n\t"
		"adc	%1, %0, %1, lsl %5		\n\t"
		: "=&r" (res), "=&r" (tmp)
		: "r" (a), "r" (b), "rM" (n), "rM" (p)
	);
	return res;
}

This allows the compiler to use a register or a constant in the range 
0-31.  But it's quite possible that you will always get a register passed 
in this case.

R.


------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sources.redhat.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]