powerpc-gcc inline assembly function - gcc

i want to use mtspr instruction for a special purpose register whose number in passed to me in a function.
__MTSPR(unsigned int spr, long long val)
i have to put val in spr.
here is what i tried in vain.
__asm__(
"mtspr %[a], %[b] "
: : [a]"I"(spr), [b]"r"(val)
);
i get this error :
ppc_gnu.c: In function '__MTSPR':
ppc_gnu.c:69:2: warning: asm operand 0 probably doesn't match constraints [enabled by default]
ppc_gnu.c:69:2: error: impossible constraint in 'asm'
so how to solve this problem and please no MACROs. i can not modify this function's usage or declaration.

Related

Why does g++ 4.x allows implicit conversion of nullptr to another types when passed as parameter but > 5.x dont?

My understanding is that, nullptr could not be converted implicitly to another types. But later I "found" that it could be converted to bool.
The issue is, I can see it being converted to bool on GCC 4.x, but it complains on GCC > 5.X
#include <iostream>
bool f(bool a){
return !a;
}
// Type your code here, or load an example.
int main() {
return f(nullptr);
}
On >5.x I get
<source>: In function 'int main()':
<source>:7:21: error: converting to 'bool' from 'std::nullptr_t' requires direct-initialization [-fpermissive]
return f(nullptr);
^
<source>:2:6: note: initializing argument 1 of 'bool f(bool)'
bool f(bool a){
^
Compiler returned: 1
I couldn't find anything on the release notes of GCC 5.X that would explain that.
Can be observed here:
https://godbolt.org/g/1Uc2nM
Can someone explain why there is a difference between versions and what rule is applied here.
The rule can be found in C++17 [conv.bool]/1:
For direct-initialization, a prvalue of type std::nullptr_t can
be converted to a prvalue of type bool; the resulting value is false.
Initialization of function parameters is copy-initialization , not direct-initialization. If you are not familiar with this topic; initialization contexts in C++ can be divided into these two classes, and there are some operations that can only occur in direct-initialization.
The restriction to direct-initialization was added in C++14, which could explain the difference between g++ versions.
I assume the purpose of this rule is to raise an error for the exact code you've written: a bool is expected and a null pointer constant was provided; testing a null pointer constant for boolean-ness is not very meaningful since it only has one state anyway.
Remember that nullptr is not a pointer; it's a thing that can be implicitly converted to a null pointer if the code explicitly requests such a conversion. The whole reason for adding it was to fix the hack of 0 being used as a null pointer constant, and inadvertently matching some other template or overload.
The code could be:
return f(static_cast<bool>(nullptr));
or perhaps you could add an overload of f that accepts std::nullptr_t.

Assembler templates, asmSymbolicName and "error: expected string-literal"

I'm trying to use GCC's extended ASM like Microsoft's assembler. Under Microsoft's MASM, we can do the following, where __FUNC is a C variable:
mov eax, __FUNC
According to Extended Asm - Assembler Instructions with C Expression Operands, § 6.44.3.1 Input Operands:
Operands are separated by commas. Each operand has this format:
[ [asmSymbolicName] ] constraint (cexpression)
asmSymbolicName
Specifies a symbolic name for the operand. Reference the name in the assembler template by enclosing it in square brackets (i.e. ‘%[Value]’). The scope of the name is the asm statement that contains the definition. Any valid C variable name is acceptable, including names already defined in the surrounding code...
When I try and use it in code:
unsigned int func = 1;
...
__asm__ __volatile__ (
"movl %[__FUNC], %%eax"
...
:
: __FUNC "" (func)
);
It results in:
cpu.cpp:148:5: error: expected string-literal before ‘__FUNC’
: __FUNC "" (func)
^
cpu.cpp:148:5: error: expected ‘(’ before ‘__FUNC’
cpu.cpp:148:17: error: ‘__FUNC’ was not declared in this scope
...
The best I can tell, I am using __FUNC according to the manual and its description of asmSymbolicName. But obviously I am not since there's an error.
What am I doing wrong?
I also tried the following because the manual told me I could use variable names in surrounding code, but it did not work either:
"movl %[func], %%eax"
...
:
: func "" (func)
And:
"movl %[func], %%eax"
...
:
: func (func)
...
This is correct:
Operands are separated by commas. Each operand has this format:
[ [asmSymbolicName] ] constraint (cexpression)
However [asmSymbolicName] means asmSymbolicName is literally surrounded by square brackets [ and ] (The outside brackets say that it is an optional parameter). You might have been going for this:
uint32_t func = 1;
uint32_t result;
__asm__ __volatile__ (
"movl %[func], %[result]"
: [result]"=a"(result)
: [func]"g"(func)
);
This takes an input parameter of func makes it available as a symbolic name called func within the assembler template. Output parameter is eax (writable) with a symbolic name of result and eax will be stored in the C variable result when finished. I chose "g" since any immediate value, memory address, or register would be appropriate for the source in movl . You could pass an immediate value rather than a "C" variable with:
: [func]"g"(42)

Can't call fseek with inline assembly

#include "stdio.h"
void fseek(void *, int, int);
main () {
FILE* f = fopen("myfile", "rb");
asm("push 2");
asm("push 0");
asm("push f");
asm("call fseek");
asm("add esp, 12");
}
gcc -masm=intel call.c
call.c:(.text+0x2c): undefined reference to `f'
call.c:(.text+0x31): undefined reference to `fseek'
I have been trying to use AT/T syntax but got the same result.
Well you can not write like this, since there is no grantee that symbol f would exist in the generated assembly -- it's merely a symbol in C.
The solution is to use GCC's extended asm syntax. For example, push f could be rewrited into this:
asm volatile ("pushl %0"
: /* no output operands */
: "m" (f)
: /* no clobbered operands */);
As for the function call fseek, I believed your code shall be alright (at least in my experience and on my laptop it works just now). What's your platform info? Do you have glibc or similar things providing the standard libraries of C?
Also Please notice you're using a weird declaration of fseek since it shall at least have a return value according to the C specification.
Just for your information, you may try this style of an indirect call:
asm volatile ("call *%0"
: /* no output operands */
: "r"(fseek)
: /* no clobbered operands */);

GCC: Customizing printf for string output

GCC allows customization of printf specifiers. However, I don't see how I can "teach" it to accept my string class for %s specifier. My string class is a simple wrapper over char pointer and has exactly one member variable (char * data) and no virtual functions. So, it's kind of ok to pass it as-is to printf-like functions in place of regular char *. The problem is that on gcc static analyzer prevents me from doing so and I have to explicitly cast it to const char * to avoid warnings or errors.
My cstring looks something like this:
class cstring
{
cstring() : data(NULL){}
cstring(const char * str) : data(strdup(str)){}
cstring(const cstring & str) : data(strdup(str.data)){}
~cstring()
{
free(data);
}
...
const char * c_str() const
{
return data;
}
private:
char * data;
};
Example code that uses cstring:
cstring str("my string");
printf("str: '%s'", str);
On GCC I get this error:
error: cannot pass objects of non-trivially-copyable type 'class cstring' through '...'
error: format '%s' expects argument of type 'char*', but argument 1 has type 'cstring' [-Werror=format]
cc1plus.exe: all warnings being treated as errors
The C++ standard doesn't require compilers to support this sort of code, and not all versions of gcc support it. (https://gcc.gnu.org/onlinedocs/gcc/Conditionally-supported-behavior.html suggests that gcc-6.0 does, at least - an open question whether it will work with classes such as the one here.)
The relevant section in the C++11 standard is 5.2.2 section 7:
When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg ...
Passing a potentially-evaluated argument of class type (Clause 9)
having a non-trivial copy constructor, a non-trivial move constructor,
or a non-trivial destructor, with no corresponding parameter, is
conditionally-supported with implementation-defined semantics.
(But look on the bright side: if you get into the habit of using c_str, then at least you won't get tripped up when/if you use std::string.)

Use both SSE2 intrinsics and gcc inline assembler

I have tried to mix SSE2 intrinsics and inline assembler in gcc. But if I specify a variable as xmm0/register as input then in some cases I get a compiler error. Example:
#include <emmintrin.h>
int main() {
__m128i test = _mm_setzero_si128();
asm ("pxor %%xmm0, %%xmm0" : : "xmm0" (test) : );
}
When compiled with gcc version 4.6.1 I get:
>gcc asm_xmm.c
asm_xmm.c: In function ‘main’:
asm_xmm.c:10:3: error: matching constraint references invalid operand number
asm_xmm.c:7:5: error: matching constraint references invalid operand number
The strange thing is that in same cases where I have other input variables/registers then it suddenly works with xmm0 as input but not xmm1, etc. And in another case I was able to specify xmm0-xmm4 but not above. A little confused/frustrated about this :S
Thanks :)
You should let the compiler do the register assignment. Here's an example of pshufb (for gcc too old to have tmmintrin for SSSE3):
static inline __m128i __attribute__((always_inline))
_mm_shuffle_epi8(__m128i xmm, __m128i xmm_shuf)
{
__asm__("pshufb %1, %0" : "+x" (xmm) : "xm" (xmm_shuf));
return xmm;
}
Note the "x" qualifier on the arguments and simply %0 in the assembly itself, where the compiler will substitute in the register it selected.
Be careful to use the right modifiers. "+x" means xmm is both an input and an output parameter. If you are sloppy with these modifiers (eg using "=x" meaning output only when you needed "+x") you will run into cases where it sometimes works and sometimes doesn't.

Resources