Jumping into ARM assembly


When two lowest bits are set to 1 (and the other bits are 0), the result is 3.
The instruction "tst r0, #3" updates flags based on operation r0 AND 3. So it sets the zero flag only when the lowest two bits are zero.
 
It doesn't need to be reset because AND-ing with 3 sets all bits in the result except the lowest two to zero. (AND-ing with 3 is the same as doing modulo 4)
You can also use and instruction instead of tst - it's easier to understand, but the result is the same:
Code:
add r0, r0, #1
andS r0, r0, #3
beq do_something
 
Oh, that's quite neat. I'd mentioned doing an ANDS test to check the bottom two bits, but I was anticpating just throwing the result away (i'd forgotten the tst mnemonic does that for you), but using ands and overwriting the counter with the result solves two problems with one stone. I'm not sure its actually any faster than the original technique of setting a register to 1001001... and then rotating it indefinitely, since in that case you can increment the counter (rotate it) and get the result in one command, while here you need to add one and then ands test it in two commands, before branching in both cases.
 
Performance-wise, which method for what I do is the best in add vs ror ?

New question !
I'd like to use the getrandom() syscall, but nobody answers when I call the 384. I guess that the number is filled somewhere in the memory, not in a register.
 
getrandom() syscall has three parameters: address of a buffer (which is filled with random data), length of the buffer and flags (see the man page). But the syscall was introduced in version 3.17 of the Linux kernel - Pandora OS uses kernel version 3.2, so the syscall doesn't work on default Pandora OS.
 
I saw these C parameters, but I have no idea how to pass them, and what are their limits.
Yup, I'm on a devboard for this.
 
Well one benefit of ARM over other competing architectures is that in most circumstances you can just count instructions to compare them, since everything other than STM/LDM (and probably a few newer instructions I'm less aware of) takes one tick (apart from branches which you can assume take 5 or so ticks, or whatever your pipeline length is, which is why when you've got an inline conditional where the resulting code is a 4 or less instructions, it's better usually to block it out using a conditional extension like NE or CS - but if you need to loop you're going to have to branch anyway.

As I said before, I reckon your mov r#, r# ror 1 trick beats all the competition, but I can't be bothered to mock up the alternatives, so that's little more than a few instruction counts and a bit on my intuition.

Actually, if you're going for all out speed, you'd be best off unrolling your loop as much as you can. Duplicate your loop code a few times in a row and branch back to the start at the end. If it's an infinite loop like yours you don't even need to test in between each chunk of code and jump to the end if some condition is met. Do it five times in a row and you'll have saved 4 out of every five pipeline length delays - 20 ticks or so every five iterations, which easily beats one or two saved instructions every iteration.
 
Well one benefit of ARM over other competing architectures is that in most circumstances you can just count instructions to compare them, since everything other than STM/LDM (and probably a few newer instructions I'm less aware of) takes one tick (apart from branches which you can assume take 5 or so ticks, or whatever your pipeline length is, which is why when you've got an inline conditional where the resulting code is a 4 or less instructions, it's better usually to block it out using a conditional extension like NE or CS - but if you need to loop you're going to have to branch anyway.
Cortex A8 has a pipeline depth of 13 - I'm really lacking on the assembly part, but with that depth I'd hardly expect any guaranteed 1-tick instructions.

The Pyra's Cortex A15 cores switched over to an out-of-order architecture with 15 steps for integer and 17-25 steps for float.
 
Well one benefit of ARM over other competing architectures is that in most circumstances you can just count instructions to compare them, since everything other than STM/LDM (and probably a few newer instructions I'm less aware of) takes one tick (apart from branches which you can assume take 5 or so ticks, or whatever your pipeline length is, which is why when you've got an inline conditional where the resulting code is a 4 or less instructions, it's better usually to block it out using a conditional extension like NE or CS - but if you need to loop you're going to have to branch anyway.

Applies more or less to ARM9, but not so much to anything newer.
 
You see that from a code in the kernel ?
I was about to compile as C and see how it goes with gdb.
 
You see that from a code in the kernel ?
I was about to compile as C and see how it goes with gdb.

I call ARM functions from C all the time and yes, this is how it works. But only for the first four parameters. The rest (if there are more) are stored on the stack.
 
You mean for each system call ?

Sorry, I didn't see the context that this was about syscalls, not ordinary C function calls. For ARM Linux EABI the first seven parameters are passed in r0 through r6. I don't know how you pass further parameters, or if any Linux syscalls even have more than 7 parameters..

This is actually documented in the Linux manpages, check out man syscall.
 
Back
Top