/*	
 *	clipdlst.c
 *
 *	ユーティリティ：ダブルリンクリスト
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2015 Naoyuki Sawa
 *
 *	* Tue Jan 06 21:26:41 JST 2015 Naoyuki Sawa
 *	- 新規作成。
 *	- 「ユーティリティ：ダブルリンクリスト」を、clipmisc.*⇒clipdlst.*へ分離しました。
 *	  使用頻度は高いので、無駄なリンクを防ぐためと言うよりも、モジュール分けして分り易くするためです。
 *	* Wed Jan 07 00:30:50 JST 2015 Naoyuki Sawa
 *	- InitializeListHead(),IsListEmpty(), RemoveHeadList(), RemoveTailList(),RemoveEntryList(),InsertHeadList(),InsertTailList()をAsm化しました。
 *	  C版:100バイト⇒Asm版:72バイト になりました。28バイト節約できました。
 */
#include "clip.h"

/*****************************************************************************
 *	ユーティリティ：ダブルリンクリスト
 *****************************************************************************/

#ifndef PIECE
void InitializeListHead(LIST_ENTRY* ListHead) {
	ListHead->Flink = ListHead->Blink = ListHead;
}
int IsListEmpty(LIST_ENTRY* ListHead) {
	return ListHead->Flink == ListHead;
}
LIST_ENTRY* RemoveHeadList(LIST_ENTRY* ListHead) {
	LIST_ENTRY* Head = ListHead->Flink;
	RemoveEntryList(Head);
	return Head;
}
LIST_ENTRY* RemoveTailList(LIST_ENTRY* ListHead) {
	LIST_ENTRY* Tail = ListHead->Blink;
	RemoveEntryList(Tail);
	return Tail;
}
void RemoveEntryList(LIST_ENTRY* Entry) {
	LIST_ENTRY* Flink = Entry->Flink;
	LIST_ENTRY* Blink = Entry->Blink;
	Blink->Flink = Flink;
	Flink->Blink = Blink;
}
void InsertHeadList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry) {
	LIST_ENTRY* Head = ListHead->Flink;
	Entry->Flink = Head;
	Entry->Blink = ListHead;
	ListHead->Flink = Head->Blink = Entry;
}
void InsertTailList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry) {
	LIST_ENTRY* Tail = ListHead->Blink;
	Entry->Flink = ListHead;
	Entry->Blink = Tail;
	Tail->Flink = ListHead->Blink = Entry;
}
#else //PIECE
void InitializeListHead(LIST_ENTRY* ListHead);
int IsListEmpty(LIST_ENTRY* ListHead);
LIST_ENTRY* RemoveHeadList(LIST_ENTRY* ListHead);
LIST_ENTRY* RemoveTailList(LIST_ENTRY* ListHead);
void RemoveEntryList(LIST_ENTRY* Entry);
void InsertHeadList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry);
void InsertTailList(LIST_ENTRY* ListHead, LIST_ENTRY* Entry);
asm("
		.code
		.align		1
		.global		InitializeListHead
		.global		IsListEmpty
		.global		RemoveHeadList
		.global		RemoveTailList
		.global		RemoveEntryList
		.global		InsertHeadList
		.global		InsertTailList
		;//-------------------------------------;//
InitializeListHead:
		xld.w		[%r12+4], %r12		;//ListHead->Blink = ListHead
		ld.w		[%r12], %r12		;//ListHead->Flink = ListHead
		ret
		;//-------------------------------------;//
IsListEmpty:
		ld.w		%r10, [%r12]		;//%r10    :=  ListHead->Flink
		cmp		%r10, %r12		;//%psr(Z) := (ListHead->Flink == ListHead)	!INTERLOCK!
		ld.w		%r10, %psr		;//%r10[1] := (ListHead->Flink == ListHead)
		ret.d					;//
		and		%r10, 2			;//return     (ListHead->Flink == ListHead)	*delay*		//C版は非0値として1を返すが、Asm版は非0値として2を返す。非0値に依存しないよう注意せよ。
		;//-------------------------------------;//
RemoveHeadList:
		ld.w		%r12, [%r12]		;//%r12 := Head = ListHead->Flink
		jp		RemoveEntryList		;//return RemoveEntryList(Head)					//Asm版RemoveEntryList()の隠れ戻り値に依存
		;//-------------------------------------;//
RemoveTailList:
		xld.w		%r12, [%r12+4]		;//%r12 := Tail = ListHead->Blink
	;//不要	jp		RemoveEntryList		;//return RemoveEntryList(Tail)					//Asm版RemoveEntryList()の隠れ戻り値に依存
		;//-------------------------------------;//
RemoveEntryList:
	;//{{インターロック回避
	;//	ld.w		%r10, %r12		;//%r10 := Entry
	;//	ld.w		%r11, [%r12]+		;//%r11 := Flink = Entry->Flink
	;//	ld.w		%r12, [%r12]		;//%r12 := Blink = Entry->Blink
	;//	ld.w		[%r12] %r11		;// Blink->Flink = Flink			!INTERLOCK!
	;//	xld.w		[%r11+4], %r12		;// Flink->Blink = Blink
	;//	ret					;//return  Entry						//Asm版RemoveEntryList()の隠れ戻り値 %r10 := Entry
	;//↓インターロック回避
		ld.w		%r10, %r12		;//%r10 := Entry
		ld.w		%r11, [%r12]+		;//%r11 := Flink = Entry->Flink
		ld.w		%r12, [%r12]		;//%r12 := Blink = Entry->Blink
		xld.w		[%r11+4], %r12		;// Flink->Blink = Blink
		ld.w		[%r12] %r11		;// Blink->Flink = Flink
		ret					;//return  Entry						//Asm版RemoveEntryList()の隠れ戻り値 %r10 := Entry
	;//}}インターロック回避
		;//-------------------------------------;//
InsertHeadList:
	;//{{インターロック回避,1命令節約
	;//	ld.w		%r9, [%r12]		;//%r9  :=    Head = ListHead->Flink
	;//	ld.w		[%r13], %r9		;//   Entry->Flink = Head			!INTERLOCK!
	;//	xld.w		[%r13+4], %r12		;//   Entry->Blink = ListHead
	;//	xld.w		[%r9+4], %r13		;//    Head->Blink = Entry
	;//	ld.w		[%r12], %r13		;//ListHead->Flink = Entry
	;//	ret
	;//↓インターロック回避,1命令節約
		ld.w		%r9, [%r12]		;//%r9  :=    Head = ListHead->Flink
		xld.w		[%r9+4], %r13		;//    Head->Blink = Entry
		ld.w		[%r12], %r13		;//ListHead->Flink = Entry
		ld.w		[%r13]+, %r9		;//   Entry->Flink = Head, %r13 := &Entry->Blink
		ld.w		[%r13], %r12		;//   Entry->Blink = ListHead
		ret
	;//}}インターロック回避,1命令節約
		;//-------------------------------------;//
InsertTailList:
	;//{{1命令節約
	;//	xld.w		%r9, [%r12+4]		;//%r9  :=    Tail = ListHead->Blink
	;//	ld.w		[%r13], %r12		;//   Entry->Flink = ListHead
	;//	xld.w		[%r13+4], %r9		;//   Entry->Blink = Tail
	;//	xld.w		[%r12+4], %r13		;//ListHead->Blink = Entry
	;//	ld.w		[%r9], %r13		;//    Tail->Flink = Entry
	;//	ret
	;//↓1命令節約
		ld.w		[%r13], %r12		;//   Entry->Flink = ListHead
		add		%r12, 4			;//%r12 :=          &ListHead->Blink
		ld.w		%r9, [%r12]		;//%r9  :=    Tail = ListHead->Blink
		xld.w		[%r13+4], %r9		;//   Entry->Blink = Tail
		ld.w		[%r12], %r13		;//ListHead->Blink = Entry
		ld.w		[%r9], %r13		;//    Tail->Flink = Entry
		ret
	;//}}1命令節約
");
#endif//PIECE
