bitswap の 16bit-16bit の実装について

lut を使う場合に 4bit x4 で無難に実装しているんだが 1 bit + 5 bit x3 の実装を試してみたが、これがかなり tricky にわりと早くメモリ消費もそこそこらしいというコードができた.

	lea	table+0x80,a0
	moveq	#0x3e,d1
	moveq	#0,d0 ;output q
	add.w	d2,d2 ;input d
#if delta >= 8
	roxr.w	#16-delta,d0
#elif delta >= 1
	roxl.w	#delta+1,d0
#else ;delta == 0
	addx.w	d0,d0
#endif
	move.w	d2,d3
	and.w	d1,d3
	or.w	(-0x80,a0,d3.w),d0
	lsr.w	#5,d2
	move.w	d2,d3
	and.w	d1,d3
	or.w	(-0x40,a0,d3.w),d0
	lsr.w	#5,d2
	and.w	d1,d2
	or.w	(0,a0,d2.w),d0
src 15 to
dest:clocks
0: 112  8: 130
1: 118  9: 128
2: 120 10: 126
3: 122 11: 124
4: 124 12: 122
5: 126 13: 120
6: 128 14: 118
7: 130 15: 116

delta は src bit 15 が dest bit 0 からの移動量ということになり、それらの条件で生成する命令や実行時間がことなってくる.
lut へは (d8,an,IX) の addressing で取り込むのだが、68000 は index に scale をつけられない上に 16 bit 単位アクセスなので、通常は index を左循環1回をやってから右循環を繰り返して index を作成することになる.
ここでは左循環1回ではなく左シフト1回相当の add.w d2,d2 を使って src bit 15 を X に追いやる. X を bit0 にいれる場合は addx d0,d0, bit 1 に入れる場合は roxl.w #2,d0, bit 15 に入れる場合は roxr.w #1,d0 となる.
src bit 15 を片付けると index は都合よくズレているので lsr.w で随時 index 作成となる.

src bit 15 に対する dest bit が 7 とか 8 だと循環回数が 8 回になって遅いが addx が使えるのならとても早くてメモリ消費も悪くないというコード.

lut 3 段は他に試作したコードは下記があり 5*2+6 がバランスがよいだろうということになる.

 i  o step  shift clocks   elemnts bytes
16 16 16        1  42      0x10000 0x20000
16 16 8*2       9  98      0x200   0x400
16 16 4*4      13 142      0x40    0x80
16 16 4*2+8     9 116      0x120   0x240
16 16 5*2+6    11 122      0x80    0x100
16 16 1+5*3  11+n 112..130 0x60    0xc0
16 16 4+6*2    11 126      0x90    0x120