I did some tests with gcc compiler. Can you replace divide by 2 operation with right-shift operation?
When you shift negative number to the right, the upper bit is filled with ones. This means that gcc is using arithmetic shift and 2's complement implementation. Looks like you can replace division with shift operation. (signed 16-bit integer)
But, dividing and shifting -1 gives different results. True division is rounded to zero. Bit-shift is truncated down to -1.
Positive numbers behave as expected. No traps here.
Of course there is performance difference between shift and true division:
When you shift negative number to the right, the upper bit is filled with ones. This means that gcc is using arithmetic shift and 2's complement implementation. Looks like you can replace division with shift operation. (signed 16-bit integer)
Code:
decimal: -32768
binary: 1000000000000000
Shift >>1
decimal: -16384
binary: 1100000000000000
Divide by 2
decimal: -16384
binary: 1100000000000000
But, dividing and shifting -1 gives different results. True division is rounded to zero. Bit-shift is truncated down to -1.
Code:
decimal: -1
binary: 1111111111111111
Shift >>1
decimal: -1
binary: 1111111111111111
Divide by 2
decimal: 0
binary: 0000000000000000
Positive numbers behave as expected. No traps here.
Code:
decimal: 32767
binary: 0111111111111111
Shift >>1
decimal: 16383
binary: 0011111111111111
decimal: 32767
binary: 0111111111111111
Divide by 2
decimal: 16383
binary: 0011111111111111
decimal: 1
binary: 0000000000000001
Shift >>1
decimal: 0
binary: 0000000000000000
decimal: 1
binary: 0000000000000001
Divide by 2
decimal: 0
binary: 0000000000000000
Of course there is performance difference between shift and true division:
C:
int16 >>= 1;
000001B2 LDD R24,Y+34 Load indirect with displacement
000001B3 LDD R25,Y+35 Load indirect with displacement
000001B4 ASR R25 Arithmetic shift right
000001B5 ROR R24 Rotate right through carry
000001B6 STD Y+35,R25 Store indirect with displacement
000001B7 STD Y+34,R24 Store indirect with displacement
int16 /= 2;
00000259 LDD R24,Y+34 Load indirect with displacement
0000025A LDD R25,Y+35 Load indirect with displacement
0000025B IN R0,0x3F In from I/O location
0000025C CLI Global Interrupt Disable
0000025D OUT 0x3E,R29 Out to I/O location
0000025E OUT 0x3F,R0 Out to I/O location
0000025F OUT 0x3D,R28 Out to I/O location
00000260 TST R25 Test for Zero or Minus
00000261 BRGE PC+0x02 Branch if greater or equal, signed
00000262 ADIW R24,0x01 Add immediate to word
00000263 ASR R25 Arithmetic shift right
00000264 ROR R24 Rotate right through carry
00000265 STD Y+35,R25 Store indirect with displacement
00000266 STD Y+34,R24 Store indirect with displacement
Last edited: