First of all, I'm not sure if solution even exists. I spent more than a couple of hours trying to come up with one, so beware.
The problem:
r1 contains an arbitrary integer, flags are not set according to its value. Set r0 to 1 if r1 is 0x80000000, to 0 otherwise, using only two instructions.
It's easy to do that in 3 instruc开发者_开发知识库tions (there are many ways), however doing it in 2 seems very hard, and may very well be impossible.
something like
SMMUL r0,r1,r1
MOV r0,r0,lsr #30
Here's a partial solution that gives the correct answer in the top bit of r0
, so it is available as a shifter operand (r0 lsr #31
).
; r0 = r1 & -r1
rsb r0, r1, #0
and r0, r0, r1
This works because 0
and 0x80000000
are the only numbers that retain their sign bits when negated. I'm fairly sure an exact solution is impossible.
EDIT: no, it's not impossible. See Martin's answer.
adds r0, r1, #0x80000000 ; if r1 is 0x80000000, r0 will now hold 0
movne r0, #1 ; otherwise, set r0 to 1
This is equivalent to:
unsigned int r0, r1;
r0 = r1 + 0x80000000; // 32 bits, so top bit will be lost on overflow
if (r0 != 0)
{
r0 = 1;
}
Something like:
mov r0,r1,lsr #31
Tough puzzle if one wants to use "fast" instructions. I can't quite come up with a solution, but can offer a couple more 'notions':
; If goal were to have value of zero if $80000000 and something else otherwise: adds r0,r1,r1 ; Overflow only if $80000000 movvc r0,#whatever ; If goal were to have value of $80000000 if $80000000 and zero otherwise subs r0,r1,#0 ; Overflow only if $80000000 movvc r0,#0 ; Or whatever ; If the goal were to have value of $7FFFFFFF if $80000000 and zero otherwise adds r0,r1,r1,asr #31 ; Overflow only if $80000000 movvc r0,#0 ; If carry were known to be set beforehand addcs r0,r1,r1 ; Overflow only if $80000000 (value is 1) movvc r0,#0 ; If register r2 were known to hold #1 adds r0,r1,r1,asr #31 ; If $80000000, MSB and carry set sbc r0,r2,r0,lsr #31
None of those is a perfect solution, but they're interesting.
精彩评论