Been ages since I've been here but the very first thing I read was this post from Seghur. Couldn't let this challenge go, now could I? :-)
I'll cheat a bit by assuming 'a' is either 0x00000000 or 0xffffffff...
; r0 = a
; r1 = b
; r2 = c
and r1,r1,r0
andnot r2,r0
or r0,r1,r2
The way it works is that if 'a' is 0, b will become zero, as b&0 = 0. Likewise, 'c' will then become c&0xffffffff which will become 'c'. The final result is than 0|c which is this case is 'c'. If a is NOT zero, b will become b&0xffffffff and c will become c&0, in which case you'll get c. Results get written back into r0.
Yvo
Game: optimised machine code
-
- XCore Addict
- Posts: 133
- Joined: Tue Dec 15, 2009 10:23 pm
-
- XCore Expert
- Posts: 844
- Joined: Sun Jul 11, 2010 1:31 am
Hi Yvo,
Cheating is of course allowed, if you can get away with it
that is!
If you know that a is -1 if it isn't 0 (like in your case), you
need only _two_ instructions. Same with 1 instead of -1,
which is how you can do the a1==a2 case.
Another question is how can you transform zero/non-zero
into 0/-1? It can be done in two insns, can it be done in
one? (I don't know the answer).
Cheating is of course allowed, if you can get away with it
that is!
If you know that a is -1 if it isn't 0 (like in your case), you
need only _two_ instructions. Same with 1 instead of -1,
which is how you can do the a1==a2 case.
Another question is how can you transform zero/non-zero
into 0/-1? It can be done in two insns, can it be done in
one? (I don't know the answer).
-
- Respected Member
- Posts: 318
- Joined: Tue Dec 15, 2009 12:46 am
I can't beat two instructionssegher wrote:Another question is how can you transform zero/non-zero
into 0/-1? It can be done in two insns, can it be done in
one? (I don't know the answer).
Code: Select all
eq r1, r0, 0
sext r1, 1
Code: Select all
eq r1, r0, 0
neg r1, r1
Code: Select all
// r0 is zero iff it is not negative and it is not strictly positive.
ashr r1, r0, 32
neg r2, r0
ashr r2, r2, 32
or r1, r2, r1
I can see how to use compute the result in 2 additional instructions for the -1 / 0 case, e.g.segher wrote:If you know that a is -1 if it isn't 0 (like in your case), you
need only _two_ instructions. Same with 1 instead of -1,
which is how you can do the a1==a2 case.
Code: Select all
eq tmp1, a1, a2
neg tmp1, tmp1
sub tmp2, b, c
lmul tmp3, d, tmp1, tmp2, c, tmp2
-
- XCore Expert
- Posts: 844
- Joined: Sun Jul 11, 2010 1:31 am
That transforms zero/non-zero to -1/0, not 0/-1. Not thatrichard wrote:I can't beat two instructionssegher wrote:Another question is how can you transform zero/non-zero
into 0/-1? It can be done in two insns, can it be done in
one? (I don't know the answer).Code: Select all
eq r1, r0, 0 sext r1, 1
Code: Select all
eq r1, r0, 0 neg r1, r1
this matters for the case at hand. You can do
Code: Select all
eq r1,r0,0
sub r1,r1,1
You can use clz to get three.Without using eq, bt or bf, the shortest instruction sequence I can come up with is 4 instructions long (can this be improved?):Code: Select all
// r0 is zero iff it is not negative and it is not strictly positive. ashr r1, r0, 32 neg r2, r0 ashr r2, r2, 32 or r1, r2, r1
[/quote]I can see how to use compute the result in 2 additional instructions for the -1 / 0 case, e.g.segher wrote:If you know that a is -1 if it isn't 0 (like in your case), you
need only _two_ instructions. Same with 1 instead of -1,
which is how you can do the a1==a2 case.I can't see how to do it in two instructions in the 1 / 0 case however. Any clues?Code: Select all
eq tmp1, a1, a2 neg tmp1, tmp1 sub tmp2, b, c lmul tmp3, d, tmp1, tmp2, c, tmp2
Cheat a bit: use one of the input regs as output reg. The
problem with lmul is that it has two input addends, as you
noticed :-)
-
- Respected Member
- Posts: 318
- Joined: Tue Dec 15, 2009 12:46 am
Here's my entry for the "Most Evil Code" category. The code computes a ? b : c. On entry a, b, c are expected to be in r0, r1, r2 respectively and at the end the result is stored in r0.
This entry involves self modifying code, but that's not the most evil part. Can you explain how bf instruction affects the result?
Code: Select all
.align 4
nop
ldap r11, .L666
ldw r3, r11[0]
ldc r4, 0xc
xor r4, r3, r4
bf r0, 0
stw r4, r11[0]
.L666:
mov r0, r1
stw r3, r11[0]
-
- XCore Expert
- Posts: 844
- Joined: Sun Jul 11, 2010 1:31 am
Cute! It will misbehave if you want to run it a second
time though. Or when an interrupt happens at the right
(wrong?) spot, but there isn't much you can do about
that I suppose?
time though. Or when an interrupt happens at the right
(wrong?) spot, but there isn't much you can do about
that I suppose?
-
- Respected Member
- Posts: 318
- Joined: Tue Dec 15, 2009 12:46 am
It should work when called for a second time - the code is restored to its original unmodified state by the second stw instruction. Interrupts are a problem - there is a two instruction window (starting at the first stw instruction) where an taking an interrupt would result in the code always returning c regardless of the value of a. You could disable / enable interrupts around this part of the code, but you might still get a debug interrupt.segher wrote:Cute! It will misbehave if you want to run it a second
time though. Or when an interrupt happens at the right
(wrong?) spot, but there isn't much you can do about
that I suppose?
-
- XCore Expert
- Posts: 844
- Joined: Sun Jul 11, 2010 1:31 am
Oh I totally missed that second store :-)
Do you want to make the next challenge? My stash of
neat little tricks is limited...
Do you want to make the next challenge? My stash of
neat little tricks is limited...
-
- XCore Addict
- Posts: 133
- Joined: Tue Dec 15, 2009 10:23 pm
Middle of the night here but this just hit me: You can do it in one instruction (okay, two if you count the eq ), if you assume b and c are stored consecutively in memory with r2 as the base address and a is stored in r0. ( lots of cheating, I know )
eq r0, r0, #0 ; either 0 or 1
ldw r0,r2[r0]
Since the index register gets scaled automatically, this will load either b or c back into r0.
night all!
Yvo
eq r0, r0, #0 ; either 0 or 1
ldw r0,r2[r0]
Since the index register gets scaled automatically, this will load either b or c back into r0.
night all!
Yvo
-
- XCore Expert
- Posts: 844
- Joined: Sun Jul 11, 2010 1:31 am
Nice one :-)