/*
 *	framdrh.c
 *
 *	差分圧縮⇒連長圧縮⇒ハフマン圧縮
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2016 Naoyuki Sawa
 *
 *	* Mon Nov 24 10:36:38 JST 2014 Naoyuki Sawa
 *	- 1st リリース。
 *	- ハフマン圧縮の応用例として、作成しました。
 *	  連続して変化するようなデータを圧縮する際に、ハフマン圧縮だけを単独で使用するよりも圧縮率が良くなります。
 *	  今後、LEDデコーダーで利用することを想定しています。
 *	- 当モジュールで工夫した点は、連長と差分の符号をマージした事です。
 *	  連長と差分は、別々の符号表で圧縮します。(連長と差分の出現値は偏りの傾向が違うので、別々の符号表で圧縮する方が圧縮率が良いと思うから)
 *	  一方、連長と差分の符号並びは分けない方が、次に読み出す符号のビット位置を一つで管理でき、都合が良いです。
 *	  従って、連長と差分の符号が交互に取得できるよう、マージしました。
 *	  確か、一般的な圧縮形式(zipやlzh等)も、そうなっていたと思います。
 *	- 連長圧縮が効かないデータだと、ハフマン圧縮よりも単純に2倍の処理時間がかかります。(連長と差分の復号化を行う必要があるため)
 *	  データの特性によって、圧縮の方式を慎重に選択する必要があります。
 *	* Thu Nov 27 21:49:37 JST 2014 Naoyuki Sawa
 *	- DeltaRunHuffmanDecoder_Decode(),DeltaRunHuffmanDecoder_Init(),DeltaRunHuffmanDecoder_Getc()をアセンブラ化しました。
 *	  DeltaRunHuffmanDecoder_Decode()で、約50KB⇒約64KBの展開を行った時の速度が、約2.237秒⇒約1.487秒に高速化しました。(Clock=48MHz,Code=SRAM,Stack=FRAM)
 *	- まだ、アセンブラ版DeltaRunHuffmanDecoder_Decode(),DeltaRunHuffmanDecoder_Init(),DeltaRunHuffmanDecoder_Getc()の動作確認を、充分に行っていません。	//┐
 *	  引き続き、アセンブラ版DeltaRunHuffmanDecoder_Decode(),DeltaRunHuffmanDecoder_Init(),DeltaRunHuffmanDecoder_Getc()の動作確認を行う予定です。		//※TODO:2014/11/27時点未完了。充分に動作確認したらこのコメントは消せ。
 *	  特に、アセンブラ版DeltaRunHuffmanDecoder_Getc()の動作確認を、重点的に行う必要があります。								//┘
 *	* Tue Sep 06 21:06:46 JST 2016 Naoyuki Sawa
 *	- DeltaRunHuffmanDecoder_Init()が、(int)でアドレス演算を行っていたのを、(intptr_t),及び,(char*)で行うように修正しました。
 *	  DeltaRunHuffmanDecoder_Getc()が、(int)でアドレス演算を行っていたのを、(intptr_t)で行うように修正しました。
 *	  64ビット対応のための準備ですが、32ビットでも(intptr_t),及び,(char*)で行う方が本当は正しいからです。
 *	  とは言え、32ビットではどちらでも同じ結果になるので、既存の32ビットコードには影響有りません。
 */
#include "clip.h"

//[note]
//詳細なコメントは省略した。
//アルゴリズムの説明はcliphfm.c,framhfm.cを参照せよ。

/****************************************************************************
 *	差分圧縮⇒連長圧縮⇒ハフマン圧縮デコーダー
 ****************************************************************************/
