how to solve xilinx-gcc compile c-asm error - embedded-linux

asm volatile (
"NEONCopyPLD: \n"
"sub %[dst], %[dst], #64 \n"
"1: \n"
"ldnp q0, q1, [%[src]] \n"
"ldnp q2, q3, [%[src], #32] \n"
"add %[dst], %[dst], #64 \n"
"subs %[sz], %[sz], #64 \n"
"add %[src], %[src], #64 \n"
"stnp q0, q1, [%[dst]] \n"
"stnp q2, q3, [%[dst], #32] \n"
"b.gt 1b \n"
: [dst]"+r"(dst), [src]"+r"(src), [sz]"+r"(sz) : : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "cc", "memory");
{standard input}:634: Error: symbol NEONCopyPLD' is already defined {standard input}:678: Error: symbol NEONCopyPLD' is already defined
when compile this code use gcc, gcc shows a error. I cannot find some solution by google, could someone know how to solve this error?

Related

inline ARMv7-M assembly code into c using gcc and macros

I have this code that works fine:
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word 0x401C4000 \n"
:: "i" (1<<17), "i" (16)
);
}
But to declare .ADDRESS I used the magic number 0x401C4000. I actually have a macro for this.
For Example:
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)ADDR_BASE)
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word %2 \n"
:: "i" (1<<17), "i" (16), "i" (ADDR)
);
}
That doesn't build.
How can I use a macro in this case?
See the edit below. I'm only leaving this first solution as an example of what you shouldn't do.
I found this post where a solution is given to my same problem, but it involves x86.
I wanted to try it anyway, and it works.
Then use %c2 instead of %2, as shown here:
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)0x401C4000)
void function( void )
{
__asm volatile
(
" ldr r3, .ADDRESS \n"
" mov r2, %0 \n"
" str r2, [r3, %1] \n"
".ADDRESS: .word %c2 \n"
:: "i" (1<<17), "i" (16), "i" (ADDR): "r2", "r3", "memory"
);
}
EDIT
The solution I suggested above may not work by seeing the generated code:
20 function:
21 # Function supports interworking.
22 # args = 0, pretend = 0, frame = 0
23 # frame_needed = 1, uses_anonymous_args = 0
24 # link register save eliminated.
25 0000 04B02DE5 str fp, [sp, #-4]!
26 0004 00B08DE2 add fp, sp, #0
27 .syntax divided
28 # 6 "test.c" 1
29 0008 04309FE5 ldr r3, .ADDRESS
30 000c 0228A0E3 mov r2, #131072
31 0010 102083E5 str r2, [r3, #16]
32 0014 00401C40 .ADDRESS: .word 1075593216
33
34 # 0 "" 2
35 .arm
36 .syntax unified
37 0018 0000A0E1 nop
38 001c 00D08BE2 add sp, fp, #0
39 # sp needed
40 0020 04B09DE4 ldr fp, [sp], #4
41 0024 1EFF2FE1 bx lr
You can see at line 32 the symbol .ADDRESS has been issued, but it is surrounded by code, and there is no instruction to skip it. I believe that it can be attempted to be executed as if it were an instruction.
Maybe a better solution, suggested by Peter, is
#define ADDR_BASE 0x401C4000
#define ADDR ((void *)0x401C4000)
void function( void )
{
__asm volatile
(
"str %0, [%2, %1]"
:: "r" (1<<17), "i" (16), "r" (ADDR) : "memory"
);
}

error: 'asm' operand has impossible constraints (A53) - gcc 9.3.1

This is code to read 64bit address space. Issue showed up with gcc 9.3.1, did not have issue with earlier version of gcc
static inline void write_to_64bit_address(uint64_t address,
uint32_t data) {
uint32_t address_upper = (uint32_t)(address >> 32);
uint32_t address_lower = (uint32_t)(address);
uint32_t smc_code = SMC_LONG_ADDRESS_WRITE_SINGLE;
asm volatile("mov r0, %[smc_code]\n"
"mov r1, %[addr_upper]\n"
"mov r2, %[addr_lower]\n"
"mov r3, %[data_all]\n"
"mov r4, %[smc_zero]\n"
"mov r5, %[smc_zero]\n"
"mov r6, %[smc_zero]\n"
"smc #0\n"
:
: [smc_code] "r"(smc_code),
[addr_upper] "r"(address_upper),
[addr_lower] "r"(address_lower),
[data_all] "r"(data),
[smc_zero] "g"(SMC_ZERO)
: "r0","r1","r2","r3","r4", "r5", "r6");
}
I don't understand this assembly as well and learning. Can someone help.

Using scanf_s in dev-C++ gives error: 'scanf_s' was not declared in this scope

[Error] 'scanf_s' was not declared in this scope
I'm new here and i don't know much about programming
We use this type of programming at University.
we add this before main body /*#include ,#pragma warning(disable:4996)
#include<stdio.h>
int main()
{
int _a;
char _b;
printf("Zadaj cislo od 0 do 15: ");
scanf_s("%d",&_a);
asm(".intel_syntax noprefix \n"
"mov eax, _a \n"
"mov ecx, 9 \n"
"cmp eax,ecx \n"
"jg vacsie \n "
"jl mensie \n"
"mensie: \n"
"add eax, '0' \n"
"jmp end"
"vacsie: \n"
"add eax,55 \n"
"end:"
"mov _b,al"
".att_syntax \n"
);
if (_a<=15 && _a>0)
printf("v hexa %c \n",_b);
else printf("cislo nieje spravne");
getchar();
return 0;
}

GCC Inline Assembler "memory" Clobber don't prevent from re-arrange the code in ARM

I read article about GCC Inline Assembler
(http://www.ethernut.de/en/documents/arm-inline-asm.html).
In this article, "memory" Clobber forces the compiler to store all
cached values before and reload them after executing the assembler
instructions. And it must retain the sequence.
this is the example.
The following code intends to multiply c with b, of which one or both
may be modified by an interrupt routine. Disabling interrupts before
accessing the variables and re-enable them afterwards looks like a
good idea.
This may fail. Because the optimizer may decide to do the
multiplication first and then execute both inline assembler
instructions or vice versa. :
asm volatile("mrs r12, cpsr\n\t"
"orr r12, r12, #0xC0\n\t"
"msr cpsr_c, r12\n\t" ::: "r12", "cc");
c *= b; /* This may fail. */
asm volatile("mrs r12, cpsr\n"
"bic r12, r12, #0xC0\n"
"msr cpsr_c, r12" ::: "r12", "cc");
This is safe by adding "memory" Clobber .
asm volatile("mrs r12, cpsr\n\t"
"orr r12, r12, #0xC0\n\t"
"msr cpsr_c, r12\n\t" :: : "r12", "cc", "memory");
c *= b; /* This is safe. */
asm volatile("mrs r12, cpsr\n"
"bic r12, r12, #0xC0\n"
"msr cpsr_c, r12" ::: "r12", "cc", "memory");
But I disassemble code by objdump -d . "memory" Clobber don't works,
the code is to do execute both inline assembler instructions, and then
do the multiplication.
mrs ip, CPSR
orr ip, ip, #192 ; 0xc0
msr CPSR_c, ip
mrs ip, CPSR
bic ip, ip, #192 ; 0xc0
msr CPSR_c, ip
mul r0, r1, r0
mov pc, lr
Can anyone explain why"memory" Clobber don't works?
note:
source code.it may fail.
#include <stdio.h>
int main()
{
int a = mul(20, 10);
printf("%d a\n", a);
return 0;
};
int mul(int b, int c)
{
asm volatile("mrs r12, cpsr\n\t"
"orr r12, r12, #0xC0\n\t"
"msr cpsr_c, r12\n\t" ::: "r12", "cc");
c *= b; /* This may fail. */
asm volatile("mrs r12, cpsr\n"
"bic r12, r12, #0xC0\n"
"msr cpsr_c, r12" : :: "r12", "cc");
return c;
}
~
this is safe.
#include <stdio.h>
int main()
{
int a = mul(20, 10);
printf("%d a\n", a);
return 0;
};
int mul(int b, int c)
{
asm volatile("mrs r12, cpsr\n\t"
"orr r12, r12, #0xC0\n\t"
"msr cpsr_c, r12\n\t" : "=X" (b) :: "r12", "cc");
c *= b; /* This is safe. */
asm volatile("mrs r12, cpsr\n"
"bic r12, r12, #0xC0\n"
"msr cpsr_c, r12" :: "X" (c) : "r12", "cc");
return c;
}
compile and disassemble command:
lumotuwe#ubuntu:~/test_nfc$ arm-linux-gcc -O2 inline_asm.c
lumotuwe#ubuntu:~/test_nfc$ arm-linux-objdump -d a.out
Contrary to the question, the variables a, b and c can not be modified by an interrupt as they are local variables and there is no pointer to them.
If a pointer to the variables is stored in a global variable which an interrupt handler could use access the variable, the "memory" clobber will ensure access to variables is not moved past the asm statement.
Either volatile or a "memory" is required, ther is no need to do both.

How to specify an individual register as constraint in ARM GCC inline assembly?

in x86 inline assembly i can write something like this:
asm ("cpuid"
: "=a" (_eax),
"=b" (_ebx),
"=c" (_ecx),
"=d" (_edx)
: "a" (op));
so in the matchin constraints instead of just writing "=r" and let the compiler chose the register, I can say which particular register i want to use (=a for example to use %eax)
how can I do this for ARM assembly?
the ARM GCC assembly cookbook http://www.ethernut.de/en/documents/arm-inline-asm.html states that i can for example use the constraints
"r" for one of the general purpose registers R0-R15
"w" for one of the VFP floating point registers S0-S31
but how can I constraint an operand for example exactly to s1? or to a particular general purpose register?
I don't think gcc for ARM allows you to use constraints to specify exactly which register to use. However, you can use explicit register variables to specify a register to store a variable in:
register int my_variable asm("r0");
Explicit register variables minimal runnable example
Here is an ARMv8 Linux C freestanding hello world exemplifying https://stackoverflow.com/a/3936064/9160762 with some disassembly analysis:
main.c
#include <inttypes.h>
void _start(void) {
uint64_t exit_status;
/* write */
{
char msg[] = "hello syscall v8\n";
uint64_t syscall_return;
register uint64_t x0 __asm__ ("x0") = 1; /* stdout */
register char *x1 __asm__ ("x1") = msg;
register uint64_t x2 __asm__ ("x2") = sizeof(msg);
register uint64_t x8 __asm__ ("x8") = 64; /* syscall number */
__asm__ __volatile__ (
"svc 0;"
: "+r" (x0)
: "r" (x1), "r" (x2), "r" (x8)
: "memory"
);
syscall_return = x0;
exit_status = (syscall_return != sizeof(msg));
}
/* exit */
{
register uint64_t x0 __asm__ ("x0") = exit_status;
register uint64_t x8 __asm__ ("x8") = 93;
__asm__ __volatile__ (
"svc 0;"
: "+r" (x0)
: "r" (x8)
:
);
}
}
GitHub upstream.
Compile and run:
sudo apt-get install qemu-user gcc-aarch64-linux-gnu
aarch64-linux-gnu-gcc -O3 -std=c99 -ggdb3 -march=armv8-a -pedantic -Wall -Wextra \
-ffreestanding -nostdlib -static -o main.out main.c
qemu-aarch64 main.out
Output:
hello syscall v8
Disassembly:
aarch64-linux-gnu-objdump -S main.out
Output:
main.out: file format elf64-littleaarch64
Disassembly of section .text:
0000000000400110 <_start>:
void _start(void) {
uint64_t exit_status;
/* write */
{
char msg[] = "hello syscall v8\n";
400110: 90000003 adrp x3, 400000 <_start-0x110>
400114: 91056063 add x3, x3, #0x158
void _start(void) {
400118: d10083ff sub sp, sp, #0x20
uint64_t syscall_return;
register uint64_t x0 __asm__ ("x0") = 1; /* stdout */
40011c: d2800020 mov x0, #0x1 // #1
register char *x1 __asm__ ("x1") = msg;
400120: 910023e1 add x1, sp, #0x8
register uint64_t x2 __asm__ ("x2") = sizeof(msg);
400124: d2800242 mov x2, #0x12 // #18
char msg[] = "hello syscall v8\n";
400128: a9401464 ldp x4, x5, [x3]
register uint64_t x8 __asm__ ("x8") = 64; /* syscall number */
40012c: d2800808 mov x8, #0x40 // #64
char msg[] = "hello syscall v8\n";
400130: 79402063 ldrh w3, [x3, #16]
400134: a90097e4 stp x4, x5, [sp, #8]
400138: 790033e3 strh w3, [sp, #24]
__asm__ __volatile__ (
40013c: d4000001 svc #0x0
: "+r" (x0)
: "r" (x1), "r" (x2), "r" (x8)
: "memory"
);
syscall_return = x0;
exit_status = (syscall_return != sizeof(msg));
400140: eb02001f cmp x0, x2
}
/* exit */
{
register uint64_t x0 __asm__ ("x0") = exit_status;
register uint64_t x8 __asm__ ("x8") = 93;
400144: d2800ba8 mov x8, #0x5d // #93
register uint64_t x0 __asm__ ("x0") = exit_status;
400148: 9a9f07e0 cset x0, ne // ne = any
__asm__ __volatile__ (
40014c: d4000001 svc #0x0
: "+r" (x0)
: "r" (x8)
:
);
}
}
400150: 910083ff add sp, sp, #0x20
400154: d65f03c0 ret
Attempt without explicit register variables
Mostly for fun, I tried to reach the same result without using register variables, but I was not able to do it.
In any case, the code would be more complicated, so you are better off just using register variables.
Here is my best attempt:
main.c
#include <inttypes.h>
void _start(void) {
uint64_t exit_status;
/* write */
{
char msg[] = "hello syscall v8\n";
uint64_t syscall_return;
__asm__ (
"mov x0, 1;" /* stdout */
"mov x1, %[msg];"
"mov x2, %[len];"
"mov x8, 64;" /* syscall number */
"svc 0;"
"mov %[syscall_return], x0;"
: [syscall_return] "=r" (syscall_return)
: [msg] "p" (msg),
[len] "i" (sizeof(msg))
: "x0", "x1", "x2", "x8", "memory"
);
exit_status = (syscall_return != sizeof(msg));
}
/* exit */
__asm__ (
"mov x0, %[exit_status];"
"mov x8, 93;" /* syscall number */
"svc 0;"
:
: [exit_status] "r" (exit_status)
: "x0", "x8"
);
}
GitHub upstream.
Disassembly:
main.out: file format elf64-littleaarch64
Disassembly of section .text:
0000000000400110 <_start>:
void _start(void) {
uint64_t exit_status;
/* write */
{
char msg[] = "hello syscall v8\n";
400110: 90000000 adrp x0, 400000 <_start-0x110>
400114: 9105a000 add x0, x0, #0x168
void _start(void) {
400118: d10083ff sub sp, sp, #0x20
char msg[] = "hello syscall v8\n";
40011c: a9400c02 ldp x2, x3, [x0]
400120: a9008fe2 stp x2, x3, [sp, #8]
400124: 79402000 ldrh w0, [x0, #16]
uint64_t syscall_return;
__asm__ (
400128: 910023e3 add x3, sp, #0x8
char msg[] = "hello syscall v8\n";
40012c: 790033e0 strh w0, [sp, #24]
__asm__ (
400130: d2800020 mov x0, #0x1 // #1
400134: aa0303e1 mov x1, x3
400138: d2800242 mov x2, #0x12 // #18
40013c: d2800808 mov x8, #0x40 // #64
400140: d4000001 svc #0x0
400144: aa0003e3 mov x3, x0
: [syscall_return] "=r" (syscall_return)
: [msg] "p" (msg),
[len] "i" (sizeof(msg))
: "x0", "x1", "x2", "x8", "memory"
);
exit_status = (syscall_return != sizeof(msg));
400148: f100487f cmp x3, #0x12
40014c: 9a9f07e1 cset x1, ne // ne = any
}
/* exit */
__asm__ (
400150: aa0103e0 mov x0, x1
400154: d2800ba8 mov x8, #0x5d // #93
400158: d4000001 svc #0x0
"svc 0;"
:
: [exit_status] "r" (exit_status)
: "x0", "x8"
);
}
40015c: 910083ff add sp, sp, #0x20
400160: d65f03c0 ret
This was less efficient for the following reasons:
write constraint p need to use an intermediate register x3 for the add to sp
I don't know how to get the syscall return status without an extra mov to an output register
exit status gets moved one extra time through x1. With register variables is just calculated directly into x0.
Tested in Ubuntu 18.10, GCC 8.2.0, QEMU 2.12.

Resources