/*	
 *	framfont.c
 *
 *	高速RAMに転送するモジュール
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2007 Naoyuki Sawa
 *
 *	* Tue Nov 19 12:30:00 JST 2002 Naoyuki Sawa
 *	- 旧clipdobj.cとclipmod.cから、コピー・修正して新規作成しました。
 *	* Sun Dec 8 05:43:00 JST 2002 Naoyuki Sawa
 *	- mod_mix()のループ音バグを修正。
 *	- テンポエフェクト対応。
 *	* Fri Jan 31 21:57:00 JST 2003 Naoyuki Sawa
 *	- new_LCDDrawObject()のPIXEL(p,m)マクロのmask判定部分を改良。
 *	 「(mask >> (m) & 1)」→「(mask & (1 << (m)))」に変更しました。
 *	  約3%高速化(全画面転送時)、コードサイズは20バイト少なくなりました。
 *	  この改良は「ryukの薫製工房」さん(http://www.interq.or.jp/earth/ryuk/)によるものです。
 *	- new_LCDDrawObject()のクリッピング時画面外判定処理を改良。
 *	  これまで、反転なし/ありそれぞれの処理の中で行っていたものを、共通化してまとめました。
 *	  コードサイズが4バイト少なくなりました。
 *	- 以上の変更を行った結果、現時点のコードサイズは0xfe0(4064)バイトです。
 *	* Sat Feb 1 14:08:00 JST 2003 Naoyuki Sawa
 *	- new_LCDDrawObject()にて、残りライン数の取得「y = obj.dh」を共通化、容量節約しました。
 *	- MODドライバを可変チャネル数に対応しました。
 *	* Tue Apr 1 19:00:00 JST 2003 Naoyuki Sawa
 *	- clipfram.cを分割し、このファイルを新設しました。
 *	* Wed Sep 19 16:48:08 JST 2007 Naoyuki Sawa
 *	- 高速化しました。
 *	  これまで使っていた上のコードは、実装を簡単にするために、要クリッピング時にrender_point()を利用していました。
 *	  しかし、render_point()を呼ばない方が高速で、また、レジスタ保存が少ない分コードも減らせることがわかりました。
 *	  そこで、render_point()を呼ばない方法で再実装し、高速化とコードサイズの削減を行いました。
 *	  クリッピング不要時は10%程度高速化、要クリッピング時は3倍近い高速化の効果が得られました。
 *	- ASM版を実装したので、これまで本モジュールに対して適用していた、sedによるmlt.w→mlt.h変換が不要になりました。
 *	  従って、Makefileのframfont.o生成規則を修正しました。
 */
#include "clip.h"

/****************************************************************************
 *	ユーティリティ：フォント
 ****************************************************************************/