#ifndef PIECE
int DeltaRunHuffmanDecoder_Decode(const void* src, void* _dst, int dstBytes) {
	ST_DeltaRunHuffmanDecoder stDeltaRunHuffmanDecoder;
	unsigned char* dst = _dst;
	int value, dstPos = 0;
	DeltaRunHuffmanDecoder_Init(&stDeltaRunHuffmanDecoder, src);	//差分圧縮⇒連長圧縮⇒ハフマン圧縮デコーダーを初期化する。
	while((value = DeltaRunHuffmanDecoder_Getc(&stDeltaRunHuffmanDecoder)) != -1) {	//１バイトデコードする。
		if(dstPos++ < dstBytes) { *dst++ = value; }		//圧縮元データを格納する。
	}
	return dstPos;							//圧縮元データのバイト数を返す。
}
#else //PIECE
//アセンブラ版HuffmanDecoder_Decodeの'工夫した実装'とほぼ同じです。詳細はアセンブラ版HuffmanDecoder_Decodeを参照してください。
int DeltaRunHuffmanDecoder_Decode(const void* src, void* _dst, int dstBytes);
asm("
		.code
		.align		1
		.global		DeltaRunHuffmanDecoder_Decode
DeltaRunHuffmanDecoder_Decode:
		pushn		%r3
		xsub		%sp, %sp, 12				;//%sp  := &stDeltaRunHuffmanDecoder
		ld.w		%r0, %sp				;//%r0  := &stDeltaRunHuffmanDecoder								%spのままでは、callの遅延スロットで既に変化しているので、%r0にもコピーしておく。
		ld.w		%r1, %r13				;//%r1  := dst
		ld.w		%r2, %r14				;//%r2  := dstBytes
		ld.w		%r13, %r12				;//%r13 := src
		xcall.d		DeltaRunHuffmanDecoder_Init		;//DeltaRunHuffmanDecoder_Init(&stDeltaRunHuffmanDecoder, src)
		ld.w		%r12, %r0				;//%r12 :=                     &stDeltaRunHuffmanDecoder			*delay*
		jp.d		DeltaRunHuffmanDecoder_Decode_START	;//goto START
		ld.w		%r3, -1					;//%r3  := dstPos = -1								*delay*		最後のループを抜ける時もプレインクリメントする分と相殺するため(-1)に初期化する。
		;//%sp  := &stDeltaRunHuffmanDecoder
		;//%r0  := &stDeltaRunHuffmanDecoder
		;//%r1  := dst
		;//%r2  := dstBytes
		;//%r3  := dstPos
DeltaRunHuffmanDecoder_Decode_LOOP:					;//do {
		cmp		%r3, %r2				;//  if(dstPos < dstBytes) {									プレインクリメントであるが比較条件を(<=)に変更しないよう注意せよ。(-1)に初期化しているのでプレインクリメント分とは相殺済みである。
		jrge		2
		 ld.b		[%r1]+, %r10				;//    *dst++ = value }
DeltaRunHuffmanDecoder_Decode_START:
		xcall.d		DeltaRunHuffmanDecoder_Getc		;//  %r10 := value = DeltaRunHuffmanDecoder_Getc(&stDeltaRunHuffmanDecoder)
		ld.w		%r12, %r0				;//  %r12 :=                                     &stDeltaRunHuffmanDecoder	*delay*
		cmp		%r10, -1				;//} while(value != -1)
		jrne.d		DeltaRunHuffmanDecoder_Decode_LOOP	;//
		add		%r3, 1					;//  %r3  := dstPos++								*delay*
		ld.w		%r10, %r3				;//%r10 := dstPos
		xadd		%sp, %sp, 12
		popn		%r3
		ret
");
#endif//PIECE
/*--------------------------------------------------------------------------*/
#ifndef PIECE
void DeltaRunHuffmanDecoder_Init(ST_DeltaRunHuffmanDecoder* pDeltaRunHuffmanDecoder, const void* src) {
	const unsigned char* hdr;
	int i, codeLenMask, codeLenCount;
	pDeltaRunHuffmanDecoder->src	= src;			//符号表のアドレスを格納する。
	//連長の符号表,及び,差分の符号表を読み飛ばす。
	hdr = pDeltaRunHuffmanDecoder->src;
	i = 2;
	do {
		codeLenMask = *(*(int**)&hdr)++;
		do {
			if(codeLenMask < 0) {
				codeLenCount = *hdr++ + 1;
				hdr += codeLenCount;
			}
		} while(codeLenMask <<= 1);
//{{2016/09/06変更:DeltaRunHuffmanDecoder_Init()が、(int)でアドレス演算を行っていたのを、(intptr_t),及び,(char*)で行うように修正しました。
//		hdr = (unsigned char*)(((int)hdr + 3) & ~3);	//32bit境界まで進める。
//↓2016/09/06変更:DeltaRunHuffmanDecoder_Init()が、(int)でアドレス演算を行っていたのを、(intptr_t),及び,(char*)で行うように修正しました。
		hdr = (unsigned char*)(((intptr_t)hdr + 3) & ~3);	//32bit境界まで進める。
//}}2016/09/06変更:DeltaRunHuffmanDecoder_Init()が、(int)でアドレス演算を行っていたのを、(intptr_t),及び,(char*)で行うように修正しました。
	} while(--i);
	//構造体を初期化する。
//{{2016/09/06変更:DeltaRunHuffmanDecoder_Init()が、(int)でアドレス演算を行っていたのを、(intptr_t),及び,(char*)で行うように修正しました。
//	pDeltaRunHuffmanDecoder->srcPos	= ((int)hdr - (int)pDeltaRunHuffmanDecoder->src) << 3;
//↓2016/09/06変更:DeltaRunHuffmanDecoder_Init()が、(int)でアドレス演算を行っていたのを、(intptr_t),及び,(char*)で行うように修正しました。
	pDeltaRunHuffmanDecoder->srcPos	= ((char*)hdr - (char*)pDeltaRunHuffmanDecoder->src) << 3;
//}}2016/09/06変更:DeltaRunHuffmanDecoder_Init()が、(int)でアドレス演算を行っていたのを、(intptr_t),及び,(char*)で行うように修正しました。
	pDeltaRunHuffmanDecoder->run	= 0;
	pDeltaRunHuffmanDecoder->delta	= 0;
	pDeltaRunHuffmanDecoder->value	= 0;
}
#else //PIECE
void DeltaRunHuffmanDecoder_Init(ST_DeltaRunHuffmanDecoder* pDeltaRunHuffmanDecoder, const void* src);
asm("
		.code
		.align		1
		.global		DeltaRunHuffmanDecoder_Init
DeltaRunHuffmanDecoder_Init:
		ld.w		[%r12], %r13				;//pDeltaRunHuffmanDecoder->src = src, %r13 := hdr
		ld.w		%r4, 2					;//%r4  := i = 2
DeltaRunHuffmanDecoder_Init_L10:					;//do {
		ld.w		%r5, [%r13]+				;//  %r5  := codeLenMask = *(int*)hdr, %r13 := hdr += 4
DeltaRunHuffmanDecoder_Init_L20:					;//  do {
		add		%r5, %r5				;//    %psr(C) := (codeLenMask < 0), %r5  := codeLenMask <<= 1, %psr(Z) := !codeLenMask	─┐
		jruge		DeltaRunHuffmanDecoder_Init_L30		;//    if(%psr(C)) {────────────┐						　│
		ld.ub		%r6, [%r13]+				;//      %r6  := codeLenCount-1 = *hdr++　　│		//codeLenCount-1 := 0〜255	　│
		adc		%r13, %r6				;//      %r5  := hdr += codeLenCount-1 + 1←┘						　│	ここでは必ず%psr(C)=1であることを利用して、adcを利用して+1する工夫をしました。
		cmp		%r5, 0					;//                                                             %psr(Z) := !codeLenMask	─┤
DeltaRunHuffmanDecoder_Init_L30:					;//    }										　│
		jrne		DeltaRunHuffmanDecoder_Init_L20		;//  } while(codeLenMask)	←────────────────────────────┘
		add		%r13, 3					;//  %r13 := hdr +=  3
	;//	and		%r13, -4				;//  %r13 := hdr &= ~3	─┐
		sub		%r4, 1					;//  %r4  := i--	　│
		jrne.d		DeltaRunHuffmanDecoder_Init_L10		;//} while(i)		　│
		and		%r13, -4				;//  %r13 := hdr &= ~3	←┘									*delay*
		ld.w		%r5, [%r12]+				;//%r5  :=                                            pDeltaRunHuffmanDecoder->src
		sub		%r13, %r5				;//%r13 :=                           ((int)hdr - (int)pDeltaRunHuffmanDecoder->src)
		sla		%r13, 3					;//%r13 :=                           ((int)hdr - (int)pDeltaRunHuffmanDecoder->src) << 3
		ld.w		[%r12]+, %r13				;//pDeltaRunHuffmanDecoder->srcPos = ((int)hdr - (int)pDeltaRunHuffmanDecoder->src) << 3
		ld.w		[%r12]+, %r8				;//pDeltaRunHuffmanDecoder->run = pDeltaRunHuffmanDecoder->delta = pDeltaRunHuffmanDecoder->value = (パディング) = 0
		ret
");
#endif//PIECE
/*--------------------------------------------------------------------------*/
#ifndef PIECE
int DeltaRunHuffmanDecoder_Getc(ST_DeltaRunHuffmanDecoder* pDeltaRunHuffmanDecoder) {
	//残りの連長が有れば…
	if(pDeltaRunHuffmanDecoder->run) {
		pDeltaRunHuffmanDecoder->run--;		//残りの連長を減らす。
	//残りの連長が無ければ…
	} else {
		const unsigned char* hdr = pDeltaRunHuffmanDecoder->src;
		int code, codeLenMask, codeLen, codeTmp1, codeTmp2, codeLenCount;
		//--- 連長を取得する処理 ---
		code = bitarray_msb1st_get(pDeltaRunHuffmanDecoder->src, pDeltaRunHuffmanDecoder->srcPos, 32);
		codeLenMask = *(*(int**)&hdr)++;
		codeLen = codeTmp1 = codeTmp2 = 0;
		do {
			codeTmp1 <<= 1;
			codeTmp2 = (codeTmp2 << 1) | (code < 0);
			code <<= 1;
			codeLen++;
			if(codeLenMask < 0) {
				codeLenCount = *hdr++ + 1;
				hdr      += codeLenCount;
				codeTmp1 += codeLenCount;
				codeTmp2 -= codeTmp1;
				if(codeTmp2 < 0) {
					pDeltaRunHuffmanDecoder->srcPos += codeLen;
					pDeltaRunHuffmanDecoder->run = hdr[codeTmp2];
					goto L_NEXT;	//連長の符号表の残りを読み飛ばす処理へ移行する。
				}
				codeTmp2 += codeTmp1;
			}
		} while(codeLenMask <<= 1);
		return -1;				//連長の展開ストリームが終端ならば、終了とする。
		//連長の符号表の残りを読み飛ばす。
		do {
			if(codeLenMask < 0) {
				codeLenCount = *hdr++ + 1;
				hdr += codeLenCount;
			}
L_NEXT:			;//連長を取得する処理を抜けた時、その回の'codeLenMask<<=1'をまだ行っていないので、ここから開始する。
		} while(codeLenMask <<= 1);
//{{2016/09/06変更:DeltaRunHuffmanDecoder_Getc()が、(int)でアドレス演算を行っていたのを、(intptr_t)で行うように修正しました。
//		hdr = (unsigned char*)(((int)hdr + 3) & ~3);	//32bit境界まで進める。
//↓2016/09/06変更:DeltaRunHuffmanDecoder_Getc()が、(int)でアドレス演算を行っていたのを、(intptr_t)で行うように修正しました。
		hdr = (unsigned char*)(((intptr_t)hdr + 3) & ~3);	//32bit境界まで進める。
//}}2016/09/06変更:DeltaRunHuffmanDecoder_Getc()が、(int)でアドレス演算を行っていたのを、(intptr_t)で行うように修正しました。
		//--- 差分を取得する処理 ---
		code = bitarray_msb1st_get(pDeltaRunHuffmanDecoder->src, pDeltaRunHuffmanDecoder->srcPos, 32);
		codeLenMask = *(*(int**)&hdr)++;
		codeLen = codeTmp1 = codeTmp2 = 0;
		do {
			codeTmp1 <<= 1;
			codeTmp2 = (codeTmp2 << 1) | (code < 0);
			code <<= 1;
			codeLen++;
			if(codeLenMask < 0) {
				codeLenCount = *hdr++ + 1;
				hdr      += codeLenCount;
				codeTmp1 += codeLenCount;
				codeTmp2 -= codeTmp1;
				if(codeTmp2 < 0) {
					pDeltaRunHuffmanDecoder->srcPos += codeLen;
					pDeltaRunHuffmanDecoder->delta = hdr[codeTmp2];
					break;
				}
				codeTmp2 += codeTmp1;
			}
		} while(codeLenMask <<= 1);
		if(!codeLenMask) { DIE(); }		//バグ。連長と差分の展開サイズが合っていない。
	}
	return pDeltaRunHuffmanDecoder->value += pDeltaRunHuffmanDecoder->delta;	//連長の期間も毎回値が変化することに注意せよ。	アセンブラ化する時は、戻り値を8bit符号無し値とする事に注意せよ。
}
#else //PIECE
int DeltaRunHuffmanDecoder_Getc(ST_DeltaRunHuffmanDecoder* pDeltaRunHuffmanDecoder);
asm("
		.code
		.align		1
		.global		DeltaRunHuffmanDecoder_Getc
DeltaRunHuffmanDecoder_Getc:
		add		%r12, 8					;//%r12 :=      &pDeltaRunHuffmanDecoder->run
		ld.ub		%r9, [%r12]				;//%r9  := run = pDeltaRunHuffmanDecoder->run
		sub		%r9, 1					;//%r9  := run--										!INTERLOCK!
		ld.b		[%r12]+, %r9				;//pDeltaRunHuffmanDecoder->run = run, %r12 := &pDeltaRunHuffmanDecoder->delta
		jrge		DeltaRunHuffmanDecoder_Getc_RET		;//if(run >= 0) { goto RET }
		;//{{pushn〜popn区間------------------------------------;//
		;//--- 連長を取得する処理 ---
		;//%r12 := &pDeltaRunHuffmanDecoder->delta
		pushn		%r2
		xsub		%r0, %r12, 9				;//%r0  := pDeltaRunHuffmanDecoder
		ld.w		%r1, [%r0]+				;//%r1  := hdr = src = pDeltaRunHuffmanDecoder->src, %r0  := &pDeltaRunHuffmanDecoder->srcPos
		ld.w		%r2, [%r0]+				;//%r2  := srcPos = pDeltaRunHuffmanDecoder->srcPos, %r0  := &pDeltaRunHuffmanDecoder->run
		ld.w		%r12, %r1				;//%r12 :=                            src
		xld.w		%r14, 32				;//%r14 :=                                         32
		xcall.d		bitarray_msb1st_get			;//%r10 := code = bitarray_msb1st_get(src, srcPos, 32)
		ld.w		%r13, %r2				;//%r13 :=                                 srcPos						*delay*
		;//%r0  := &pDeltaRunHuffmanDecoder->run
		;//%r1  := hdr
		;//%r2  := srcPos
		;//%r10 := code
		ld.w		%r4, [%r1]+				;//%r4  := codeLenMask = *(int*)hdr, %r1  := hdr += 4
		ld.w		%r5, 0					;//%r5  := codeLen  = 0
		ld.w		%r6, 0					;//%r6  := codeTmp1 = 0
		ld.w		%r7, 0					;//%r7  := codeTmp2 = 0
		;//%r0  := &pDeltaRunHuffmanDecoder->run
		;//%r1  := hdr
		;//%r2  := srcPos
		;//%r4  := codeLenMask
		;//%r5  := codeLen
		;//%r6  := codeTmp1
		;//%r7  := codeTmp2
		;//%r10 := code
DeltaRunHuffmanDecoder_Getc_L10:					;//do {
		add		%r10, %r10				;//  %psr(C) :=                           (code < 0), %r10 := code <<= 1
		adc		%r7, %r7				;//  %r7  := codeTmp2 = (codeTmp2 << 1) | (code < 0)
		cmp		%r4, 0					;//  if(codeLenMask < 0) {
		jrge.d		DeltaRunHuffmanDecoder_Getc_L30
		add		%r5, 1					;//  %r5  := codeLen++										*delay*
		ld.ub		%r11, [%r1]+				;//    %r11 := codeLenCount-1 = *hdr++			//codeLenCount-1 := 0〜255
		add		%r11, 1					;//    %r11 := codeLenCount				//codeLenCount   := 1〜256
	;//	add		%r1, %r11				;//    %r1  := hdr      += codeLenCount	─┐
		add		%r6, %r11				;//    %r6  := codeTmp1 += codeLenCount	　│
		sub		%r7, %r6				;//    %r7  := codeTmp2 -= codeTmp1	　│
		jrge.d		DeltaRunHuffmanDecoder_Getc_L20		;//    if(codeTmp2 < 0) {		　│
		add		%r1, %r11				;//    %r1  := hdr      += codeLenCount	←┘							*delay*
		add		%r7, %r1				;//      %r7  :=      &hdr[codeTmp2]
		ld.ub		%r9, [%r7]				;//      %r9  := run = hdr[codeTmp2]
		ld.b		[%r0]+, %r9				;//      pDeltaRunHuffmanDecoder->run = run, %r0  := &pDeltaRunHuffmanDecoder->delta
		jp.d		DeltaRunHuffmanDecoder_Getc_NEXT	;//      goto NEXT
		add		%r2, %r5				;//      %r2  := srcPos += codeLen								*delay*
DeltaRunHuffmanDecoder_Getc_L20:					;//    }
		add		%r7, %r6				;//    %r7  := codeTmp2 += codeTmp1
DeltaRunHuffmanDecoder_Getc_L30:					;//  }
		sla		%r4, 1					;//} while(codeLenMask <<= 1)
		jrne.d		DeltaRunHuffmanDecoder_Getc_L10
		sla		%r6, 1					;//  %r6  := codeTmp1 <<= 1									*delay*
		popn		%r2
		ret.d							;//return -1
		ld.w		%r10, -1				;//												*delay*
		;//連長の符号表の残りを読み飛ばす。
		;//%r0  := &pDeltaRunHuffmanDecoder->delta
		;//%r1  := hdr
		;//%r2  := srcPos
		;//%r4  := codeLenMask
	;//	cmp		%r4, 0					;//do {					─┐
		 jrge		4					;//  if(codeLenMask < 0) {		　│
		  ld.ub		%r9, [%r1]+				;//    %r9  := codeLenCount-1 = *hdr++	　│
		  add		%r9, 1					;//    %r9  := codeLenCount		　│
		  add		%r1, %r9				;//    %r1  := hdr += codeLenCount	　│
DeltaRunHuffmanDecoder_Getc_NEXT:					;//  }					　│
		 sla		%r4, 1					;//  %r4  := codeLenMask <<= 1		　│
		jrne.d		-5					;//} while(codeLenMask)			　│
		cmp		%r4, 0					;//					←┘							*delay*
		add		%r1, 3					;//%r1  := hdr +=  3
		and		%r1, -4					;//%r1  := hdr &= ~3
		;//--- 差分を取得する処理 ---
		;//%r0  := &pDeltaRunHuffmanDecoder->delta
		;//%r1  := hdr
		;//%r2  := srcPos
		xsub		%r9, %r0, 9				;//%r9  := pDeltaRunHuffmanDecoder
		ld.w		%r12, [%r9]				;//%r12 := src = pDeltaRunHuffmanDecoder->src
		xld.w		%r14, 32				;//%r14 :=                                         32
		xcall.d		bitarray_msb1st_get			;//%r10 := code = bitarray_msb1st_get(src, srcPos, 32)
		ld.w		%r13, %r2				;//%r13 :=                                 srcPos						*delay*
		;//%r0  := &pDeltaRunHuffmanDecoder->delta
		;//%r1  := hdr
		;//%r2  := srcPos
		;//%r10 := code
		ld.w		%r4, [%r1]+				;//%r4  := codeLenMask = *(int*)hdr, %r1  := hdr += 4
		ld.w		%r5, 0					;//%r5  := codeLen  = 0
		ld.w		%r6, 0					;//%r6  := codeTmp1 = 0
		ld.w		%r7, 0					;//%r7  := codeTmp2 = 0
		;//%r0  := &pDeltaRunHuffmanDecoder->delta
		;//%r1  := hdr
		;//%r2  := srcPos
		;//%r4  := codeLenMask
		;//%r5  := codeLen
		;//%r6  := codeTmp1
		;//%r7  := codeTmp2
		;//%r10 := code
DeltaRunHuffmanDecoder_Getc_L40:					;//do {
		add		%r10, %r10				;//  %psr(C) :=                           (code < 0), %r10 := code <<= 1
		adc		%r7, %r7				;//  %r7  := codeTmp2 = (codeTmp2 << 1) | (code < 0)
		cmp		%r4, 0					;//  if(codeLenMask < 0) {
		jrge.d		DeltaRunHuffmanDecoder_Getc_L60
		add		%r5, 1					;//  %r5  := codeLen++										*delay*
		ld.ub		%r11, [%r1]+				;//    %r11 := codeLenCount-1 = *hdr++			//codeLenCount-1 := 0〜255
		add		%r11, 1					;//    %r11 := codeLenCount				//codeLenCount   := 1〜256
	;//	add		%r1, %r11				;//    %r1  := hdr      += codeLenCount	─┐
		add		%r6, %r11				;//    %r6  := codeTmp1 += codeLenCount	　│
		sub		%r7, %r6				;//    %r7  := codeTmp2 -= codeTmp1	　│
		jrge.d		DeltaRunHuffmanDecoder_Getc_L50		;//    if(codeTmp2 < 0) {		　│
		add		%r1, %r11				;//    %r1  := hdr      += codeLenCount	←┘							*delay*
		add		%r7, %r1				;//      %r7  :=        &hdr[codeTmp2]
		ld.ub		%r9, [%r7]				;//      %r9  := delta = hdr[codeTmp2]
		ld.b		[%r0], %r9				;//      pDeltaRunHuffmanDecoder->delta = delta
		jp.d		DeltaRunHuffmanDecoder_Getc_BREAK	;//      goto BREAK
		add		%r2, %r5				;//      %r2  := srcPos += codeLen								*delay*
DeltaRunHuffmanDecoder_Getc_L50:					;//    }
		add		%r7, %r6				;//    %r7  := codeTmp2 += codeTmp1
DeltaRunHuffmanDecoder_Getc_L60:					;//  }
		sla		%r4, 1					;//} while(codeLenMask <<= 1)
		jrne.d		DeltaRunHuffmanDecoder_Getc_L40
		sla		%r6, 1					;//  %r6  := codeTmp1 <<= 1									*delay*
		jp		DeltaRunHuffmanDecoder_Getc_DIE
DeltaRunHuffmanDecoder_Getc_BREAK:
		ld.w		%r12, %r0				;//%r12 := &pDeltaRunHuffmanDecoder->delta
		sub		%r0, 5					;//%r0  := &pDeltaRunHuffmanDecoder->srcPos
		ld.w		[%r0], %r2				;//pDeltaRunHuffmanDecoder->srcPos = srcPos
		popn		%r2
		;//}}pushn〜popn区間------------------------------------;//
DeltaRunHuffmanDecoder_Getc_RET:
		;//%r12 := &pDeltaRunHuffmanDecoder->delta
		ld.ub		%r9, [%r12]+				;//%r9  := delta = pDeltaRunHuffmanDecoder->delta, %r12 := &pDeltaRunHuffmanDecoder->value
		ld.ub		%r10, [%r12]				;//%r10 := value = pDeltaRunHuffmanDecoder->value
		add		%r10, %r9				;//%r10 := value += delta									!INTERLOCK!
		ld.b		[%r12], %r10				;//pDeltaRunHuffmanDecoder->value = value
		ret.d							;//return  (unsigned char)value
		ld.ub		%r10, %r10				;//%r10 := (unsigned char)value			//戻り値を8bit符号無し値とする事に注意せよ。	*delay*
");
static void __attribute__((noreturn,unused))/*asmブロックから参照*/ DeltaRunHuffmanDecoder_Getc_DIE() { DIE(); }
#endif//PIECE
