;//
;//	framshsi.s
;//
;//	可変ビット数シフト関数(アセンブラプログラムのコードサイズ削減用)
;//
;//	CLiP - Common Library for P/ECE
;//	Copyright (C) 2015 Naoyuki Sawa
;//
;//	* Wed Oct 28 21:51:16 JST 2015 Naoyuki Sawa
;//	- 1st リリース。
;//	- __ashlsi3,__ashrsi3,__lshrsi3の関数名は、一般的なgccのサポートライブラリ関数に倣って名付けました。
;//	  □参照資料
;//	  │「C17WB for Interface Manual」(C17WBforInterfaceV100.pdf) p.7-7
;//	  │⇒『7 ライブラリ』⇒『7.2 エミュレーションライブラリ』⇒『7.2.3 整数演算関数』
;//	  □参照資料
;//	  │「GCC online documentation」
;//	  │⇒『4 The GCC low-level runtime library』⇒『4.1 Routines for integer arithmetic』
;//	  │(http://gcc.gnu.org/onlinedocs/gccint/Integer-library-routines.html)
;//	- ただし、gcc33.exeが生成するコードは、これらのサポートライブラリ関数を呼び出しません。
;//	  gcc33.exeが生成するコードは、「xsla %rd,%rs」「xsra %rd,%rs」「xsrl %rd,%rs」拡張命令を生成します。
;//	  gcc33.exeが生成したコードから下記の関数が呼ばれる事は無く、この関数名である事に必然性は有りません。
;//	  あくまでも、わかり易くするために、一般的なgccのサポートライブラリ関数の名前に倣っただけです。
;//	- それではなぜ当モジュールを用意したかと言うと、アセンブラプログラムのコードサイズ削減のためです。	←←←←←■要点■
;//	  「xsla %rd,%rs」「xsra %rd,%rs」「xsrl %rd,%rs」拡張命令は、かなり多くの命令数に展開されます。
;//	  プログラムの多くの箇所で上記の拡張命令を使用すると、個々の箇所で展開されて、容量を消費します。
;//	  __ashlsi3,__ashrsi3,__lshrsi3を呼び出す方が、(レジスタ移動を含めても)コードサイズを削減出来ます。
;//	  実際の所、__ashlsi3,__ashrsi3,__lshrsi3の処理内容は、拡張命令を展開したのとほぼ同じ内容です。
;//	- __ashlsi3,__ashrsi3,__lshrsi3は、最小限のレジスタしか、破壊しません。
;//	  %r9,%r10,%psr以外は、引数である%r12,%r13も含めて、どのレジスタも破壊しません。
;//	  従って、呼び出し側のアセンブラプログラムでは、ほぼ、レジスタ退避を考慮しなくて構いません。
;//	  拡張命令を使用するのと同じ感覚で、これらの関数を呼び出して大丈夫です。
;//	- __ashlsi3,__ashrsi3,__lshrsi3は、アセンブラプログラムから呼び出す事だけを想定しており、C言語プログラムから呼び出す事は想定していません。
;//	  アセンブラプログラムから呼び出す場合は関数宣言は不要なので、__ashlsi3,__ashrsi3,__lshrsi3を関数宣言するヘッダファイルは存在していません。
;//	  もし(テスト等の目的で)C言語プログラムから呼び出す場合は、呼び出し側のC言語プログラムモジュールの中で、以下の関数宣言をおこなって下さい。
;//	  │int __ashlsi3(int a, int b);
;//	  │int __ashrsi3(int a, int b);
;//	  │int __lshrsi3(int a, int b);
;//	- 上の方で、「拡張命令を展開したのとほぼ同じ内容」と書きましたが、実は、少し高速化の工夫をしました。
;//	  ext33.exeが拡張命令を展開すると、ループ部分以降は以下のように展開されます。(準備部分は省略します)
;//	  │cmp  %r9, 8		┐
;//	  │jrle 4		│ループ部分
;//	  │sla  %r10, 8	│
;//	  │jp.d -3		┘
;//	  │sub  %r9, 8		*delay*
;//	  │sla  %r10, %r9
;//	  一方、当モジュールでは、以下のように実装しました。(準備部分は省略します)
;//	  │sub  %r9, 8		┐
;//	  │jrle 3		│ループ部分
;//	  │jp.d -2		┘
;//	  │sla  %r10, 8	*delay*
;//	  │add  %r9, 8
;//	  │sla  %r10, %r9
;//	  全体の命令数は同じですが、当モジュールの実装の方が、ループ部分の命令数が少ないです。
;//	  シフト数が 0〜 8ならば、ext33.exeの展開コードの方が、1命令高速になります。
;//	  シフト数が 9〜16ならば、同じ速度になります。
;//	  シフト数が17〜24ならば、当モジュールの実装の方が、1命令高速になります。
;//	  シフト数が25〜31ならば、当モジュールの実装の方が、2命令高速になります。
;//	  平均すると、当実装の方が、高速に実行出来ると思います。(可変ビット数シフトで17ビット以上が指定される頻度にもよりますが…)
;//	  この高速化テクニックは当モジュールだけでなく、シフト処理を個別に展開しているアセンブラブログラムにも応用出来ると思います。	←←←←←■NOTE■
;//
		.code
		.align		1
		.global		__ashlsi3
		.global		__ashrsi3
		.global		__lshrsi3
		;//---------------------------------------------;//
		;//32ビット算術左シフト x ← a << bビット
		;//[in]
		;//		%r12		a
		;//		%r13		b
		;//[out]
		;//		%r10		x ← a << bビット
		;//		%psr(Z)		x ＝ 0
		;//		%psr(N)		x ＜ 0
		;//[mod]
		;//		%r9
