I'm trying to du some inline assembly code.
My function is
void pixemcpy(unsigned char *im_src, unsigned char *im_dest, int npix)
{
int i;
for(i=0;i<npix;i++) *im_dest++=*im_src++;
}
My assembly inline function is
void inline_pixelcpy(unsigned char *im_src, unsigned char *im_dest, int npix){
__asm__ volatile(
"0: \n"
"ldrb r3, [%[src]], #1 \n"
"strb r3, [%[dst]], #1 \n"
"subs %[iter], %[iter], #1\n"
"bgt 0b\n"
:
: [src] "r" (im_src), [dst] "r" (im_dest), [iter] "r" (npix)
: "cc", "r3"
);
}
Both function are in the same c file!
When I compile my c file that's work's ! Both function do the same thing there is no problem.
If I use -O2 or -O3 gcc option, I have a segmentation fault when returning (not calling) my assembly function !
This problem do not occured if my 2 function are into separate files !
Is there a problem into my inline code ! How can I tell to gcc to not try to optimise my inline code !
thank's
Etienne
Related
I am trying to creat AST for a kernel file using pyCparser and met ParseError.
I preprocessed the file using command like, and no error generated.
clang -E -D'__attribute__(x)=' -D'__extension__=' -D'__signed__=signed' -D'__builtin_va_list=int' ...-c -o /mnt/os_tmp/cparser/test1/clk-pp.c linux/drivers/clk/xx/clk.c
I met errors when parse the file with commands:
pycparser.parse_file('/mnt/os_tmp/cparser/test1/clk-pp.c')
pycparser.plyparser.ParseError: linux/arch/arm64/include/asm/barrier.h:77:6: before: volatile
barrier.h:72
static inline unsigned long array_index_mask_nospec(unsigned long idx,
unsigned long sz)
{
unsigned long mask;
asm volatile(
" cmp %1, %2\n"
" sbc %0, xzr, xzr\n"
: "=r" (mask)
: "r" (idx), "Ir" (sz)
: "cc");
csdb();
return mask;
}
Can somebody help me on the issue?
To start with optimizing my code I have to start with adding assembly code into my C which is crosscompiled with gcc riscv toolchain, to start with I trying to implement simple riscv inline as follows
int src = 1;
int dst;
asm ("mov %1, %0\n\t"
"add $1, %0\n\t"
: "=r" (dst)
: "r" (src));
But error while crosscompiling it as
Error: unrecognized opcode `mov a1,a1'
Error: illegal operands `add $1,a1'
Should I add any specific flags for inline assembly implementation? any help would be great!
I am using Mingw gcc and ld to generate an executable for windows.
I would like to access the start address of a section in c code, but I have tried a lot of methods and no one works.
My linker script file has this:
.data BLOCK(__section_alignment__) :
{
__data_start__ = . ;
*(.data)
*(.data2)
*(SORT(.data$*))
KEEP(*(.jcr))
__data_end__ = . ;
*(.data_cygwin_nocopy)
}
In C code I do this:
extern char __data_start__;
uint32_t test = &__data_start__;
And get this error:
undefined reference to __data_start__
Could anyone help me with this?
Thanks
mingw32 is using leading underscores, i.e. the compiler will add a _ (underscore) to each symbol. The part of the linker description file you are showing is part of the default linker script (at least in my installation), and for your code I am getting the mentioned error for
int main()
{
extern char __data_start__;
return (int) &__data_start__;
}
with -save-temps, the assembly code has
movl $___data_start__, %eax
which has 3 leading _'s not just 2.
Thus, there are 2 solutions: You can advise the compiler to emit __data_start__ as assembly name, which is a GCC extension:
int main()
{
extern char some_identifier __asm("__data_start__");
return (int) &some_identifier;
}
Or you can use _data_start:
int main()
{
extern char _data_start__;
return (int) &_data_start__;
}
Both use __data_start__ in assembly / object file:
movl $__data_start__, %eax
i686-w64-mingw32-nm module.o
U __data_start__
#define MOV_MACRO(R0,R1)\
{\
"mov R0, R1 \n\t"\
}
__asm__ volatile(\
MOV_MACRO(r4,r5)
:"r4","r5"\
);\
Is it possible to use a function like this in an asm block ?
If not, please suggest ways to use it.
Yes, it's possible, but if you need such functionality you probably shouldn't be using inline asm but a separate asm module.
#define MOV_MACRO(R0,R1) "mov " #R0 ", " #R1 "\n\t"
void foo()
{
__asm__ volatile(
MOV_MACRO(r4,r5)
::
:"r4","r5"
);
}
(This is a followup from "Getting GCC to optimize hand assembly")
I've been trying to get GCC (3.3.6-m68hc1x-20060122) to emit bset and bclr assembly instructions using indexed addressing, but no set of constraints I use seems to work.
The asm:
#define bset(base, offset, mask) { \
volatile unsigned char *__base = base; \
const unsigned char __offset = offset; \
const char __mask = mask; \
asm volatile ("bset %0 %1" : "=o" (__base[__offset]) : "X" (__mask),
"x" (__base)); }
The C:
inline void spi_init()
{
bset(_io_ports, M6811_DDRD, 0x38);
bset(_io_ports, M6811_PORTD, 0x20);
bset(_io_ports, M6811_SPCR, (M6811_SPE | M6811_DWOM | M6811_MSTR));
}
The assembly code result:
spi_init:
ldx #_io_ports
; Begin inline assembler code
#APP
bset _io_ports+9 #56
bset _io_ports+8 #32
bset _io_ports+40 #112
; End of inline assembler code
#NO_APP
rts
Now this is really, really close. But unfortunately it's completely invalid. It must read as follows:
spi_init:
ldx #_io_ports
; Begin inline assembler code
#APP
bset 9,x #56
bset 8,x #32
bset 40,x #112
; End of inline assembler code
#NO_APP
rts
What constraints must I use in order to direct GCC to emit that assembly code?
GCC 3.3.6 extended assembly documentation
GCC 3.3.6 constraint documentation