#
#	gcc33_bugchk.awk
#
#	GNU C Compiler for E0C33 Ver 2.7.2 (Rev 1.5) 最適化バグ検出スクリプト
#
#	* Wed Feb 13 06:00:00 JST 2002 Naoyuki Sawa
#	- 1st リリース。
#

#
#	P/ECE開発環境のgcc33.exeには、符号反転処理の最適化バグがあるようです。
#	バグを再現するソースコード例せ、以下に示します。
#
#	[ソースコード]
#		// (x,y)の、絶対値の、整数部を取得する関数。
#		// (x,y)は、小数部8bitの固定小数表現とする。
#		void xy_abs_num(int* px, int* py) {
#			int x = *px;
#			int y = *py;
#			*px = (x >= 0 ? x : -x) >> 8; // 「*px = abs(x) >> 8;」としても、同じコードが生成されます。
#			*py = (y >= 0 ? y : -y) >> 8; // 「*py = abs(y) >> 8;」としても、同じコードが生成されます。
#		}
#
#	[コンパイル方法]
#		pcc33 -O2 -b -c sample.c
#
#	[生成されるコード]
#		xy_abs_num:
#			xld.w	%r11,[%r13]
#			xld.w	%r10,[%r12]
#			cmp	%r10,0x0
#			xjrge	__L1
#			not	%r10,%r10
#			add	%r10,1
#		__L1:
#			xsra	%r10,8
#			xld.w	[%r12],%r10
#			ld.w	%r10,%r11	;//この行と次の行の間に、「cmp %r10,0x0」が不足しています。
#			xjrge	__L2		;//そもそも、値を%r10に移す必要が無く、無駄があるようです。
#			not	%r10,%r10
#			add	%r10,1
#		__L2:
#			xsra	%r10,8
#			xld.w	[%r13],%r10
#			ret
#
#	メモリからロード、または、関数から取得した複数の値に対して、特定の順番で符号反転を行った場合に発生するようです。
#	正確な発生条件は、まだ判っていません。
#
#	実際には、ごく稀にしか発生しないようで、さほど心配しなくても良さそうです。
#	今回、「タワーリングレスキューもどき」の作成時に、このバグに気付きました。
#	そこで、これまで八年間に作成したCLiPライブラリのコードを検査しましたが、その中には一件も発生していませんでした。
#
#	[スクリプトの使い方]
#		gawk -f gcc33_bugchk.awk *.ps
#
#		gawkは、下記のバージョンを使って、動作確認を行いました。
#		Gnu Awk (gawk) 2.15, patchlevel 4 + multi-byte extension 1.03
#

{
	#// 以下のパターンに一致したら、コンパイラの最適化バクの可能性が有ります。
	#//
	#// line4「 ld.w %rX,%rY」
	#// line3「 xjrge __Label」
	#// line2「 not %rX,%rX」
	#// line1「 add %rX,1」
	#// line0「__Label:」
	#//
	#// ⇒line4とline3の間に、「 cmp %rX,0x0」が不足している可能性が有ります。

	line4 = line3	#// 四行前
	line3 = line2	#// 三行前
	line2 = line1	#// 二行前
	line1 = line0	#// 一行前
	line0 = $0	#// 現在行

	#// line0「__Label:」
	if($1 ~ /^__L[0-9]+:$/) {
		label = $1
		#// line1「 add %rX,1」
		$0 = line1
		if($1 == "add") {
			split($2, a, ",")
			if(a[2] == "1") {
				reg = a[1]
				#// line2「 not %rX,%rX」
				$0 = line2
				if($1 == "not") {
					split($2, a, ",")
					if((a[1] == reg) && (a[2] == reg)) {
						#// line3「 xjrge __Label」
						$0 = line3
						if(($1 == "xjrge") && (($2 ":") == label)) {
							#// line4「 ld.w %rX,%rY」
							$0 = line4
							if($1 == "ld.w") {
								split($2, a, ",")
								if(a[1] == reg) {
									print FILENAME "(" (FNR - 4) ") コンパイラの最適化バグの可能性が有ります。"
								}
							}
						}
					}
				}
			}
		}
	}
}
