Here's a quick test program I wrote in C; compile to assembler to get the result for your specific hardware: Code: void swapbits() { for (int i=0; i<4; i++) { int reg=0, exp=0, reg1; switch (i) { case 0: reg=0xffff0000; exp=0x7fff0001; break; // 1xx0 -> 0xx1 case 1: reg=0xffff0001; exp=0xffff0001; break; // 1xx1 -> 1xx1 case 2: reg=0x7fff0001; exp=0xffff0000; break; // 0xx1 -> 1xx0 case 3: reg=0x7fff0000; exp=0x7fff0000; break; // 0xx0 -> 0xx0 } reg1=reg; if (reg>0 && reg&1 || reg<0 && !(reg&1)) reg ^= 0x80000001; printf("Swap 0x%04x, expect 0x%04x, result 0x%04x, %s\n", reg1, exp, reg, (exp==reg) ? "OK" : "NOK"); } } Most of it is just a testbed for the calculation itself, which is just: Code: if (reg>0 && reg&1 || reg<0 && !(reg&1)) reg ^= 0x80000001;
Here's another expression that doesn't use "if" statements and should execute in constant time regardless of the bit values, unlike the previous one. Execution in constant time is useful for programming embedded systems. With disassembly, as generated by Visual Studio 2008: Code: reg ^= (- ( (reg&0x00000001) ^ ((reg&0x80000000)>>31) )) & 0x80000001; 00413B6B mov eax,dword ptr [reg] 00413B6E and eax,1 00413B71 mov ecx,dword ptr [reg] 00413B74 and ecx,80000000h 00413B7A shr ecx,1Fh 00413B7D xor eax,ecx 00413B7F neg eax 00413B81 and eax,80000001h 00413B86 xor eax,dword ptr [reg] 00413B89 mov dword ptr [reg],eax And here's a hand coded one in 9 pseudocode instructions that uses one register for the two bits, and assumes that <<= shifts the carry flag C into bit 0 and bit 31 into C, and >>= works the same way, AND not only doesn't require C to be set to anything specific but preserves its value (u) throughout: Code: reg1 reg2 C reg2=reg1; axxb axxb ; goal: reg1=bxxa reg1&=0110; 0xx0 u reg1>>=1; u0xx 0 reg2<<=1; xxb0 a reg1<<=1; 0xxa u reg1<<=1; xxau 0 reg2>>=1; 0xxb 0 reg2>>=1; 00xx b reg1>>=1; bxxa u This can be reduced to 7 instructions if two consecutive <<=1's and >>=1's have exactly the same effect as a single <<=2 or >>=2. Note <<= and >>= are NOT equivalent to the C instructions because these shift a zero bit into the register and lose the bit that drops off the end.
And here's one in just six (realised the &=0110 wasn't necessary): Code: reg2=reg1 axxb axxb u reg1<<=1 xxbu a reg2>>=1 aaxx b reg1>>=2 ubxx b reg2<<=1 axxb a reg1<<=1 bxxa u