I would like to know the meaning of %P3 in the following code:
#define get_user(x, ptr) \
({ \
int __ret_gu; \
register __inttype(*(ptr)) __val_gu asm("%edx"); \
__chk_user_ptr(ptr); \
might_fault(); \
asm volatile("call __get_user_%P3" \
: "=a" (__ret_gu), "=r" (__val_gu) \
: "0" (ptr), "i" (sizeof(*(ptr)))); \
(x) = (__typeof__(*(ptr))) __val_gu; \
__ret_gu; \
})
Moreover in the LLVM IR the code is mapped to:
call { i32*, i64 } asm sideeffect "call __get_user_${3:P}", "={ax},={edx},0,i,~{dirflag},~{fpsr},~{flags}"(i32* %tmp73, i64 4)
My understanding is that this is actually calling a specific function __get_user_X in arch/x86/lib/getuser.S, but it's not clear which one in particular (__get_user_4?).
Finally, I would like to understand the difference between %P and %p.
I think %P3 indicates that the X in __get_user_X is depend on "i" (sizeof((ptr)). Such as sizeof((ptr)) may be 1, 2, 4, 8.
The 3 means the third parameter inside the asm volatile("...") statement. And %P is for string concatenation.
About %P and %p difference, I guess it's for string specification, but I am not sure. I copied following sentences from GCC user manual:
%p Substitutes the standard macro predefinitions for the current target machine.
Use this when running cpp.
%P Like ‘%p’, but puts ‘__’ before and after the name of each predefined macro,
except for macros that start with ‘__’ or with ‘_L’, where L is an uppercase
letter. This is for ISO C.
Related
Trying to multiply 400 by 2 with inline assembly, using the fact imul implicity multiplies by eax. However, i'm getting "undefined reference" compile errors to $1 and $2
int c;
int a = 400;
int b = 2;
__asm__(
".intel_syntax;"
"mov eax, $1;"
"mov ebx, $2;"
"imul %0, ebx;"
".att_syntax;"
: "=r"(c)
: "r" (a), "r" (b)
: "eax");
std::cout << c << std::endl;
Do not use fixed registers in inline asm, especially if you have not listed them as clobbers and have not made sure inputs or outputs don't overlap them. (This part is basically a duplicate of segmentation fault(core dumped) error while using inline assembly)
Do not switch syntax in inline assembly as the compiler will substitute wrong syntax. Use -masm=intel if you want intel syntax.
To reference arguments in an asm template string use % not $ prefix. There's nothing special about $1; it gets treated as a symbol name just like if you'd used my_extern_int_var. When linking, the linker doesn't find a definition for a $1 symbol.
Do not mov stuff around unnecessarily. Also remember that just because something seems to work in a certain environment, that doesn't guarantee it's correct and will work everywhere every time. Doubly so for inline asm. You have to be careful. Anyway, a fixed version could look like:
__asm__(
"imul %0, %1"
: "=r"(c)
: "r" (a), "0" (b)
: );
Has to be compiled using -masm=intel. Notice b has been put into the same register as c.
using the fact imul implicity multiplies by eax
That's not true for the normal 2-operand form of imul. It works the same as other instructions, doing dst *= src so you can use any register, and not waste uops writing the high half anywhere if you don't even want it.
I try to do a simple example to insert, into a C code, a piece of Sparc assembly 32 bits; this little code performs an incrementation on the variable "sum".
The code is :
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
int n;
int sum;
int main ()
{
n = 100;
sum = 0;
struct timeval tv1, tv2;
long long diff;
gettimeofday (&tv1, NULL);
asm volatile ("set sum, %g1\n\t" \
"set n, %g3\n" \
"loop:\n\t" \
"add %g1, 1, %g2\n\t" \
"sub %g3, 1, %g4\n\t" \
"bne loop\n\t" \
"nop\n\t" \
: "=r" (sum)
: "r" (n)
);
gettimeofday (&tv2, NULL);
diff = (tv2.tv_sec - tv1.tv_sec) * 1000000L + (tv2.tv_usec - tv1.tv_usec);
printf ("Elapsed time = %d usec\n", diff);
printf ("Sum = %d\n", sum);
return 0;
}
Unfortunately, compilation with gcc4.1.2 produces the following errors :
loop_dev_for-assembly_code.c: In function #main#:
loop_dev_for-assembly_code.c:18: error: invalid 'asm': invalid operand output code
loop_dev_for-assembly_code.c:18: error: invalid 'asm': operand number out of range
loop_dev_for-assembly_code.c:18: error: invalid 'asm': invalid operand output code
loop_dev_for-assembly_code.c:18: error: invalid 'asm': operand number out of range
loop_dev_for-assembly_code.c:18: error: invalid 'asm': operand number out of range
loop_dev_for-assembly_code.c:18: error: invalid 'asm': operand number out of range
It seems the line 18 corresponds to "asm volatile ("set sum, %g1\n\t" \ ...".
But I don't know how to circumvent these errors. It may come from the variable sum which is set to %g1 register.
About the links between variable belonging to C code and variable localted in Assembly code part. I have also seen, for inputs and outputs parameters, the syntax "=g" (output paramter ??), "g" (input parameter) : I think that it corresponds to different registers between the 2 syntax.
if someone could give to me some clues to understand this link and debug my little code which does a simple loop to increment variable sum.
Thanks for your help, regards.
As somebody else said, there are many errors and misconceptions in your inline assembly code. Here are just a few things. First, in extended asm syntax, you must escape all the '%' symbols with another '%', so for example you need to put '%%g1' instead of '%g1' and do this for all the registers you access. Second, you can't use 'set' for either of the variables n or sum, since they are both stack variables, not globals. You have already declared these variables as positional parameters in your asm statement, so sum is parameter %0 and n is %1. Your add instruction puts the result in %g2, which is never initialized or used anywhere.
I think the entire sequence could be rendered much more simply like this (not tested):
asm volatile ("clr %%g1\n" \
"loop:\n\t" \
"add %%g1, 1, %%g1\n\t" \
"subcc %1, 1, %1\n\t" \
"bne loop\n\t" \
"nop\n\t" \
"mov %%g1, %0\n" \
: "=r" (sum)
: "r" (n)
: "g1" );
I want to use SPI1 on a 18F series PIC as master and then use SPI2 on the same PIC as a slave to another PIC ? Can this be done ?
Yes it can. In fact there would be little point providing two serial modules if you were then constrained to use them in the same way.
As it says in the datasheet:
Note that each operates independently from the other. Also, for each module in SPI mode:
You can see that both master and slave modes are supported.
Each MSSP module has its own set of registers, which are used to configure each module as required.
I use the AD7793 as well, but I've rolled my own SPI_READ and SPI_WRITE macros. These macros work on 16-bit processors, and maybe on 32-bit (I have not tried). The first parameter passed is the SPI port number (e.g. 1 or 2). They work in slave and master mode.
e.g. SPI_WRITE(1, 'H'); or SPI_READ(2, char_to_send, char_to_receive_data);
#define _SPI_WRITE_final(_SPIBUF, _SPIRBF, _SPIROV, ch) \
_SPIROV = 0; \
while (_SPIRBF) \
__asm__ volatile ("mov %0, w0" : : "g"(_SPIBUF) : "cc", "w0"); \
_SPIBUF = (uint8_t)(ch); \
__asm__ volatile ("nop"); \
while (!_SPIRBF);
#define _SPI_WRITE_int(bus, ch) \
_SPI_WRITE_final(SPI##bus##BUF, SPI##bus##STATbits.SPIRBF, \
SPI##bus##STATbits.SPIROV, ch)
#define _SPI_WRITE(bus, ch) do {_SPI_WRITE_int(bus, ch);} while(0)
#define _SPI_READ_final(_SPIBUF, _SPIRBF, _SPIROV, ch_out, ch_in) \
_SPIROV = 0; \
while (_SPIRBF) \
__asm__ volatile ("mov %0, w0" : : "g"(_SPIBUF) : "cc", "w0"); \
_SPIBUF = (uint8_t)(ch_out); \
__asm__ volatile ("nop"); \
while (!_SPIRBF); \
ch_in = _SPIBUF;
#define _SPI_READ_int(bus, ch_out, ch_in) \
_SPI_READ_final(SPI##bus##BUF, SPI##bus##STATbits.SPIRBF, \
SPI##bus##STATbits.SPIROV, ch_out, ch_in)
#define _SPI_READ(bus, ch_out, ch_in) do {_SPI_READ_int(bus, ch_out, ch_in);} while(0)
I have the following boost preprocessor macro to generate a function
extern "C" EXPORT out name(BOOST_PP_SEQ_FOR_EACH_I(PARAMETER_LIST, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))
This works great unless if __VA_ARGS__ is empty. After some searching I found a way to count the numer of arguments in __VA_ARGS__ using BOOST_PP_VARIADIC_SIZE. After some thinking I wrote this MACRO:
extern "C" EXPORT out name(BOOST_PP_IF(BOOST_PP_VARIADIC_SIZE(__VA_ARGS__), BOOST_PP_SEQ_FOR_EACH_I(PARAMETER_LIST, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), void))
I think this should work, however I keep getting the following warning
warning C4002: too many actual parameters for macro 'BOOST_PP_IIF_1'
Although this is a warning it still seems to break the preprocessor. When passing multiple arguments it will only process the first one. I find this so strange, how will adding this if break everything is such a weird way? I've checked the comma's and brackets hundred times but they seem fine. How can I fix this preprocessor?
http://www.boost.org/doc/libs/1_54_0/libs/preprocessor/doc/ref/if.html
Edit: this regression seems relevant: https://svn.boost.org/trac/boost/ticket/8606
implementation:
#include <boost/preprocessor.hpp>
// based on the: http://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments
#define __ARG16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define __HAS_COMMA(...) __ARG16(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0)
#define __TRIGGER_PARENTHESIS_(...) ,
#define __PASTE5(_0, _1, _2, _3, _4) _0 ## _1 ## _2 ## _3 ## _4
#define __IS_EMPTY_CASE_0001 ,
#define __IS_EMPTY(_0, _1, _2, _3) __HAS_COMMA(__PASTE5(__IS_EMPTY_CASE_, _0, _1, _2, _3))
#define TUPLE_IS_EMPTY(...) \
__IS_EMPTY( \
/* test if there is just one argument, eventually an empty one */ \
__HAS_COMMA(__VA_ARGS__), \
/* test if _TRIGGER_PARENTHESIS_ together with the argument adds a comma */ \
__HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__), \
/* test if the argument together with a parenthesis adds a comma */ \
__HAS_COMMA(__VA_ARGS__ (/*empty*/)), \
/* test if placing it between _TRIGGER_PARENTHESIS_ and the parenthesis adds a comma */ \
__HAS_COMMA(__TRIGGER_PARENTHESIS_ __VA_ARGS__ (/*empty*/)) \
)
#define __GEN_EMPTY_ARGS(...) \
void
#define __GEN_NONEMPTY_ARGS_CB(unused, data, idx, elem) \
BOOST_PP_COMMA_IF(idx) elem arg##idx
#define __GEN_NONEMPTY_ARGS(seq) \
BOOST_PP_SEQ_FOR_EACH_I( \
__GEN_NONEMPTY_ARGS_CB \
,~ \
,seq \
)
#define GEN(out, name, ...) \
extern "C" EXPORT out name( \
BOOST_PP_IF( \
TUPLE_IS_EMPTY(__VA_ARGS__) \
,__GEN_EMPTY_ARGS \
,__GEN_NONEMPTY_ARGS \
)(BOOST_PP_TUPLE_TO_SEQ((__VA_ARGS__))) \
) {}
// test
GEN(void, finc0, int, char, long)
GEN(void, func1)
output:
extern "C" EXPORT void finc0( int arg0 , char arg1 , long arg2 ) {}
extern "C" EXPORT void func1( void ) {}
I am using Visual Studio, developing a native application, I have a programmatical breakpoint (assert) in my code placed using __asm int 3 or __debugbreak. Sometimes when I hit it, I would like to disable it so that successive hits in the same debugging session no longer break into the debugger. How can I do this?
x86 / x64
Assuming you are writing x86/x64 application, write following in your watch window:
x86: *(char *)eip,x
x64: *(char *)rip,x
You should see a value 0xcc, which is opcode for INT 3. Replace it with 0x90, which is opcode for NOP. You can also use the memory window with eip as an address.
PPC
Assuming you are writing PPC application (e.g. Xbox 360), write following in your watch window:
*(int *)iar,x
You should see a value 0xfeNNNNNN, which is opcode for trap (most often 0x0fe00016 = unconditional trap). Replace it with 0x60000000, which is opcode for NOP.
You might try something like this:
#define ASSERT(x) {\
if (!(x)) \
{ \
static bool ignore = false; \
if (!ignore) \
{ \
ignore = true; \
__asm int 3 \
} \
}\
}
This should hit the debug only once. You might even show a messagebox to the user and ask what to do: continue (nothing happens), break (int 3 is called) or ignore (ignore is set to true, the breakpoint is never hit again)