ARM での software packed 演算による飽和加算(3)
昨日のやつ、ちゃんと動いてませんでしたorz
どうやら、
EOR r1, r2, r2, LSR #16 ; r1 = r2 ^ (r2 >> 16) AND r1, r1, r7 ; r1 = r1 & 0x7beff7de ADD r0, r0, r1, LSR #1 ; r0 = r0 + (r1 >> 1)
EOR をやると r1 にゴミが残っていて、r7 も上位にゴミがあるため、AND をしても まだゴミが残っていて、しかも ADD の部分で右シフトしているため、16bit目にあるゴミが r0 に入っているようです。
なので、
; r7 = 0x7beff7de ; r8 = 0x08010821 ; r2 = c0 | (c1 << 16) AND r0, r2, r2, LSR #16 ; r0 = r2 & (r2 >> 16) EOR r1, r2, r2, LSL #16 ; r1 = r2 ^ (r2 << 16) AND r1, r7, r1, LSR #16 ; r1 = 0x7beff7de & (r1 >> 16) ADD r0, r0, r1, LSR #1 ; r0 = r0 + (r1 >> 1) AND r0, r0, r8, LSR #1 ; r0 = r0 & (0x08010821 >> 1) ADD r0, r0, r8, LSR #12 ; r0 = r0 + (0x08010821 >> 12) AND r0, r8, r0, LSR #5 ; r0 = 0x08010821 & (r0 >> 5) ADD r0, r7, r0, LSL #16 ; r0 = 0x7beff7de & (r0 << 16) EOR r0, r0, r7 ; r0 = r0 ^ 0x7beff7de ADD r1, r2, r2, LSR #16 ; r1 = r2 + (r2 >> 16) SUB r1, r1, r0, LSR #16 ; r1 = r1 - (r0 >> 16) ORR r0, r1, r0, LSR #16 ; r0 = r1 | (r0 >> 16)
2,3行目だけ変更しています。
このように、最初の EOR の時点では左16ビットで計算して、右シフトしながら AND をしています。
こうすると、ゴミが残らないので成功します。
Windows で全パターンの加算合成を試してみたので大丈夫かと。
……まあ、テストプログラムが間違ってなかったらの話ですが(;´Д`)
ところでこれって、C言語で書くと、
unsigned int r7 = 0x7beff7de; unsigned int r8 = 0x08010821; unsigned int r2 = c0 | (c1 << 16); unsigned int r0; r0 = (((((((((r2 >> 16) & r2) + (((((r2 << 16) ^ r2) >> 16) & r7 ) >> 1)) & (r8 >> 1)) + (r8 >> 12)) >> 5) & r8) << 16) + r7) ^ r7; r0 = (((r2 >> 16) + r2) - (r0 >> 16)) | (r0 >> 16);
こうなるんですけど、可読性皆無っていうか、ほんとに効率の良いコードなのかと疑いたくなりますね。