__ashlsi3:
		ld.w		%r10, %r12			;//%r10 := x = a
		xand		%r9, %r13, 31			;//%r9  := b = b & 31
		sub		%r9, 8				;//while((b -= 8) > 0) {
		jrle		3				;//  
		 jp.d		-2				;//  %r10 := x <<= 8
		 sla		%r10, 8				;//}				*delay*
		add		%r9, 8				;//%r9  := b += 8
		ret.d						;//return  x
		sla		%r10, %r9			;//%r10 := x <<= b		*delay*
		;//---------------------------------------------;//
		;//32ビット算術右シフト x ← a >> bビット
		;//[in]
		;//		%r12		a
		;//		%r13		b
		;//[out]
		;//		%r10		x ← a >> bビット
		;//		%psr(Z)		x ＝ 0
		;//		%psr(N)		x ＜ 0
		;//[mod]
		;//		%r9
__ashrsi3:
		ld.w		%r10, %r12			;//%r10 := x = a
		xand		%r9, %r13, 31			;//%r9  := b = b & 31
		sub		%r9, 8				;//while((b -= 8) > 0) {
		jrle		3				;//  
		 jp.d		-2				;//  %r10 := x >>= 8
		 sra		%r10, 8				;//}				*delay*
		add		%r9, 8				;//%r9  := b += 8
		ret.d						;//return  x
		sra		%r10, %r9			;//%r10 := x >>= b		*delay*
		;//---------------------------------------------;//
		;//32ビット論理右シフト x ← a >>> bビット
		;//[in]
		;//		%r12		a
		;//		%r13		b
		;//[out]
		;//		%r10		x ← a >>> bビット
		;//		%psr(Z)		x ＝ 0
		;//		%psr(N)		x ＜ 0
		;//[mod]
		;//		%r9
__lshrsi3:
		ld.w		%r10, %r12			;//%r10 := x = a
		xand		%r9, %r13, 31			;//%r9  := b = b & 31
		sub		%r9, 8				;//while((b -= 8) > 0) {
		jrle		3				;//  
		 jp.d		-2				;//  %r10 := x >>>= 8
		 srl		%r10, 8				;//}				*delay*
		add		%r9, 8				;//%r9  := b += 8
		ret.d						;//return  x
		srl		%r10, %r9			;//%r10 := x >>>= b		*delay*
		;//---------------------------------------------;//
