seek(2)のなぞ

mkfileの説明で端折ったが,seek(2)のときに処理を場合わけしている.これは何をしているんだろうか?もう一度,該当部分を引用する.int命令の後なので,戻り値関係だと予想できる."4(PC)"は「PC + 4バイト」ではなく「PC + 4命令」の意味なので,AXが-1でなければ,すぐリターンする.

		case 386
			echo TEXT $i'(SB)', 1, '$0'
			echo MOVL '$'$n, AX
			echo INT '$'64
			if(~ $i seek) {
				echo 'CMPL AX,$-1
				JNE 4(PC)
				MOVL a+0(FP),CX
				MOVL AX,0(CX)
				MOVL AX,4(CX)'
			}
			echo RET

seek(2)のmanは,次のようになっている.

vlong seek(int fd, vlong n, int type)

実は戻り値(に限らず引数の場合もなのだが)にvlongを返すために胡散臭いことをやっているのだ.ちなみに,vlongとは64ビット整数のことである.通常,戻り値はAXで返すが,戻り値の型がレジスタサイズより大きなvlongの場合はどうなるのだろうか?どうも,caller側ではvlong値を格納するアドレスをarg[0]で渡して,callee側は戻り値をarg[0]で指定されたアドレスに書いているようだ.したがって,seekの場合は,本来の第一引数であるfdがarg[1]とずれる.さらに,第二引数のnはvlong型なので,arg[2],arg[3]を使って渡している.話を戻して,スタブルーチンでAXが-1の場合は,arg[0]が指しているアドレスに(vlong)-1を書き込むことを意味している.
Linux/x86でも,llseekが同じ問題にぶつかると思うがどう解決しているのだろう.