I want to translate this function:
iowrite32(mem1, value1);
into assembly code.
mem1 is defined as:
int * mem1;
in order to use ioremap.
I've written this code:
asm volatile(
"mov %[whr],%[wht]"
: [whr] "=r" (mem1)
: [wht] "r" (value)
);
Then I've realized I don't want to move value to mem1, but to the ADDRESS stored in mem1.
How do I write it in assembly?
You might want to take a look at the m constraint
asm volatile(
"mov %[wht], %[whr];"
: [whr] "=m" (*mem1)
: [wht] "r" (value)
);
Related
Trying to save a variable in an arm register using inline assembly.
unsigned int lma_offset = 0x1234; // typically calculated, hardcoded for example
__asm volatile ("MOV R10, %[input]"
: [input] "=r" (lma_offset)
);
This changes lma_offset to 0xd100 in my case, instead of setting the register. What am I doing wrong?
PS: when I declare lma_offset as const it gives a compiler error because lma_offset is used as output. So obviously something is wrong, still I cant find the correct syntax for this.
For future reference, according to Erics comment
const unsigned int lma_offset = 0x10000;
__asm__ volatile ("MOV R10, %[input]"
: // no C variable outputs
: [input] "r" (lma_offset)
: "R10" // tell the compiler R10 is modified
);
using double : and replacing the "=r" with "r" indeed solves the problem.
It would also be possible to ask the compiler to have that constant already in R10 for an asm statement, by using a register local variable to force the "r" input to pick r10. (Then we can omit the redundant mov r10, r10).
register unsigned r10 __asm__("r10") = lma_offset; // picks r10 for "r" constraints, no other *guaranteed* effects
__asm__ volatile ("# inline asm went here" // empty template, actually just a comment you can see if looking at the compiler's asm output
: // no C variable outputs
: [input] "r" (lma_offset)
: // no clobbers needed
);
When writing a register to some output C variable it would result in
unsigned int lma_offset = 0x0;
__asm__ volatile ("MOV %[output], R11"
: [output] "=r" (lma_offset)
// no clobbers needed; reading a register doesn't step on the compiler's toes
);
Not exactly sure how to title this, but
I want to emulate this code:
asm("movl %%fs:0x30, %0" : "=r" (peb) : : );
but I want to specify the offset variably in C
trying:
int mee = 48;
asm("movl %%fs:%1, %0"
: "=r" (peb)
: "r" (mee)
:
);
Error is bad memory operand '%eax'
For what you have written, the compiler translates the first operand to %fs:%eax because it chooses %eax to be the register holding the value of mee. The addressing mode I think you're trying to use is base:offset and the offset must be a value rather than a register. This is the reason for the error "bad memory operand". It worked in the %fs:0x30 case because 0x30 is an immediate value.
To use the register %eax as an offset, try a dereference of it %%fs:(%1) to get the value in the register:
int mee = 48;
asm("movl %%fs:(%1), %0" : "=r" (peb) : "r" (mee) :);
See also this guide, which contains some possibly useful examples of memory access (and more) in inline assembly.
This question already has answers here:
When to use earlyclobber constraint in extended GCC inline assembly?
(2 answers)
Closed 4 months ago.
Following this manual I wanted to create simplest inline AVR assembly snippet possible: copy values of two variables to two other variables.
uint8_t a, b, c, d;
a = 42;
b = 11;
asm(
"mov %0, %2\n\t"
"mov %1, %3\n\t"
: "=r" (c), "=r" (d)
: "r" (a), "r" (b)
);
I would expect it to be equivalent to:
uint8_t a, b, c, d;
a = 42;
b = 11;
c = a;
d = b;
However, after running both values of c and d are equal to 42. If I change the asm snipptet to:
asm(
"mov %0, %3\n\t"
"mov %1, %2\n\t"
: "=r" (c), "=r" (d)
: "r" (a), "r" (b)
);
c is equal to 11 and d is equal to 42 as expected. Similarly, changing both source operands to %2 yields two 42 and setting both of them to %3 yields two 11.
Why the first version does not work as intended?
I would expect it to be equivalent to:
uint8_t a, b, c, d;
a = 42;
b = 11;
c = a;
d = b;
No, it's not1. The reason is that in the C code, one assignment follows after the other, whereas in inline asm, the compiler treats the "code" as if it happens at once. The compiler does not analyze the code in the asm string template in any way, it's just a string on which it performs replacements of %-operands. In
asm ("mov %0, %3" "\n\t"
"mov %1, %2"
: "=r" (c), "=r" (d)
: "r" (a), "r" (b));
the lifetime of a and b ends at the asm, and the lifetime of c and d begins. Therefore, it's totally fine for the compiler to use the same register for, say c and a. This means the output of the 1st move overrides the input of the 2nd move. This is the classic early-clobber situation, and you'll have to tell this fact to the compiler by means of early-clobber modifier &:
asm ("mov %0, %3" "\n\t"
"mov %1, %2"
: "=&r" (c), "=r" (d)
: "r" (a), "r" (b));
However, the code that's generated is sub-optimal because it's actually fine if the compiler uses the same register for c and b, and the same register for d and a. This means you don't need any explicit asm code at all, and everything can be described by means of the constraints:
asm (""
: "=r" (c), "=r" (d)
: "1" (a), "0" (b));
1Apart from that, your asm code tries to implement c = b and d = a, not c = a and d = b.
I want to assign an array using inline assembly using the AT&T syntax. I want to achieve something like the following. Note that rsp here is the %rsp register.
long saved_sp[N];
long new_sp[N];
void some_function( unsigned int tid, ... )
{
// These two lines should be in assembly
saved_sp[tid] = rsp;
rsp = new_sp[tid];
......
}
I'm sure I don't need to warn you...
__asm__ __volatile__ (
"movq %%rsp, (%0, %2, 8)\n\t"
"movq (%1, %2, 8), %%rsp\n\t"
: : "r" (saved_sp), "r" (new_sp), "r" ((long) tid));
Perhaps "memory" should be added as a clobber, but it seems kind of redundant. Wherever you go after this, remember that the frame pointer "%rbp" will be invalidated.
I have to write inline assembly code that executes a custom instruction that I integrated into my hardware.
Depending on what hardware is to find on the actual chip, the instruction behaves differently. My assembly looks as follows:
asm volatile (
" instr_generic %1, %2, %0 \n\t"
: "=r" (c)
: "r" (a), "r" (b)
: "%g0"
);
This instr_generic could now execute either an addition or subtraction for example, depending on what is on the hardware.
Now, instead of instr_generic I wanna write cust_add or cust_sub and this should then be replaced with instr_generic. In other words, it should look like this here
#define cust_add instr_generic
...
asm volatile (
" cust_add %1, %2, %0 \n\t"
: "=r" (c)
: "r" (a), "r" (b)
: "%g0"
);
But I guess I can't use the pre-processor in this context to replace inline assemly is that right? Is there another way to do that easily?
...
#define cust(arg) \
asm volatile (
" " #arg " %1, %2, %0 \n\t" \
: "=r" (c) \
: "r" (a), "r" (b) \
: "%g0" \
)
...
cust(cust_add);
I would either do an if-then-else with the different solutions based on runtime detection of the processor, or to squeeze a little speed, use a function pointer to functions containing the different solution, if detected a then funptr = a_solution, else if detected b then funptr = b_solution, etc. Do that one time then use funptr for the duration of the program.
As already mentioned the custom instruction needs to be compiled at compile time not runtime. if you want to change the instruction runtime that is a third option to do self-modifying code to insert the proper instruction at runtime.
Can't you just use string concatenation? Or is there some reason you can't do it that way?
#define cust_add "instr_generic"
...
asm volatile (
cust_add " %1, %2, %0 \n\t"
: "=r" (c)
: "r" (a), "r" (b)
: "%g0"
);