#if 0 /* 2007/09/19まで安定して動作していたコードなので、コメントアウトして保存しておくことにします。 */
///* シンプルライブラリのput_1char()内部関数(\usr\PIECE\lib\src\simple\symbol.c)を参考にしました。
// * また、pceFontPut()関数(\usr\PIECE\sysdev\pcekn\font.c)に倣って、ビューポート内/外による場合分けを行いました。
// * フォント描画領域が完全にビューポート内なら、クリッピングを省略し、二倍程度高速に描画できます。
// */
//unsigned short
//render_font(RENDER* render, int x, int y, unsigned short code, int type, int color)
//{
//	SURFACE* surface;
//	unsigned char* vptr;
//	const unsigned char* p;
//	int ofs, w, h, x_min, y_min, x_max, y_max, c;
//
//	/* フォントサイズを求めます。 */
//	type &= 0x7f; /* bit7(改行指示)は無視 */
//	if(type < 0 || 2 < type) /*DIE()*/return 0; /* 無効なフォントタイプ、容量削減のためDIE()しません */
//	w = render_font_size[type][0];
//	h = render_font_size[type][1];
//
//	 /* 半角空白は頻繁に指定されると思うので、描画を省略して高速化します。
//	  * w,hは戻り値に使うので、w,hを取得する前にスキップしないよう注意！
//	  */
//	if(code == ' ') goto SKIP;
//
//	/* フォントアドレスを求めます。 */
//	pceFontSetType(type);
//	p = pceFontGetAdrs(code);
//
//	/* 半角フォント描画… */
//	if((int)p & (1 << 31)) {
//		p = (unsigned char*)((int)p & ~(1 << 31)); /* 半角ビットを下ろす */
//		/* 描画範囲を求めます。 */
//		x_min = x;
//		y_min = y;
//		x_max = x + w;
//		y_max = y + h;
//		/* 完全にビューポート内なら、クリッピング不要です。 */
//		if(render->left <= x_min && x_max <= render->right &&
//		   render->top  <= y_min && y_max <= render->bottom) {
//			surface = render->surface;
//			ofs = surface->w * y + x;
//			vptr = surface->vbuff + ofs;
//			for(y = y_min; y < y_max; y++) {
//				c = *p++;
//				for(x = x_min; x < x_max; x++) {
//					if(c & 0x80) *vptr = color;
//					vptr++;
//					c <<= 1;
//				}
//				vptr += surface->w - w; /* 次の行へ */
//			}
//		/* ビューポートをはみ出していたら、要クリッピング。 */
//		} else {
//			for(y = y_min; y < y_max; y++) {
//				c = *p++;
//				for(x = x_min; x < x_max; x++) {
//					if(c & 0x80) render_point(render, x, y, color);
//					c <<= 1;
//				}
//			}
//		}
//	/* 全角フォント描画… */
//	} else {
//		w *= 2; /* 全角なので二文字分の幅。戻り値に使うのでwを変更する必要あり */
//		/* 描画範囲を求めます。 */
//		x_min = x;
//		y_min = y;
//		x_max = x + w;
//		y_max = y + h;
//		/* 完全にビューポート内なら、クリッピング不要です。 */
//		if(render->left <= x_min && x_max <= render->right &&
//		   render->top  <= y_min && y_max <= render->bottom) {
//			surface = render->surface;
//			ofs = surface->w * y + x;
//			vptr = surface->vbuff + ofs;
//			for(y = y_min; y < y_max; y += 2) { /* 2ラインづつ描く */
//				c = p[0] << 16 | p[1] << 8 | p[2]; /* 3バイトで2ライン分 */
//				p += 3;
//				for(x = x_min; x < x_max; x++) {
//					if(c & 0x800000) *(vptr + 0         ) = color;
//					if(c &    0x800) *(vptr + surface->w) = color;
//					vptr++;
//					c <<= 1;
//				}
//				vptr += surface->w * 2 - w; /* 二行下へ */
//			}
//		/* ビューポートをはみ出していたら、要クリッピング。 */
//		} else {
//			for(y = y_min; y < y_max; y += 2) { /* 2ラインづつ描く */
//				c = p[0] << 16 | p[1] << 8 | p[2]; /* 3バイトで2ライン分 */
//				p += 3;
//				for(x = x_min; x < x_max; x++) {
//					if(c & 0x800000) render_point(render, x, y + 0, color);
//					if(c &    0x800) render_point(render, x, y + 1, color);
//					c <<= 1;
//				}
//			}
//		}
//	}
//SKIP:
//	return h << 8 | w;
//}
#endif
//↓* Wed Sep 19 16:48:08 JST 2007 Naoyuki Sawa
//↓- 高速化しました。
//↓  これまで使っていた上のコードは、実装を簡単にするために、要クリッピング時にrender_point()を利用していました。
//↓  しかし、render_point()を呼ばない方が高速で、また、レジスタ保存が少ない分コードも減らせることがわかりました。
//↓  そこで、render_point()を呼ばない方法で再実装し、高速化とコードサイズの削減を行いました。
//↓  クリッピング不要時は10%程度高速化、要クリッピング時は3倍近い高速化の効果が得られました。
#if 0 /* 2007/09/19作成のC言語版です。 */
unsigned short
render_font(RENDER* render, int x, int y, unsigned short code, int type, int color)
{
	int w;
	int h;
	int xlim;
	int ylim;
	int xmax;
	int ymax;
	int vadd;
	int c;
	SURFACE* surface;
	unsigned char* vptr;
	const unsigned char* p;

	/* フォントサイズを求めます。 */
	type &= 0x7F; /* bit7(改行指示)は無視。bit31-8も無視する仕様(pceFontSetType()に準拠) */
	if(type > 2) /*DIE()*/return 0; /* 無効なフォントタイプ、容量削減のためDIE()しません */
	w = render_font_size[type][0];
	h = render_font_size[type][1];

	 /* 半角空白は頻繁に指定されると思うので、描画を省略して高速化します。
	  * w,hは戻り値に使うので、w,hを取得する前にスキップしないよう注意！
	  */
	if(code != ' ') {
		/* フォントアドレスを求めます。 */
		pceFontSetType(type);
		p = pceFontGetAdrs(code);

		/* 描画開始アドレスを求めます。
		 * 画面外の場合もそのまま計算しておき、描画時に1ピクセルづつ判定します。
		 */
		surface = render->surface;
		vptr = surface->vbuff + surface->w * y + x;
		vadd = surface->w - w; /* 半角左へ戻って1行下へ */

		/* ループカウンタ範囲を求めます。 */
		x -= render->left;
		y -= render->top;
		xlim = render->right - render->left;
		ylim = render->bottom - render->top;
		xmax = x + w;
		ymax = y + h;

		/* 半角フォント描画… */
		if((int)p & (1<<31)) {
			p = (unsigned char*)((int)p & ~(1<<31)); /* 半角ビットを下ろす */

			/* 完全にビューポート内なら、クリッピング不要です。 */
			if((0 <= x) && (xmax <= xlim) &&
			   (0 <= y) && (ymax <= ylim)) {
				do {
					c = *p++;
					do {
						if(c & (1<<7)) {
							*vptr = color;
						}
						c <<= 1;
						vptr++;
					} while(++x < xmax);
					x -= w;
					vptr += vadd; /* 半角左へ戻って1行下へ */
				} while(++y < ymax);
			/* ビューポートをはみ出していたら、要クリッピング。 */
			} else {
				do {
					c = *p++;
					do {
						if(c & (1<<7)) {
							if(((unsigned)x < (unsigned)xlim)) {		/* ((0 <= x) && (x < xlim)) */
								if((unsigned)y < (unsigned)ylim) {	/* ((0 <= y) && (y < ylim)) */
									*vptr = color;
								}
							}
						}
						c <<= 1;
						vptr++;
					} while(++x < xmax);
					x -= w;
					vptr += vadd; /* 半角左へ戻って1行下へ */
				} while(++y < ymax);
			}
		/* 全角フォント描画… */
		} else {
			/* 全角なので二文字分の幅とします。 */
			xmax += w; /* xmax =              x + 半角w * 2 */
			w    *= 2; /* w    =                  半角w * 2 */
			vadd *= 2; /* vadd = surface->w * 2 - 半角w * 2 (全角左へ戻って2行下へ) */

			/* 完全にビューポート内なら、クリッピング不要です。 */
			if((0 <= x) && (xmax <= xlim) &&
			   (0 <= y) && (ymax <= ylim)) {
				do {
					c =          *p++;
					c = (c<<8) | *p++;
					c = (c<<8) | *p++;
					do {
						if(c & (1<<23)) {
							*(vptr + 0         ) = color;
						}
						if(c & (1<<11)) {
							*(vptr + surface->w) = color;
						}
						c <<= 1;
						vptr++;
					} while(++x < xmax);
					x -= w;
					vptr += vadd; /* 全角左へ戻って2行下へ */
				} while((y += 2) < ymax); /* 2ラインづつ描く */
			/* ビューポートをはみ出していたら、要クリッピング。 */
			} else {
				do {
					c =          *p++;
					c = (c<<8) | *p++;
					c = (c<<8) | *p++;
					do {
						if(((unsigned)x < (unsigned)xlim)) {			/* ((0 <= x) && (x < xlim)) */
							if(c & (1<<23)) {
								if((unsigned)y < (unsigned)ylim) {	/* ((0 <= y) && (y < ylim)) */
									*(vptr + 0         ) = color;
								}
							}
							if(c & (1<<11)) {
								y++; /* 忘れないで!! */
								if((unsigned)y < (unsigned)ylim) {	/* ((0 <= y) && (y < ylim)) */
									*(vptr + surface->w) = color;
								}
								y--; /* 忘れないで!! */
							}
						}
						c <<= 1;
						vptr++;
					} while(++x < xmax);
					x -= w;
					vptr += vadd; /* 全角左へ戻って2行下へ */
				} while((y += 2) < ymax); /* 2ラインづつ描く */
			}
		}
	}

	return (h<<8) | w;
}
#else /* 2007/09/19作成のASM版です。C言語版とほぼ同じアルゴリズムですが、一部ASM版特有の高速化を行いました。 */
asm("
	.code
	.align	1
	.global	render_font
render_font:
	pushn	%r3
	ld.w	%r0, %r12			; %r0 = render
	ld.w	%r1, %r13			; %r1 = x
	ld.w	%r2, %r14			; %r2 = y
	ld.uh	%r3, %r15			; %r3 = code
	;// %r0 = render
	;// %r1 = x
	;// %r2 = y
	;// %r3 = code
	;// [%sp+20] = type
	;// [%sp+24] = color
	xld.ub	%r12, [%sp+20]			; %r12 = type     (00000000 00000000 00000000 ?ttttttt)
	add	%r12, %r12			; %r12 = type * 2 (00000000 00000000 0000000? ttttttt0)
	ld.ub	%r12, %r12			; %r12 = type * 2 (00000000 00000000 00000000 ttttttt0)
	xcmp	%r12, 4				; if(type * 2 > 2 * 2) goto render_font_ERR
	xjrgt	render_font_ERR
	ext	render_font_size@ah
	ext	render_font_size@al
	ld.uh	%r10, [%r12]			; %r10 = (h<<8)|w (00000000 00000000 hhhhhhhh wwwwwwww)
	;// %r0 = render
	;// %r1 = x
	;// %r2 = y
	;// %r3 = code
	;// %r10 = (h<<8)|w
	;// %r12 = type*2
	;// [%sp+24] = color
	xcmp	%r3, 0x20			; if(code == ' ') goto render_font_SPC
	xjreq	render_font_SPC
	xld.h	[%sp+20], %r10			; [%sp+20] = w, [%sp+21] = h
	;// %r0 = render
	;// %r1 = x
	;// %r2 = y
	;// %r3 = code
	;// %r10 = (h<<8)|w
	;// %r12 = type*2
	;// [%sp+20] = w
	;// [%sp+21] = h
	;// [%sp+24] = color
	xcall.d	pceFontSetType			; pceFontSetType(type)
	srl	%r12, 1				; *delay* %r12 = type (00000000 00000000 00000000 0ttttttt)
	xcall.d	pceFontGetAdrs			; %r10 = p = pceFontGetAdrs(code) (?ppppppp pppppppp pppppppp pppppppp)
	ld.w	%r12, %r3			; *delay*
	;// %r0 = render
	;// %r1 = x
	;// %r2 = y
	;// %r10 = p
	;// [%sp+20] = w
	;// [%sp+21] = h
	;// [%sp+24] = color
	ld.w	%r3, [%r0]+			; %r3 = surface
	ld.h	%r4, [%r0]+			; %r4 = render->left
	ld.h	%r5, [%r0]+			; %r5 = render->top
	ld.h	%r6, [%r0]+			; %r6 = render->right
	ld.h	%r7, [%r0]			; %r7 = render->bottom
	;// %r1 = x
	;// %r2 = y
	;// %r3 = surface
	;// %r4 = render->left
	;// %r5 = render->top
	;// %r6 = render->right
	;// %r7 = render->bottom
	;// %r10 = p
	;// [%sp+20] = w
	;// [%sp+21] = h
	;// [%sp+24] = color
	xld.w	%r0, [%r3+4]			; %r0 = surface->vbuff
	xld.h	%r3, [%r3+0]			; %r3 = surface->w
	mlt.h	%r3, %r2			; %r0 = vptr = surface->vbuff + surface->w * y + x
	ld.w	%r9, %alr
	add	%r0, %r9
	add	%r0, %r1
	;// %r0 = vptr
	;// %r1 = x
	;// %r2 = y
	;// %r3 = surface->w
	;// %r4 = render->left
	;// %r5 = render->top
	;// %r6 = render->right
	;// %r7 = render->bottom
	;// %r10 = p
	;// [%sp+20] = w
	;// [%sp+21] = h
	;// [%sp+24] = color
	sub	%r1, %r4			; %r1 = x -= render->left
	sub	%r2, %r5			; %r2 = y -= render->top
	sub	%r6, %r4			; %r6 = xlim = render->right - render->left
	sub	%r7, %r5			; %r7 = ylim = render->bottom - render->top
	xld.ub	%r11, [%sp+20]			; %r11 = w
	xld.ub	%r12, [%sp+21]			; %r12 = h
	ld.w	%r4, %r11			; %r4 = w
	ld.w	%r5, %r3			; %r5 = vadd = surface->w - w
	sub	%r5, %r4
	add	%r11, %r1			; %r11 = xmax = x + w
	add	%r12, %r2			; %r12 = ymax = y + h
	xld.ub	%r13, [%sp+24]			; %r13 = color
	;// %r0 = vptr
	;// %r1 = x
	;// %r2 = y
	;// %r3 = surface->w
	;// %r4 = w
	;// %r5 = vadd
	;// %r6 = xlim
	;// %r7 = ylim
	;// %r10 = p
	;// %r11 = xmax
	;// %r12 = ymax
	;// %r13 = color
	;// [%sp+20] = w
	;// [%sp+21] = h
	add	%r10, %r10			; %psr(C) = ?, %r10 = p * 2 (pppppppp pppppppp pppppppp ppppppp0)
	xjruge.d render_font_ZEN		; if(?) goto render_font_ZEN
	srl	%r10, 1				; *delay*      %r10 = p     (0ppppppp pppppppp pppppppp pppppppp)
	;------------ 半角 ------------
	xcmp	%r1, 0				; if(x < 0) goto render_font_HAN_OUT_REPY
	xjrlt	render_font_HAN_OUT_REPY
	cmp	%r11, %r6			; if(xmax > xlim) goto render_font_HAN_OUT_REPY
	xjrgt	render_font_HAN_OUT_REPY
	xcmp	%r2, 0				; if(y < 0) goto render_font_HAN_OUT_REPY
	xjrlt	render_font_HAN_OUT_REPY
	cmp	%r12, %r7			; if(ymax < ylim) goto render_font_HAN_OUT_REPY
	xjrgt	render_font_HAN_OUT_REPY
	;--- 半角(クリッピング無し) ---
render_font_HAN_IN_REPY:			; do {
	ld.ub	%r14, [%r10]+			;   c = *p++
	swap	%r14, %r14			;   c = abcdefgh 00000000 00000000 00000000
render_font_HAN_IN_REPX:			;   do {
	add	%r14, %r14			;       %psr(C) = a, c = bcdefgh0 00000000 00000000 00000000
	jruge.d	3				;       if(a)
	 add	%r1, 1				; 	| *delay* <-----+
	 ld.b	[%r0], %r13			;       | *vptr = color |
;//	xadd	%r1, %r1, 1			;       ----------------+
	cmp	%r1, %r11			; 
	xjrlt.d	render_font_HAN_IN_REPX		;   } while(++x < xmax)
	add	%r0, 1				;   *delay* vptr++
	sub	%r1, %r4			;   x -= w
	xadd	%r2, %r2, 1			; 
	cmp	%r2, %r12			; 
	xjrlt.d	render_font_HAN_IN_REPY		; } while(++y < ymax)
	add	%r0, %r5			; *delay* vptr += vadd
	xjp	render_font_RET
	;--- 半角(クリッピング有り) ---
render_font_HAN_OUT_REPY:			; do {
	ld.ub	%r14, [%r10]+			;   c = *p++
	swap	%r14, %r14			;   c = abcdefgh 00000000 00000000 00000000
render_font_HAN_OUT_REPX:			;   do {
	add	%r14, %r14			;       %psr(C) = a, c = bcdefgh0 00000000 00000000 00000000
	jruge	6				;       if(a)
	 cmp	%r1, %r6			;       | 
	 jruge	4				;       | if((unsigned)x < (unsigned)xlim)
	  cmp	%r2, %r7			;       | | 
	  jruge	2				;       | | if((unsigned)y < (unsigned)ylim)
	   ld.b	[%r0], %r13			;       | | | *vptr = color
	xadd	%r1, %r1, 1			; 
	cmp	%r1, %r11			; 
	xjrlt.d	render_font_HAN_OUT_REPX	;   } while(++x < xmax)
	add	%r0, 1				;   *delay* vptr++
	sub	%r1, %r4			;   x -= w
	xadd	%r2, %r2, 1			; 
	cmp	%r2, %r12			; 
	xjrlt.d	render_font_HAN_OUT_REPY	; } while(++y < ymax)
	add	%r0, %r5			; *delay* vptr += vadd
	xjp	render_font_RET
	;------------ 全角 ------------
render_font_ZEN:
	add	%r11, %r4			; xmax += w
	add	%r4, %r4			; w    *= 2
	add	%r5, %r5			; vadd *= 2
	xld.b	[%sp+20], %r4			; [%sp+20] = w * 2
	xcmp	%r1, 0				; if(x < 0) goto render_font_ZEN_OUT_REPY
	xjrlt	render_font_ZEN_OUT_REPY
	cmp	%r11, %r6			; if(xmax > xlim) goto render_font_ZEN_OUT_REPY
	xjrgt	render_font_ZEN_OUT_REPY
	xcmp	%r2, 0				; if(y < 0) goto render_font_ZEN_OUT_REPY
	xjrlt	render_font_ZEN_OUT_REPY
	cmp	%r12, %r7			; if(ymax < ylim) goto render_font_ZEN_OUT_REPY
	xjrgt	render_font_ZEN_OUT_REPY
	;--- 全角(クリッピング無し) ---
render_font_ZEN_IN_REPY:			; do {
	ld.ub	%r14, [%r10]+			;   c =          *p++ (00000000 00000000 00000000 abcdefgh)
	ld.ub	%r9, [%r10]+			; 
	xsll	%r14, 8				; 
	or	%r14, %r9			;   c = (c<<8) | *p++ (00000000 00000000 abcdefgh ij00klmn)
	ld.ub	%r9, [%r10]+			; 
	xsll	%r14, 8				; 
	or	%r14, %r9			;   c = (c<<8) | *p++ (00000000 abcdefgh ij00klmn opqrst00)
;//{{高速化
;//render_font_ZEN_IN_REPX:			;   do {
;//	xand	%r9, %r14, 0x800000		; 
;//	jreq	2				;     if(c & (1<<23))
;//	 ld.b	[%r0], %r13			;     | *(vptr + 0         ) = color
;//	xand	%r9, %r14, 0x800		; 
;//	jreq	4				;     if(c & (1<<11))
;//	 add	%r0, %r3			;     |
;//	 ld.b	[%r0], %r13			;     | *(vptr + surface->w) = color
;//	 sub	%r0, %r3			;     |
;//	add	%r14, %r14			;     c <<= 1
;//	xadd	%r1, %r1, 1			; 
;//↓高速化
	xsll	%r14, 8				;   %r14 = c1 (abcdefgh ij00klmn opqrst00 00000000)
	ld.w	%r15, %r14			;   %r15 = c2 (klmnopqr st000000 00000000 00000000)
	xsll	%r15, 12
render_font_ZEN_IN_REPX:			;   do {
	add	%r14, %r14			;     %psr(C) = a, c1 = bcdefghi j00klmno pqrst000 00000000
	jruge.d	3				;     if(a)
	 add	%r15, %r15			;     | *delay* %psr(C) = k, c2 = lmnopqrs t0000000 00000000 00000000
	 ld.b	[%r0], %r13			;     | *(vptr + 0         ) = color
	jruge.d	5				;     if(k)
	 add	%r1, 1				;     | *delay*
	 add	%r0, %r3			;     |
	 ld.b	[%r0], %r13			;     | *(vptr + surface->w) = color
	 sub	%r0, %r3			;     |
;//}}高速化
	cmp	%r1, %r11			; 
	xjrlt.d	render_font_ZEN_IN_REPX		;   } while(++x < xmax)
	add	%r0, 1				;   *delay* vptr++
	sub	%r1, %r4			;   x -= w
	xadd	%r2, %r2, 2			; 
	cmp	%r2, %r12			; 
	xjrlt.d	render_font_ZEN_IN_REPY		; } while((y += 2) < ymax)
	add	%r0, %r5			; *delay* vptr += vadd
	xjp	render_font_RET
	;--- 全角(クリッピング有り) ---
render_font_ZEN_OUT_REPY:			; do {
	ld.ub	%r14, [%r10]+			;   c =          *p++ (00000000 00000000 00000000 abcdefgh)
	ld.ub	%r9, [%r10]+			; 
	xsll	%r14, 8				; 
	or	%r14, %r9			;   c = (c<<8) | *p++ (00000000 00000000 abcdefgh ij00klmn)
	ld.ub	%r9, [%r10]+			; 
	xsll	%r14, 8				; 
	or	%r14, %r9			;   c = (c<<8) | *p++ (00000000 abcdefgh ij00klmn opqrst00)
render_font_ZEN_OUT_REPX:			;   do {
	cmp	%r1, %r6			; 
	xjruge.d render_font_ZEN_OUT_SKIP	;     if((unsigned)x < (unsigned)xlim) {
	add	%r1, 1				;     *delay* <----------------------------+
	xand	%r9, %r14, 0x800000		;                                          |
	jreq	4				;       if(c & (1<<23))                    |
	 cmp	%r2, %r7			;       |                                  |
	 jruge	2				;       | if((unsigned)y < (unsigned)ylim) |
	  ld.b	[%r0], %r13			;       |   *(vptr + 0         ) = color   |
	xand	%r9, %r14, 0x800		;                                          |
	jreq	8				;       if(c & (1<<11))                    |
	 add	%r2, 1				;       | y++                              |
	 cmp	%r2, %r7			;       |                                  |
	 jruge.d 5				;       | if((unsigned)y < (unsigned)ylim) |
	  sub	%r2, 1				;       | | *delay* y--                    |
	  add	%r0, %r3			;       | |                                |
	  ld.b	[%r0], %r13			;       | | *(vptr + surface->w) = color   |
	  sub	%r0, %r3			;       | |                                |
render_font_ZEN_OUT_SKIP:			;     }                                    |
	add	%r14, %r14			;     c <<= 1                              |
;//	xadd	%r1, %r1, 1			;     -------------------------------------+
	cmp	%r1, %r11			; 
	xjrlt.d	render_font_ZEN_OUT_REPX	;   } while(++x < xmax)
	add	%r0, 1				;   *delay* vptr++
	sub	%r1, %r4			;   x -= w
	xadd	%r2, %r2, 2			; 
	cmp	%r2, %r12			; 
	xjrlt.d	render_font_ZEN_OUT_REPY	; } while((y += 2) < ymax)
	add	%r0, %r5			; *delay* vptr += vadd
	;----------------
render_font_RET:
	xld.uh	%r10, [%sp+20]			; %r10 = (h<<8)|w
render_font_SPC:
	popn	%r3
	ret
render_font_ERR:
	xjp.d	render_font_SPC
	ld.w	%r10, 0				; *delay*
");
#endif

